diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2013-05-15 03:48:23 -0400 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-06-14 11:29:41 -0400 |
commit | 199c2a9c3d1389db7f7a211e64f6809d352ce5f6 (patch) | |
tree | 8f1e921492d1d5a7b61d98900e8cb3b1b40abdba | |
parent | eb73c1b7cea7d533288ef5297a0ea0e159db85b0 (diff) |
Btrfs: introduce per-subvolume ordered extent list
The reason we introduce per-subvolume ordered extent list is the same
as the per-subvolume delalloc inode list.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
-rw-r--r-- | fs/btrfs/ctree.h | 25 | ||||
-rw-r--r-- | fs/btrfs/dev-replace.c | 4 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 45 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 6 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 4 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.c | 109 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.h | 2 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 2 | ||||
-rw-r--r-- | fs/btrfs/super.c | 2 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 |
10 files changed, 143 insertions, 58 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 43c073533940..905f7c6c82f3 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1437,17 +1437,18 @@ struct btrfs_fs_info { | |||
1437 | atomic_t open_ioctl_trans; | 1437 | atomic_t open_ioctl_trans; |
1438 | 1438 | ||
1439 | /* | 1439 | /* |
1440 | * this is used by the balancing code to wait for all the pending | 1440 | * this is used to protect the following list -- ordered_roots. |
1441 | * ordered extents | ||
1442 | */ | 1441 | */ |
1443 | spinlock_t ordered_extent_lock; | 1442 | spinlock_t ordered_root_lock; |
1444 | 1443 | ||
1445 | /* | 1444 | /* |
1446 | * all of the data=ordered extents pending writeback | 1445 | * all fs/file tree roots in which there are data=ordered extents |
1446 | * pending writeback are added into this list. | ||
1447 | * | ||
1447 | * these can span multiple transactions and basically include | 1448 | * these can span multiple transactions and basically include |
1448 | * every dirty data page that isn't from nodatacow | 1449 | * every dirty data page that isn't from nodatacow |
1449 | */ | 1450 | */ |
1450 | struct list_head ordered_extents; | 1451 | struct list_head ordered_roots; |
1451 | 1452 | ||
1452 | spinlock_t delalloc_root_lock; | 1453 | spinlock_t delalloc_root_lock; |
1453 | /* all fs/file tree roots that have delalloc inodes. */ | 1454 | /* all fs/file tree roots that have delalloc inodes. */ |
@@ -1753,6 +1754,20 @@ struct btrfs_root { | |||
1753 | struct list_head delalloc_inodes; | 1754 | struct list_head delalloc_inodes; |
1754 | struct list_head delalloc_root; | 1755 | struct list_head delalloc_root; |
1755 | u64 nr_delalloc_inodes; | 1756 | u64 nr_delalloc_inodes; |
1757 | /* | ||
1758 | * this is used by the balancing code to wait for all the pending | ||
1759 | * ordered extents | ||
1760 | */ | ||
1761 | spinlock_t ordered_extent_lock; | ||
1762 | |||
1763 | /* | ||
1764 | * all of the data=ordered extents pending writeback | ||
1765 | * these can span multiple transactions and basically include | ||
1766 | * every dirty data page that isn't from nodatacow | ||
1767 | */ | ||
1768 | struct list_head ordered_extents; | ||
1769 | struct list_head ordered_root; | ||
1770 | u64 nr_ordered_extents; | ||
1756 | }; | 1771 | }; |
1757 | 1772 | ||
1758 | struct btrfs_ioctl_defrag_range_args { | 1773 | struct btrfs_ioctl_defrag_range_args { |
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 2af312b6fb1f..4253ad580e39 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c | |||
@@ -400,7 +400,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root, | |||
400 | args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR; | 400 | args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR; |
401 | btrfs_dev_replace_unlock(dev_replace); | 401 | btrfs_dev_replace_unlock(dev_replace); |
402 | 402 | ||
403 | btrfs_wait_ordered_extents(root, 0); | 403 | btrfs_wait_all_ordered_extents(root->fs_info, 0); |
404 | 404 | ||
405 | /* force writing the updated state information to disk */ | 405 | /* force writing the updated state information to disk */ |
406 | trans = btrfs_start_transaction(root, 0); | 406 | trans = btrfs_start_transaction(root, 0); |
@@ -475,7 +475,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, | |||
475 | mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); | 475 | mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); |
476 | return ret; | 476 | return ret; |
477 | } | 477 | } |
478 | btrfs_wait_ordered_extents(root, 0); | 478 | btrfs_wait_all_ordered_extents(root->fs_info, 0); |
479 | 479 | ||
480 | trans = btrfs_start_transaction(root, 0); | 480 | trans = btrfs_start_transaction(root, 0); |
481 | if (IS_ERR(trans)) { | 481 | if (IS_ERR(trans)) { |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2748c7ccdd51..0f873872d1f8 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1192,6 +1192,7 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
1192 | root->last_trans = 0; | 1192 | root->last_trans = 0; |
1193 | root->highest_objectid = 0; | 1193 | root->highest_objectid = 0; |
1194 | root->nr_delalloc_inodes = 0; | 1194 | root->nr_delalloc_inodes = 0; |
1195 | root->nr_ordered_extents = 0; | ||
1195 | root->name = NULL; | 1196 | root->name = NULL; |
1196 | root->inode_tree = RB_ROOT; | 1197 | root->inode_tree = RB_ROOT; |
1197 | INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC); | 1198 | INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC); |
@@ -1202,11 +1203,14 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
1202 | INIT_LIST_HEAD(&root->root_list); | 1203 | INIT_LIST_HEAD(&root->root_list); |
1203 | INIT_LIST_HEAD(&root->delalloc_inodes); | 1204 | INIT_LIST_HEAD(&root->delalloc_inodes); |
1204 | INIT_LIST_HEAD(&root->delalloc_root); | 1205 | INIT_LIST_HEAD(&root->delalloc_root); |
1206 | INIT_LIST_HEAD(&root->ordered_extents); | ||
1207 | INIT_LIST_HEAD(&root->ordered_root); | ||
1205 | INIT_LIST_HEAD(&root->logged_list[0]); | 1208 | INIT_LIST_HEAD(&root->logged_list[0]); |
1206 | INIT_LIST_HEAD(&root->logged_list[1]); | 1209 | INIT_LIST_HEAD(&root->logged_list[1]); |
1207 | spin_lock_init(&root->orphan_lock); | 1210 | spin_lock_init(&root->orphan_lock); |
1208 | spin_lock_init(&root->inode_lock); | 1211 | spin_lock_init(&root->inode_lock); |
1209 | spin_lock_init(&root->delalloc_lock); | 1212 | spin_lock_init(&root->delalloc_lock); |
1213 | spin_lock_init(&root->ordered_extent_lock); | ||
1210 | spin_lock_init(&root->accounting_lock); | 1214 | spin_lock_init(&root->accounting_lock); |
1211 | spin_lock_init(&root->log_extents_lock[0]); | 1215 | spin_lock_init(&root->log_extents_lock[0]); |
1212 | spin_lock_init(&root->log_extents_lock[1]); | 1216 | spin_lock_init(&root->log_extents_lock[1]); |
@@ -2193,8 +2197,8 @@ int open_ctree(struct super_block *sb, | |||
2193 | fs_info->thread_pool_size = min_t(unsigned long, | 2197 | fs_info->thread_pool_size = min_t(unsigned long, |
2194 | num_online_cpus() + 2, 8); | 2198 | num_online_cpus() + 2, 8); |
2195 | 2199 | ||
2196 | INIT_LIST_HEAD(&fs_info->ordered_extents); | 2200 | INIT_LIST_HEAD(&fs_info->ordered_roots); |
2197 | spin_lock_init(&fs_info->ordered_extent_lock); | 2201 | spin_lock_init(&fs_info->ordered_root_lock); |
2198 | fs_info->delayed_root = kmalloc(sizeof(struct btrfs_delayed_root), | 2202 | fs_info->delayed_root = kmalloc(sizeof(struct btrfs_delayed_root), |
2199 | GFP_NOFS); | 2203 | GFP_NOFS); |
2200 | if (!fs_info->delayed_root) { | 2204 | if (!fs_info->delayed_root) { |
@@ -3683,7 +3687,7 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t, | |||
3683 | INIT_LIST_HEAD(&splice); | 3687 | INIT_LIST_HEAD(&splice); |
3684 | 3688 | ||
3685 | mutex_lock(&root->fs_info->ordered_operations_mutex); | 3689 | mutex_lock(&root->fs_info->ordered_operations_mutex); |
3686 | spin_lock(&root->fs_info->ordered_extent_lock); | 3690 | spin_lock(&root->fs_info->ordered_root_lock); |
3687 | 3691 | ||
3688 | list_splice_init(&t->ordered_operations, &splice); | 3692 | list_splice_init(&t->ordered_operations, &splice); |
3689 | while (!list_empty(&splice)) { | 3693 | while (!list_empty(&splice)) { |
@@ -3691,14 +3695,14 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t, | |||
3691 | ordered_operations); | 3695 | ordered_operations); |
3692 | 3696 | ||
3693 | list_del_init(&btrfs_inode->ordered_operations); | 3697 | list_del_init(&btrfs_inode->ordered_operations); |
3694 | spin_unlock(&root->fs_info->ordered_extent_lock); | 3698 | spin_unlock(&root->fs_info->ordered_root_lock); |
3695 | 3699 | ||
3696 | btrfs_invalidate_inodes(btrfs_inode->root); | 3700 | btrfs_invalidate_inodes(btrfs_inode->root); |
3697 | 3701 | ||
3698 | spin_lock(&root->fs_info->ordered_extent_lock); | 3702 | spin_lock(&root->fs_info->ordered_root_lock); |
3699 | } | 3703 | } |
3700 | 3704 | ||
3701 | spin_unlock(&root->fs_info->ordered_extent_lock); | 3705 | spin_unlock(&root->fs_info->ordered_root_lock); |
3702 | mutex_unlock(&root->fs_info->ordered_operations_mutex); | 3706 | mutex_unlock(&root->fs_info->ordered_operations_mutex); |
3703 | } | 3707 | } |
3704 | 3708 | ||
@@ -3706,15 +3710,36 @@ static void btrfs_destroy_ordered_extents(struct btrfs_root *root) | |||
3706 | { | 3710 | { |
3707 | struct btrfs_ordered_extent *ordered; | 3711 | struct btrfs_ordered_extent *ordered; |
3708 | 3712 | ||
3709 | spin_lock(&root->fs_info->ordered_extent_lock); | 3713 | spin_lock(&root->ordered_extent_lock); |
3710 | /* | 3714 | /* |
3711 | * This will just short circuit the ordered completion stuff which will | 3715 | * This will just short circuit the ordered completion stuff which will |
3712 | * make sure the ordered extent gets properly cleaned up. | 3716 | * make sure the ordered extent gets properly cleaned up. |
3713 | */ | 3717 | */ |
3714 | list_for_each_entry(ordered, &root->fs_info->ordered_extents, | 3718 | list_for_each_entry(ordered, &root->ordered_extents, |
3715 | root_extent_list) | 3719 | root_extent_list) |
3716 | set_bit(BTRFS_ORDERED_IOERR, &ordered->flags); | 3720 | set_bit(BTRFS_ORDERED_IOERR, &ordered->flags); |
3717 | spin_unlock(&root->fs_info->ordered_extent_lock); | 3721 | spin_unlock(&root->ordered_extent_lock); |
3722 | } | ||
3723 | |||
3724 | static void btrfs_destroy_all_ordered_extents(struct btrfs_fs_info *fs_info) | ||
3725 | { | ||
3726 | struct btrfs_root *root; | ||
3727 | struct list_head splice; | ||
3728 | |||
3729 | INIT_LIST_HEAD(&splice); | ||
3730 | |||
3731 | spin_lock(&fs_info->ordered_root_lock); | ||
3732 | list_splice_init(&fs_info->ordered_roots, &splice); | ||
3733 | while (!list_empty(&splice)) { | ||
3734 | root = list_first_entry(&splice, struct btrfs_root, | ||
3735 | ordered_root); | ||
3736 | list_del_init(&root->ordered_root); | ||
3737 | |||
3738 | btrfs_destroy_ordered_extents(root); | ||
3739 | |||
3740 | cond_resched_lock(&fs_info->ordered_root_lock); | ||
3741 | } | ||
3742 | spin_unlock(&fs_info->ordered_root_lock); | ||
3718 | } | 3743 | } |
3719 | 3744 | ||
3720 | int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | 3745 | int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, |
@@ -3977,7 +4002,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3977 | 4002 | ||
3978 | btrfs_destroy_ordered_operations(t, root); | 4003 | btrfs_destroy_ordered_operations(t, root); |
3979 | 4004 | ||
3980 | btrfs_destroy_ordered_extents(root); | 4005 | btrfs_destroy_all_ordered_extents(root->fs_info); |
3981 | 4006 | ||
3982 | btrfs_destroy_delayed_refs(t, root); | 4007 | btrfs_destroy_delayed_refs(t, root); |
3983 | 4008 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index f8ff06834e79..4ec8305fe078 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3901,7 +3901,7 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root, | |||
3901 | */ | 3901 | */ |
3902 | btrfs_start_all_delalloc_inodes(root->fs_info, 0); | 3902 | btrfs_start_all_delalloc_inodes(root->fs_info, 0); |
3903 | if (!current->journal_info) | 3903 | if (!current->journal_info) |
3904 | btrfs_wait_ordered_extents(root, 0); | 3904 | btrfs_wait_all_ordered_extents(root->fs_info, 0); |
3905 | } | 3905 | } |
3906 | } | 3906 | } |
3907 | 3907 | ||
@@ -3931,7 +3931,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, | |||
3931 | if (delalloc_bytes == 0) { | 3931 | if (delalloc_bytes == 0) { |
3932 | if (trans) | 3932 | if (trans) |
3933 | return; | 3933 | return; |
3934 | btrfs_wait_ordered_extents(root, 0); | 3934 | btrfs_wait_all_ordered_extents(root->fs_info, 0); |
3935 | return; | 3935 | return; |
3936 | } | 3936 | } |
3937 | 3937 | ||
@@ -3959,7 +3959,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, | |||
3959 | 3959 | ||
3960 | loops++; | 3960 | loops++; |
3961 | if (wait_ordered && !trans) { | 3961 | if (wait_ordered && !trans) { |
3962 | btrfs_wait_ordered_extents(root, 0); | 3962 | btrfs_wait_all_ordered_extents(root->fs_info, 0); |
3963 | } else { | 3963 | } else { |
3964 | time_left = schedule_timeout_killable(1); | 3964 | time_left = schedule_timeout_killable(1); |
3965 | if (time_left) | 3965 | if (time_left) |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 18191f193b47..51520755f4dc 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -7991,9 +7991,9 @@ void btrfs_destroy_inode(struct inode *inode) | |||
7991 | */ | 7991 | */ |
7992 | smp_mb(); | 7992 | smp_mb(); |
7993 | if (!list_empty(&BTRFS_I(inode)->ordered_operations)) { | 7993 | if (!list_empty(&BTRFS_I(inode)->ordered_operations)) { |
7994 | spin_lock(&root->fs_info->ordered_extent_lock); | 7994 | spin_lock(&root->fs_info->ordered_root_lock); |
7995 | list_del_init(&BTRFS_I(inode)->ordered_operations); | 7995 | list_del_init(&BTRFS_I(inode)->ordered_operations); |
7996 | spin_unlock(&root->fs_info->ordered_extent_lock); | 7996 | spin_unlock(&root->fs_info->ordered_root_lock); |
7997 | } | 7997 | } |
7998 | 7998 | ||
7999 | if (test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, | 7999 | if (test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 1ddd728541ee..665c640e3ea6 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "transaction.h" | 24 | #include "transaction.h" |
25 | #include "btrfs_inode.h" | 25 | #include "btrfs_inode.h" |
26 | #include "extent_io.h" | 26 | #include "extent_io.h" |
27 | #include "disk-io.h" | ||
27 | 28 | ||
28 | static struct kmem_cache *btrfs_ordered_extent_cache; | 29 | static struct kmem_cache *btrfs_ordered_extent_cache; |
29 | 30 | ||
@@ -184,6 +185,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
184 | u64 start, u64 len, u64 disk_len, | 185 | u64 start, u64 len, u64 disk_len, |
185 | int type, int dio, int compress_type) | 186 | int type, int dio, int compress_type) |
186 | { | 187 | { |
188 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
187 | struct btrfs_ordered_inode_tree *tree; | 189 | struct btrfs_ordered_inode_tree *tree; |
188 | struct rb_node *node; | 190 | struct rb_node *node; |
189 | struct btrfs_ordered_extent *entry; | 191 | struct btrfs_ordered_extent *entry; |
@@ -227,10 +229,18 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
227 | ordered_data_tree_panic(inode, -EEXIST, file_offset); | 229 | ordered_data_tree_panic(inode, -EEXIST, file_offset); |
228 | spin_unlock_irq(&tree->lock); | 230 | spin_unlock_irq(&tree->lock); |
229 | 231 | ||
230 | spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | 232 | spin_lock(&root->ordered_extent_lock); |
231 | list_add_tail(&entry->root_extent_list, | 233 | list_add_tail(&entry->root_extent_list, |
232 | &BTRFS_I(inode)->root->fs_info->ordered_extents); | 234 | &root->ordered_extents); |
233 | spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | 235 | root->nr_ordered_extents++; |
236 | if (root->nr_ordered_extents == 1) { | ||
237 | spin_lock(&root->fs_info->ordered_root_lock); | ||
238 | BUG_ON(!list_empty(&root->ordered_root)); | ||
239 | list_add_tail(&root->ordered_root, | ||
240 | &root->fs_info->ordered_roots); | ||
241 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
242 | } | ||
243 | spin_unlock(&root->ordered_extent_lock); | ||
234 | 244 | ||
235 | return 0; | 245 | return 0; |
236 | } | 246 | } |
@@ -516,8 +526,9 @@ void btrfs_remove_ordered_extent(struct inode *inode, | |||
516 | set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); | 526 | set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); |
517 | spin_unlock_irq(&tree->lock); | 527 | spin_unlock_irq(&tree->lock); |
518 | 528 | ||
519 | spin_lock(&root->fs_info->ordered_extent_lock); | 529 | spin_lock(&root->ordered_extent_lock); |
520 | list_del_init(&entry->root_extent_list); | 530 | list_del_init(&entry->root_extent_list); |
531 | root->nr_ordered_extents--; | ||
521 | 532 | ||
522 | trace_btrfs_ordered_extent_remove(inode, entry); | 533 | trace_btrfs_ordered_extent_remove(inode, entry); |
523 | 534 | ||
@@ -530,7 +541,14 @@ void btrfs_remove_ordered_extent(struct inode *inode, | |||
530 | !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY)) { | 541 | !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY)) { |
531 | list_del_init(&BTRFS_I(inode)->ordered_operations); | 542 | list_del_init(&BTRFS_I(inode)->ordered_operations); |
532 | } | 543 | } |
533 | spin_unlock(&root->fs_info->ordered_extent_lock); | 544 | |
545 | if (!root->nr_ordered_extents) { | ||
546 | spin_lock(&root->fs_info->ordered_root_lock); | ||
547 | BUG_ON(list_empty(&root->ordered_root)); | ||
548 | list_del_init(&root->ordered_root); | ||
549 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
550 | } | ||
551 | spin_unlock(&root->ordered_extent_lock); | ||
534 | wake_up(&entry->wait); | 552 | wake_up(&entry->wait); |
535 | } | 553 | } |
536 | 554 | ||
@@ -550,7 +568,6 @@ static void btrfs_run_ordered_extent_work(struct btrfs_work *work) | |||
550 | void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | 568 | void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) |
551 | { | 569 | { |
552 | struct list_head splice, works; | 570 | struct list_head splice, works; |
553 | struct list_head *cur; | ||
554 | struct btrfs_ordered_extent *ordered, *next; | 571 | struct btrfs_ordered_extent *ordered, *next; |
555 | struct inode *inode; | 572 | struct inode *inode; |
556 | 573 | ||
@@ -558,35 +575,34 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | |||
558 | INIT_LIST_HEAD(&works); | 575 | INIT_LIST_HEAD(&works); |
559 | 576 | ||
560 | mutex_lock(&root->fs_info->ordered_operations_mutex); | 577 | mutex_lock(&root->fs_info->ordered_operations_mutex); |
561 | spin_lock(&root->fs_info->ordered_extent_lock); | 578 | spin_lock(&root->ordered_extent_lock); |
562 | list_splice_init(&root->fs_info->ordered_extents, &splice); | 579 | list_splice_init(&root->ordered_extents, &splice); |
563 | while (!list_empty(&splice)) { | 580 | while (!list_empty(&splice)) { |
564 | cur = splice.next; | 581 | ordered = list_first_entry(&splice, struct btrfs_ordered_extent, |
565 | ordered = list_entry(cur, struct btrfs_ordered_extent, | 582 | root_extent_list); |
566 | root_extent_list); | 583 | list_move_tail(&ordered->root_extent_list, |
567 | list_del_init(&ordered->root_extent_list); | 584 | &root->ordered_extents); |
568 | atomic_inc(&ordered->refs); | ||
569 | |||
570 | /* | 585 | /* |
571 | * the inode may be getting freed (in sys_unlink path). | 586 | * the inode may be getting freed (in sys_unlink path). |
572 | */ | 587 | */ |
573 | inode = igrab(ordered->inode); | 588 | inode = igrab(ordered->inode); |
589 | if (!inode) { | ||
590 | cond_resched_lock(&root->ordered_extent_lock); | ||
591 | continue; | ||
592 | } | ||
574 | 593 | ||
575 | spin_unlock(&root->fs_info->ordered_extent_lock); | 594 | atomic_inc(&ordered->refs); |
595 | spin_unlock(&root->ordered_extent_lock); | ||
576 | 596 | ||
577 | if (inode) { | 597 | ordered->flush_work.func = btrfs_run_ordered_extent_work; |
578 | ordered->flush_work.func = btrfs_run_ordered_extent_work; | 598 | list_add_tail(&ordered->work_list, &works); |
579 | list_add_tail(&ordered->work_list, &works); | 599 | btrfs_queue_worker(&root->fs_info->flush_workers, |
580 | btrfs_queue_worker(&root->fs_info->flush_workers, | 600 | &ordered->flush_work); |
581 | &ordered->flush_work); | ||
582 | } else { | ||
583 | btrfs_put_ordered_extent(ordered); | ||
584 | } | ||
585 | 601 | ||
586 | cond_resched(); | 602 | cond_resched(); |
587 | spin_lock(&root->fs_info->ordered_extent_lock); | 603 | spin_lock(&root->ordered_extent_lock); |
588 | } | 604 | } |
589 | spin_unlock(&root->fs_info->ordered_extent_lock); | 605 | spin_unlock(&root->ordered_extent_lock); |
590 | 606 | ||
591 | list_for_each_entry_safe(ordered, next, &works, work_list) { | 607 | list_for_each_entry_safe(ordered, next, &works, work_list) { |
592 | list_del_init(&ordered->work_list); | 608 | list_del_init(&ordered->work_list); |
@@ -604,6 +620,33 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | |||
604 | mutex_unlock(&root->fs_info->ordered_operations_mutex); | 620 | mutex_unlock(&root->fs_info->ordered_operations_mutex); |
605 | } | 621 | } |
606 | 622 | ||
623 | void btrfs_wait_all_ordered_extents(struct btrfs_fs_info *fs_info, | ||
624 | int delay_iput) | ||
625 | { | ||
626 | struct btrfs_root *root; | ||
627 | struct list_head splice; | ||
628 | |||
629 | INIT_LIST_HEAD(&splice); | ||
630 | |||
631 | spin_lock(&fs_info->ordered_root_lock); | ||
632 | list_splice_init(&fs_info->ordered_roots, &splice); | ||
633 | while (!list_empty(&splice)) { | ||
634 | root = list_first_entry(&splice, struct btrfs_root, | ||
635 | ordered_root); | ||
636 | root = btrfs_grab_fs_root(root); | ||
637 | BUG_ON(!root); | ||
638 | list_move_tail(&root->ordered_root, | ||
639 | &fs_info->ordered_roots); | ||
640 | spin_unlock(&fs_info->ordered_root_lock); | ||
641 | |||
642 | btrfs_wait_ordered_extents(root, delay_iput); | ||
643 | btrfs_put_fs_root(root); | ||
644 | |||
645 | spin_lock(&fs_info->ordered_root_lock); | ||
646 | } | ||
647 | spin_unlock(&fs_info->ordered_root_lock); | ||
648 | } | ||
649 | |||
607 | /* | 650 | /* |
608 | * this is used during transaction commit to write all the inodes | 651 | * this is used during transaction commit to write all the inodes |
609 | * added to the ordered operation list. These files must be fully on | 652 | * added to the ordered operation list. These files must be fully on |
@@ -629,7 +672,7 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, | |||
629 | INIT_LIST_HEAD(&works); | 672 | INIT_LIST_HEAD(&works); |
630 | 673 | ||
631 | mutex_lock(&root->fs_info->ordered_operations_mutex); | 674 | mutex_lock(&root->fs_info->ordered_operations_mutex); |
632 | spin_lock(&root->fs_info->ordered_extent_lock); | 675 | spin_lock(&root->fs_info->ordered_root_lock); |
633 | list_splice_init(&cur_trans->ordered_operations, &splice); | 676 | list_splice_init(&cur_trans->ordered_operations, &splice); |
634 | while (!list_empty(&splice)) { | 677 | while (!list_empty(&splice)) { |
635 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, | 678 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, |
@@ -648,17 +691,17 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, | |||
648 | if (!wait) | 691 | if (!wait) |
649 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | 692 | list_add_tail(&BTRFS_I(inode)->ordered_operations, |
650 | &cur_trans->ordered_operations); | 693 | &cur_trans->ordered_operations); |
651 | spin_unlock(&root->fs_info->ordered_extent_lock); | 694 | spin_unlock(&root->fs_info->ordered_root_lock); |
652 | 695 | ||
653 | work = btrfs_alloc_delalloc_work(inode, wait, 1); | 696 | work = btrfs_alloc_delalloc_work(inode, wait, 1); |
654 | if (!work) { | 697 | if (!work) { |
655 | spin_lock(&root->fs_info->ordered_extent_lock); | 698 | spin_lock(&root->fs_info->ordered_root_lock); |
656 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) | 699 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) |
657 | list_add_tail(&btrfs_inode->ordered_operations, | 700 | list_add_tail(&btrfs_inode->ordered_operations, |
658 | &splice); | 701 | &splice); |
659 | list_splice_tail(&splice, | 702 | list_splice_tail(&splice, |
660 | &cur_trans->ordered_operations); | 703 | &cur_trans->ordered_operations); |
661 | spin_unlock(&root->fs_info->ordered_extent_lock); | 704 | spin_unlock(&root->fs_info->ordered_root_lock); |
662 | ret = -ENOMEM; | 705 | ret = -ENOMEM; |
663 | goto out; | 706 | goto out; |
664 | } | 707 | } |
@@ -667,9 +710,9 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, | |||
667 | &work->work); | 710 | &work->work); |
668 | 711 | ||
669 | cond_resched(); | 712 | cond_resched(); |
670 | spin_lock(&root->fs_info->ordered_extent_lock); | 713 | spin_lock(&root->fs_info->ordered_root_lock); |
671 | } | 714 | } |
672 | spin_unlock(&root->fs_info->ordered_extent_lock); | 715 | spin_unlock(&root->fs_info->ordered_root_lock); |
673 | out: | 716 | out: |
674 | list_for_each_entry_safe(work, next, &works, list) { | 717 | list_for_each_entry_safe(work, next, &works, list) { |
675 | list_del_init(&work->list); | 718 | list_del_init(&work->list); |
@@ -1055,12 +1098,12 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | |||
1055 | if (last_mod < root->fs_info->last_trans_committed) | 1098 | if (last_mod < root->fs_info->last_trans_committed) |
1056 | return; | 1099 | return; |
1057 | 1100 | ||
1058 | spin_lock(&root->fs_info->ordered_extent_lock); | 1101 | spin_lock(&root->fs_info->ordered_root_lock); |
1059 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) { | 1102 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) { |
1060 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | 1103 | list_add_tail(&BTRFS_I(inode)->ordered_operations, |
1061 | &cur_trans->ordered_operations); | 1104 | &cur_trans->ordered_operations); |
1062 | } | 1105 | } |
1063 | spin_unlock(&root->fs_info->ordered_extent_lock); | 1106 | spin_unlock(&root->fs_info->ordered_root_lock); |
1064 | } | 1107 | } |
1065 | 1108 | ||
1066 | int __init ordered_data_init(void) | 1109 | int __init ordered_data_init(void) |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 58b0e3b0ebad..d082d43e00e5 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
@@ -204,6 +204,8 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | |||
204 | struct btrfs_root *root, | 204 | struct btrfs_root *root, |
205 | struct inode *inode); | 205 | struct inode *inode); |
206 | void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput); | 206 | void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput); |
207 | void btrfs_wait_all_ordered_extents(struct btrfs_fs_info *fs_info, | ||
208 | int delay_iput); | ||
207 | void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode); | 209 | void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode); |
208 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid); | 210 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid); |
209 | void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid); | 211 | void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid); |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index f6e1b54f05d8..aa559f1161df 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -4164,7 +4164,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
4164 | err = ret; | 4164 | err = ret; |
4165 | goto out; | 4165 | goto out; |
4166 | } | 4166 | } |
4167 | btrfs_wait_ordered_extents(fs_info->tree_root, 0); | 4167 | btrfs_wait_all_ordered_extents(fs_info, 0); |
4168 | 4168 | ||
4169 | while (1) { | 4169 | while (1) { |
4170 | mutex_lock(&fs_info->cleaner_mutex); | 4170 | mutex_lock(&fs_info->cleaner_mutex); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 2a6a908d0017..41d81bee583d 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -862,7 +862,7 @@ int btrfs_sync_fs(struct super_block *sb, int wait) | |||
862 | return 0; | 862 | return 0; |
863 | } | 863 | } |
864 | 864 | ||
865 | btrfs_wait_ordered_extents(root, 1); | 865 | btrfs_wait_all_ordered_extents(fs_info, 0); |
866 | 866 | ||
867 | trans = btrfs_attach_transaction_barrier(root); | 867 | trans = btrfs_attach_transaction_barrier(root); |
868 | if (IS_ERR(trans)) { | 868 | if (IS_ERR(trans)) { |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 4b6311181412..2b17213571a0 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1505,7 +1505,7 @@ static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans, | |||
1505 | ret = btrfs_start_all_delalloc_inodes(root->fs_info, 1); | 1505 | ret = btrfs_start_all_delalloc_inodes(root->fs_info, 1); |
1506 | if (ret) | 1506 | if (ret) |
1507 | return ret; | 1507 | return ret; |
1508 | btrfs_wait_ordered_extents(root, 1); | 1508 | btrfs_wait_all_ordered_extents(root->fs_info, 1); |
1509 | } | 1509 | } |
1510 | 1510 | ||
1511 | ret = btrfs_run_delayed_items(trans, root); | 1511 | ret = btrfs_run_delayed_items(trans, root); |