@@ -2296,81 +2296,91 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
22962296 return ret ;
22972297}
22982298
2299- static int btrfs_setattr (struct dentry * dentry , struct iattr * attr )
2299+ int btrfs_cont_expand (struct inode * inode , loff_t size )
23002300{
2301- struct inode * inode = dentry -> d_inode ;
2301+ struct btrfs_trans_handle * trans ;
2302+ struct btrfs_root * root = BTRFS_I (inode )-> root ;
2303+ struct extent_io_tree * io_tree = & BTRFS_I (inode )-> io_tree ;
2304+ struct extent_map * em ;
2305+ u64 mask = root -> sectorsize - 1 ;
2306+ u64 hole_start = (inode -> i_size + mask ) & ~mask ;
2307+ u64 block_end = (size + mask ) & ~mask ;
2308+ u64 last_byte ;
2309+ u64 cur_offset ;
2310+ u64 hole_size ;
23022311 int err ;
23032312
2304- err = inode_change_ok (inode , attr );
2313+ if (size <= hole_start )
2314+ return 0 ;
2315+
2316+ err = btrfs_check_free_space (root , 1 , 0 );
23052317 if (err )
23062318 return err ;
23072319
2308- if (S_ISREG (inode -> i_mode ) &&
2309- attr -> ia_valid & ATTR_SIZE && attr -> ia_size > inode -> i_size ) {
2310- struct btrfs_trans_handle * trans ;
2311- struct btrfs_root * root = BTRFS_I (inode )-> root ;
2312- struct extent_io_tree * io_tree = & BTRFS_I (inode )-> io_tree ;
2320+ btrfs_truncate_page (inode -> i_mapping , inode -> i_size );
23132321
2314- u64 mask = root -> sectorsize - 1 ;
2315- u64 hole_start = (inode -> i_size + mask ) & ~mask ;
2316- u64 block_end = (attr -> ia_size + mask ) & ~mask ;
2317- u64 hole_size ;
2318- u64 alloc_hint = 0 ;
2322+ while (1 ) {
2323+ struct btrfs_ordered_extent * ordered ;
2324+ btrfs_wait_ordered_range (inode , hole_start ,
2325+ block_end - hole_start );
2326+ lock_extent (io_tree , hole_start , block_end - 1 , GFP_NOFS );
2327+ ordered = btrfs_lookup_ordered_extent (inode , hole_start );
2328+ if (!ordered )
2329+ break ;
2330+ unlock_extent (io_tree , hole_start , block_end - 1 , GFP_NOFS );
2331+ btrfs_put_ordered_extent (ordered );
2332+ }
23192333
2320- if ( attr -> ia_size <= hole_start )
2321- goto out ;
2334+ trans = btrfs_start_transaction ( root , 1 );
2335+ btrfs_set_trans_block_group ( trans , inode ) ;
23222336
2323- err = btrfs_check_free_space (root , 1 , 0 );
2324- if (err )
2325- goto fail ;
2337+ cur_offset = hole_start ;
2338+ while (1 ) {
2339+ em = btrfs_get_extent (inode , NULL , 0 , cur_offset ,
2340+ block_end - cur_offset , 0 );
2341+ BUG_ON (IS_ERR (em ) || !em );
2342+ last_byte = min (extent_map_end (em ), block_end );
2343+ last_byte = (last_byte + mask ) & ~mask ;
2344+ if (test_bit (EXTENT_FLAG_VACANCY , & em -> flags )) {
2345+ hole_size = last_byte - cur_offset ;
2346+ err = btrfs_insert_file_extent (trans , root ,
2347+ inode -> i_ino , cur_offset , 0 ,
2348+ 0 , hole_size , 0 , hole_size ,
2349+ 0 , 0 , 0 );
2350+ btrfs_drop_extent_cache (inode , hole_start ,
2351+ last_byte - 1 , 0 );
2352+ }
2353+ free_extent_map (em );
2354+ cur_offset = last_byte ;
2355+ if (err || cur_offset >= block_end )
2356+ break ;
2357+ }
23262358
2327- btrfs_truncate_page (inode -> i_mapping , inode -> i_size );
2359+ btrfs_end_transaction (trans , root );
2360+ unlock_extent (io_tree , hole_start , block_end - 1 , GFP_NOFS );
2361+ return err ;
2362+ }
23282363
2329- hole_size = block_end - hole_start ;
2330- while (1 ) {
2331- struct btrfs_ordered_extent * ordered ;
2332- btrfs_wait_ordered_range (inode , hole_start , hole_size );
2333-
2334- lock_extent (io_tree , hole_start , block_end - 1 , GFP_NOFS );
2335- ordered = btrfs_lookup_ordered_extent (inode , hole_start );
2336- if (ordered ) {
2337- unlock_extent (io_tree , hole_start ,
2338- block_end - 1 , GFP_NOFS );
2339- btrfs_put_ordered_extent (ordered );
2340- } else {
2341- break ;
2342- }
2343- }
2364+ static int btrfs_setattr (struct dentry * dentry , struct iattr * attr )
2365+ {
2366+ struct inode * inode = dentry -> d_inode ;
2367+ int err ;
23442368
2345- trans = btrfs_start_transaction (root , 1 );
2346- btrfs_set_trans_block_group (trans , inode );
2347- mutex_lock (& BTRFS_I (inode )-> extent_mutex );
2348- err = btrfs_drop_extents (trans , root , inode ,
2349- hole_start , block_end , hole_start ,
2350- & alloc_hint );
2369+ err = inode_change_ok (inode , attr );
2370+ if (err )
2371+ return err ;
23512372
2352- if (alloc_hint != EXTENT_MAP_INLINE ) {
2353- err = btrfs_insert_file_extent (trans , root ,
2354- inode -> i_ino ,
2355- hole_start , 0 , 0 ,
2356- hole_size , 0 , hole_size ,
2357- 0 , 0 , 0 );
2358- btrfs_drop_extent_cache (inode , hole_start ,
2359- (u64 )- 1 , 0 );
2360- btrfs_check_file (root , inode );
2361- }
2362- mutex_unlock (& BTRFS_I (inode )-> extent_mutex );
2363- btrfs_end_transaction (trans , root );
2364- unlock_extent (io_tree , hole_start , block_end - 1 , GFP_NOFS );
2373+ if (S_ISREG (inode -> i_mode ) &&
2374+ attr -> ia_valid & ATTR_SIZE && attr -> ia_size > inode -> i_size ) {
2375+ err = btrfs_cont_expand (inode , attr -> ia_size );
23652376 if (err )
23662377 return err ;
23672378 }
2368- out :
2379+
23692380 err = inode_setattr (inode , attr );
23702381
23712382 if (!err && ((attr -> ia_valid & ATTR_MODE )))
23722383 err = btrfs_acl_chmod (inode );
2373- fail :
23742384 return err ;
23752385}
23762386
@@ -3456,27 +3466,44 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
34563466 if (found_type == BTRFS_FILE_EXTENT_REG ) {
34573467 extent_end = extent_start +
34583468 btrfs_file_extent_num_bytes (leaf , item );
3459- err = 0 ;
3460- if (start < extent_start || start >= extent_end ) {
3461- em -> start = start ;
3462- if (start < extent_start ) {
3463- if (start + len <= extent_start )
3464- goto not_found ;
3465- em -> len = extent_end - extent_start ;
3466- } else {
3467- em -> len = len ;
3469+ } else if (found_type == BTRFS_FILE_EXTENT_INLINE ) {
3470+ size_t size ;
3471+ size = btrfs_file_extent_inline_len (leaf , item );
3472+ extent_end = (extent_start + size + root -> sectorsize - 1 ) &
3473+ ~((u64 )root -> sectorsize - 1 );
3474+ }
3475+
3476+ if (start >= extent_end ) {
3477+ path -> slots [0 ]++ ;
3478+ if (path -> slots [0 ] >= btrfs_header_nritems (leaf )) {
3479+ ret = btrfs_next_leaf (root , path );
3480+ if (ret < 0 ) {
3481+ err = ret ;
3482+ goto out ;
34683483 }
3469- goto not_found_em ;
3484+ if (ret > 0 )
3485+ goto not_found ;
3486+ leaf = path -> nodes [0 ];
34703487 }
3488+ btrfs_item_key_to_cpu (leaf , & found_key , path -> slots [0 ]);
3489+ if (found_key .objectid != objectid ||
3490+ found_key .type != BTRFS_EXTENT_DATA_KEY )
3491+ goto not_found ;
3492+ if (start + len <= found_key .offset )
3493+ goto not_found ;
3494+ em -> start = start ;
3495+ em -> len = found_key .offset - start ;
3496+ goto not_found_em ;
3497+ }
3498+
3499+ if (found_type == BTRFS_FILE_EXTENT_REG ) {
3500+ em -> start = extent_start ;
3501+ em -> len = extent_end - extent_start ;
34713502 bytenr = btrfs_file_extent_disk_bytenr (leaf , item );
34723503 if (bytenr == 0 ) {
3473- em -> start = extent_start ;
3474- em -> len = extent_end - extent_start ;
34753504 em -> block_start = EXTENT_MAP_HOLE ;
34763505 goto insert ;
34773506 }
3478- em -> start = extent_start ;
3479- em -> len = extent_end - extent_start ;
34803507 if (compressed ) {
34813508 set_bit (EXTENT_FLAG_COMPRESSED , & em -> flags );
34823509 em -> block_start = bytenr ;
@@ -3489,38 +3516,21 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
34893516 }
34903517 goto insert ;
34913518 } else if (found_type == BTRFS_FILE_EXTENT_INLINE ) {
3492- u64 page_start ;
34933519 unsigned long ptr ;
34943520 char * map ;
34953521 size_t size ;
34963522 size_t extent_offset ;
34973523 size_t copy_size ;
34983524
3499- size = btrfs_file_extent_inline_len (leaf , item );
3500- extent_end = (extent_start + size + root -> sectorsize - 1 ) &
3501- ~((u64 )root -> sectorsize - 1 );
3502- if (start < extent_start || start >= extent_end ) {
3503- em -> start = start ;
3504- if (start < extent_start ) {
3505- if (start + len <= extent_start )
3506- goto not_found ;
3507- em -> len = extent_end - extent_start ;
3508- } else {
3509- em -> len = len ;
3510- }
3511- goto not_found_em ;
3512- }
35133525 em -> block_start = EXTENT_MAP_INLINE ;
3514-
35153526 if (!page || create ) {
35163527 em -> start = extent_start ;
3517- em -> len = (size + root -> sectorsize - 1 ) &
3518- ~((u64 )root -> sectorsize - 1 );
3528+ em -> len = extent_end - extent_start ;
35193529 goto out ;
35203530 }
35213531
3522- page_start = page_offset ( page ) + pg_offset ;
3523- extent_offset = page_start - extent_start ;
3532+ size = btrfs_file_extent_inline_len ( leaf , item ) ;
3533+ extent_offset = page_offset ( page ) + pg_offset - extent_start ;
35243534 copy_size = min_t (u64 , PAGE_CACHE_SIZE - pg_offset ,
35253535 size - extent_offset );
35263536 em -> start = extent_start + extent_offset ;
@@ -3570,6 +3580,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
35703580 em -> len = len ;
35713581not_found_em :
35723582 em -> block_start = EXTENT_MAP_HOLE ;
3583+ set_bit (EXTENT_FLAG_VACANCY , & em -> flags );
35733584insert :
35743585 btrfs_release_path (root , path );
35753586 if (em -> start > start || extent_map_end (em ) <= start ) {
0 commit comments