@@ -2296,81 +2296,91 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
2296
2296
return ret ;
2297
2297
}
2298
2298
2299
- static int btrfs_setattr (struct dentry * dentry , struct iattr * attr )
2299
+ int btrfs_cont_expand (struct inode * inode , loff_t size )
2300
2300
{
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 ;
2302
2311
int err ;
2303
2312
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 );
2305
2317
if (err )
2306
2318
return err ;
2307
2319
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 );
2313
2321
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
+ }
2319
2333
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 ) ;
2322
2336
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
+ }
2326
2358
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
+ }
2328
2363
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 ;
2344
2368
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 ;
2351
2372
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 );
2365
2376
if (err )
2366
2377
return err ;
2367
2378
}
2368
- out :
2379
+
2369
2380
err = inode_setattr (inode , attr );
2370
2381
2371
2382
if (!err && ((attr -> ia_valid & ATTR_MODE )))
2372
2383
err = btrfs_acl_chmod (inode );
2373
- fail :
2374
2384
return err ;
2375
2385
}
2376
2386
@@ -3456,27 +3466,44 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
3456
3466
if (found_type == BTRFS_FILE_EXTENT_REG ) {
3457
3467
extent_end = extent_start +
3458
3468
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 ;
3468
3483
}
3469
- goto not_found_em ;
3484
+ if (ret > 0 )
3485
+ goto not_found ;
3486
+ leaf = path -> nodes [0 ];
3470
3487
}
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 ;
3471
3502
bytenr = btrfs_file_extent_disk_bytenr (leaf , item );
3472
3503
if (bytenr == 0 ) {
3473
- em -> start = extent_start ;
3474
- em -> len = extent_end - extent_start ;
3475
3504
em -> block_start = EXTENT_MAP_HOLE ;
3476
3505
goto insert ;
3477
3506
}
3478
- em -> start = extent_start ;
3479
- em -> len = extent_end - extent_start ;
3480
3507
if (compressed ) {
3481
3508
set_bit (EXTENT_FLAG_COMPRESSED , & em -> flags );
3482
3509
em -> block_start = bytenr ;
@@ -3489,38 +3516,21 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
3489
3516
}
3490
3517
goto insert ;
3491
3518
} else if (found_type == BTRFS_FILE_EXTENT_INLINE ) {
3492
- u64 page_start ;
3493
3519
unsigned long ptr ;
3494
3520
char * map ;
3495
3521
size_t size ;
3496
3522
size_t extent_offset ;
3497
3523
size_t copy_size ;
3498
3524
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
- }
3513
3525
em -> block_start = EXTENT_MAP_INLINE ;
3514
-
3515
3526
if (!page || create ) {
3516
3527
em -> start = extent_start ;
3517
- em -> len = (size + root -> sectorsize - 1 ) &
3518
- ~((u64 )root -> sectorsize - 1 );
3528
+ em -> len = extent_end - extent_start ;
3519
3529
goto out ;
3520
3530
}
3521
3531
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 ;
3524
3534
copy_size = min_t (u64 , PAGE_CACHE_SIZE - pg_offset ,
3525
3535
size - extent_offset );
3526
3536
em -> start = extent_start + extent_offset ;
@@ -3570,6 +3580,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
3570
3580
em -> len = len ;
3571
3581
not_found_em :
3572
3582
em -> block_start = EXTENT_MAP_HOLE ;
3583
+ set_bit (EXTENT_FLAG_VACANCY , & em -> flags );
3573
3584
insert :
3574
3585
btrfs_release_path (root , path );
3575
3586
if (em -> start > start || extent_map_end (em ) <= start ) {
0 commit comments