aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/extent-tree.c28
-rw-r--r--fs/btrfs/extent_io.c6
-rw-r--r--fs/btrfs/file.c31
-rw-r--r--fs/btrfs/inode.c10
4 files changed, 43 insertions, 32 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index fada9c22a021..535cee47fcfb 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3379,11 +3379,13 @@ static int noinline relocate_data_extent(struct inode *reloc_inode,
3379 struct btrfs_root *root = BTRFS_I(reloc_inode)->root; 3379 struct btrfs_root *root = BTRFS_I(reloc_inode)->root;
3380 struct extent_map_tree *em_tree = &BTRFS_I(reloc_inode)->extent_tree; 3380 struct extent_map_tree *em_tree = &BTRFS_I(reloc_inode)->extent_tree;
3381 struct extent_map *em; 3381 struct extent_map *em;
3382 u64 start = extent_key->objectid - offset;
3383 u64 end = start + extent_key->offset - 1;
3382 3384
3383 em = alloc_extent_map(GFP_NOFS); 3385 em = alloc_extent_map(GFP_NOFS);
3384 BUG_ON(!em || IS_ERR(em)); 3386 BUG_ON(!em || IS_ERR(em));
3385 3387
3386 em->start = extent_key->objectid - offset; 3388 em->start = start;
3387 em->len = extent_key->offset; 3389 em->len = extent_key->offset;
3388 em->block_len = extent_key->offset; 3390 em->block_len = extent_key->offset;
3389 em->block_start = extent_key->objectid; 3391 em->block_start = extent_key->objectid;
@@ -3391,7 +3393,7 @@ static int noinline relocate_data_extent(struct inode *reloc_inode,
3391 set_bit(EXTENT_FLAG_PINNED, &em->flags); 3393 set_bit(EXTENT_FLAG_PINNED, &em->flags);
3392 3394
3393 /* setup extent map to cheat btrfs_readpage */ 3395 /* setup extent map to cheat btrfs_readpage */
3394 mutex_lock(&BTRFS_I(reloc_inode)->extent_mutex); 3396 lock_extent(&BTRFS_I(reloc_inode)->io_tree, start, end, GFP_NOFS);
3395 while (1) { 3397 while (1) {
3396 int ret; 3398 int ret;
3397 spin_lock(&em_tree->lock); 3399 spin_lock(&em_tree->lock);
@@ -3401,13 +3403,11 @@ static int noinline relocate_data_extent(struct inode *reloc_inode,
3401 free_extent_map(em); 3403 free_extent_map(em);
3402 break; 3404 break;
3403 } 3405 }
3404 btrfs_drop_extent_cache(reloc_inode, em->start, 3406 btrfs_drop_extent_cache(reloc_inode, start, end, 0);
3405 em->start + em->len - 1, 0);
3406 } 3407 }
3407 mutex_unlock(&BTRFS_I(reloc_inode)->extent_mutex); 3408 unlock_extent(&BTRFS_I(reloc_inode)->io_tree, start, end, GFP_NOFS);
3408 3409
3409 return relocate_inode_pages(reloc_inode, extent_key->objectid - offset, 3410 return relocate_inode_pages(reloc_inode, start, extent_key->offset);
3410 extent_key->offset);
3411} 3411}
3412 3412
3413struct btrfs_ref_path { 3413struct btrfs_ref_path {
@@ -3831,7 +3831,6 @@ next:
3831 * the file extent item was modified by someone 3831 * the file extent item was modified by someone
3832 * before the extent got locked. 3832 * before the extent got locked.
3833 */ 3833 */
3834 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
3835 unlock_extent(&BTRFS_I(inode)->io_tree, lock_start, 3834 unlock_extent(&BTRFS_I(inode)->io_tree, lock_start,
3836 lock_end, GFP_NOFS); 3835 lock_end, GFP_NOFS);
3837 extent_locked = 0; 3836 extent_locked = 0;
@@ -3896,8 +3895,12 @@ next:
3896 lock_start = key.offset; 3895 lock_start = key.offset;
3897 lock_end = lock_start + num_bytes - 1; 3896 lock_end = lock_start + num_bytes - 1;
3898 } else { 3897 } else {
3899 BUG_ON(lock_start != key.offset); 3898 if (lock_start > key.offset ||
3900 BUG_ON(lock_end - lock_start + 1 < num_bytes); 3899 lock_end + 1 < key.offset + num_bytes) {
3900 unlock_extent(&BTRFS_I(inode)->io_tree,
3901 lock_start, lock_end, GFP_NOFS);
3902 extent_locked = 0;
3903 }
3901 } 3904 }
3902 3905
3903 if (!inode) { 3906 if (!inode) {
@@ -3951,7 +3954,6 @@ next:
3951 if (ordered) 3954 if (ordered)
3952 btrfs_put_ordered_extent(ordered); 3955 btrfs_put_ordered_extent(ordered);
3953 3956
3954 mutex_lock(&BTRFS_I(inode)->extent_mutex);
3955 extent_locked = 1; 3957 extent_locked = 1;
3956 continue; 3958 continue;
3957 } 3959 }
@@ -4073,7 +4075,6 @@ next:
4073 } 4075 }
4074 4076
4075 if (extent_locked) { 4077 if (extent_locked) {
4076 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
4077 unlock_extent(&BTRFS_I(inode)->io_tree, lock_start, 4078 unlock_extent(&BTRFS_I(inode)->io_tree, lock_start,
4078 lock_end, GFP_NOFS); 4079 lock_end, GFP_NOFS);
4079 extent_locked = 0; 4080 extent_locked = 0;
@@ -4091,7 +4092,6 @@ out:
4091 if (inode) { 4092 if (inode) {
4092 mutex_unlock(&inode->i_mutex); 4093 mutex_unlock(&inode->i_mutex);
4093 if (extent_locked) { 4094 if (extent_locked) {
4094 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
4095 unlock_extent(&BTRFS_I(inode)->io_tree, lock_start, 4095 unlock_extent(&BTRFS_I(inode)->io_tree, lock_start,
4096 lock_end, GFP_NOFS); 4096 lock_end, GFP_NOFS);
4097 } 4097 }
@@ -4180,10 +4180,8 @@ static int noinline invalidate_extent_cache(struct btrfs_root *root,
4180 4180
4181 lock_extent(&BTRFS_I(inode)->io_tree, key.offset, 4181 lock_extent(&BTRFS_I(inode)->io_tree, key.offset,
4182 key.offset + num_bytes - 1, GFP_NOFS); 4182 key.offset + num_bytes - 1, GFP_NOFS);
4183 mutex_lock(&BTRFS_I(inode)->extent_mutex);
4184 btrfs_drop_extent_cache(inode, key.offset, 4183 btrfs_drop_extent_cache(inode, key.offset,
4185 key.offset + num_bytes - 1, 1); 4184 key.offset + num_bytes - 1, 1);
4186 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
4187 unlock_extent(&BTRFS_I(inode)->io_tree, key.offset, 4185 unlock_extent(&BTRFS_I(inode)->io_tree, key.offset,
4188 key.offset + num_bytes - 1, GFP_NOFS); 4186 key.offset + num_bytes - 1, GFP_NOFS);
4189 cond_resched(); 4187 cond_resched();
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 7503bd46819b..65a0583027e9 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -946,8 +946,12 @@ int try_lock_extent(struct extent_io_tree *tree, u64 start, u64 end,
946 946
947 err = set_extent_bit(tree, start, end, EXTENT_LOCKED, 1, 947 err = set_extent_bit(tree, start, end, EXTENT_LOCKED, 1,
948 &failed_start, mask); 948 &failed_start, mask);
949 if (err == -EEXIST) 949 if (err == -EEXIST) {
950 if (failed_start > start)
951 clear_extent_bit(tree, start, failed_start - 1,
952 EXTENT_LOCKED, 1, 0, mask);
950 return 0; 953 return 0;
954 }
951 return 1; 955 return 1;
952} 956}
953EXPORT_SYMBOL(try_lock_extent); 957EXPORT_SYMBOL(try_lock_extent);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index b8a7637e14a1..1a0510ad030c 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -364,6 +364,7 @@ int noinline btrfs_drop_extents(struct btrfs_trans_handle *trans,
364 u64 start, u64 end, u64 inline_limit, u64 *hint_byte) 364 u64 start, u64 end, u64 inline_limit, u64 *hint_byte)
365{ 365{
366 u64 extent_end = 0; 366 u64 extent_end = 0;
367 u64 locked_end = end;
367 u64 search_start = start; 368 u64 search_start = start;
368 u64 leaf_start; 369 u64 leaf_start;
369 u64 ram_bytes = 0; 370 u64 ram_bytes = 0;
@@ -479,12 +480,6 @@ next_slot:
479 goto next_slot; 480 goto next_slot;
480 } 481 }
481 482
482 if (found_inline) {
483 u64 mask = root->sectorsize - 1;
484 search_start = (extent_end + mask) & ~mask;
485 } else
486 search_start = extent_end;
487
488 if (end <= extent_end && start >= key.offset && found_inline) 483 if (end <= extent_end && start >= key.offset && found_inline)
489 *hint_byte = EXTENT_MAP_INLINE; 484 *hint_byte = EXTENT_MAP_INLINE;
490 485
@@ -501,6 +496,26 @@ next_slot:
501 if (found_inline && start <= key.offset) 496 if (found_inline && start <= key.offset)
502 keep = 1; 497 keep = 1;
503 } 498 }
499
500 if (bookend && found_extent && locked_end < extent_end) {
501 ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
502 locked_end, extent_end - 1, GFP_NOFS);
503 if (!ret) {
504 btrfs_release_path(root, path);
505 lock_extent(&BTRFS_I(inode)->io_tree,
506 locked_end, extent_end - 1, GFP_NOFS);
507 locked_end = extent_end;
508 continue;
509 }
510 locked_end = extent_end;
511 }
512
513 if (found_inline) {
514 u64 mask = root->sectorsize - 1;
515 search_start = (extent_end + mask) & ~mask;
516 } else
517 search_start = extent_end;
518
504 /* truncate existing extent */ 519 /* truncate existing extent */
505 if (start > key.offset) { 520 if (start > key.offset) {
506 u64 new_num; 521 u64 new_num;
@@ -638,6 +653,10 @@ next_slot:
638 } 653 }
639out: 654out:
640 btrfs_free_path(path); 655 btrfs_free_path(path);
656 if (locked_end > end) {
657 unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1,
658 GFP_NOFS);
659 }
641 btrfs_check_file(root, inode); 660 btrfs_check_file(root, inode);
642 return ret; 661 return ret;
643} 662}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 8254d6fa6910..e8511d14b119 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -246,7 +246,6 @@ static int cow_file_range_inline(struct btrfs_trans_handle *trans,
246 return 1; 246 return 1;
247 } 247 }
248 248
249 mutex_lock(&BTRFS_I(inode)->extent_mutex);
250 ret = btrfs_drop_extents(trans, root, inode, start, 249 ret = btrfs_drop_extents(trans, root, inode, start,
251 aligned_end, aligned_end, &hint_byte); 250 aligned_end, aligned_end, &hint_byte);
252 BUG_ON(ret); 251 BUG_ON(ret);
@@ -258,7 +257,6 @@ static int cow_file_range_inline(struct btrfs_trans_handle *trans,
258 compressed_pages); 257 compressed_pages);
259 BUG_ON(ret); 258 BUG_ON(ret);
260 btrfs_drop_extent_cache(inode, start, aligned_end, 0); 259 btrfs_drop_extent_cache(inode, start, aligned_end, 0);
261 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
262 return 0; 260 return 0;
263} 261}
264 262
@@ -437,9 +435,7 @@ again:
437 BUG_ON(disk_num_bytes > 435 BUG_ON(disk_num_bytes >
438 btrfs_super_total_bytes(&root->fs_info->super_copy)); 436 btrfs_super_total_bytes(&root->fs_info->super_copy));
439 437
440 mutex_lock(&BTRFS_I(inode)->extent_mutex);
441 btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0); 438 btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0);
442 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
443 439
444 while(disk_num_bytes > 0) { 440 while(disk_num_bytes > 0) {
445 unsigned long min_bytes; 441 unsigned long min_bytes;
@@ -477,8 +473,6 @@ again:
477 em->block_start = ins.objectid; 473 em->block_start = ins.objectid;
478 em->block_len = ins.offset; 474 em->block_len = ins.offset;
479 em->bdev = root->fs_info->fs_devices->latest_bdev; 475 em->bdev = root->fs_info->fs_devices->latest_bdev;
480
481 mutex_lock(&BTRFS_I(inode)->extent_mutex);
482 set_bit(EXTENT_FLAG_PINNED, &em->flags); 476 set_bit(EXTENT_FLAG_PINNED, &em->flags);
483 477
484 if (will_compress) 478 if (will_compress)
@@ -495,7 +489,6 @@ again:
495 btrfs_drop_extent_cache(inode, start, 489 btrfs_drop_extent_cache(inode, start,
496 start + ram_size - 1, 0); 490 start + ram_size - 1, 0);
497 } 491 }
498 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
499 492
500 cur_alloc_size = ins.offset; 493 cur_alloc_size = ins.offset;
501 ret = btrfs_add_ordered_extent(inode, start, ins.objectid, 494 ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
@@ -1016,8 +1009,6 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
1016 1009
1017 INIT_LIST_HEAD(&list); 1010 INIT_LIST_HEAD(&list);
1018 1011
1019 mutex_lock(&BTRFS_I(inode)->extent_mutex);
1020
1021 ret = btrfs_drop_extents(trans, root, inode, 1012 ret = btrfs_drop_extents(trans, root, inode,
1022 ordered_extent->file_offset, 1013 ordered_extent->file_offset,
1023 ordered_extent->file_offset + 1014 ordered_extent->file_offset +
@@ -1059,7 +1050,6 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
1059 btrfs_drop_extent_cache(inode, ordered_extent->file_offset, 1050 btrfs_drop_extent_cache(inode, ordered_extent->file_offset,
1060 ordered_extent->file_offset + 1051 ordered_extent->file_offset +
1061 ordered_extent->len - 1, 0); 1052 ordered_extent->len - 1, 0);
1062 mutex_unlock(&BTRFS_I(inode)->extent_mutex);
1063 1053
1064 ins.objectid = ordered_extent->start; 1054 ins.objectid = ordered_extent->start;
1065 ins.offset = ordered_extent->disk_len; 1055 ins.offset = ordered_extent->disk_len;