diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2013-05-15 03:48:22 -0400 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-06-14 11:29:40 -0400 |
commit | eb73c1b7cea7d533288ef5297a0ea0e159db85b0 (patch) | |
tree | cb6e26e79ab0c11eed7f1db8967e37dbf770f974 /fs/btrfs | |
parent | b0feb9d96e71a88d7eec56f41b8f23e92af889b0 (diff) |
Btrfs: introduce per-subvolume delalloc inode list
When we create a snapshot, we need flush all delalloc inodes in the
fs, just flushing the inodes in the source tree is OK. So we introduce
per-subvolume delalloc inode list.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 22 | ||||
-rw-r--r-- | fs/btrfs/dev-replace.c | 2 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 49 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 6 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 167 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 2 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 |
7 files changed, 183 insertions, 67 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 91a8ca7af77e..43c073533940 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1449,13 +1449,9 @@ struct btrfs_fs_info { | |||
1449 | */ | 1449 | */ |
1450 | struct list_head ordered_extents; | 1450 | struct list_head ordered_extents; |
1451 | 1451 | ||
1452 | spinlock_t delalloc_lock; | 1452 | spinlock_t delalloc_root_lock; |
1453 | /* | 1453 | /* all fs/file tree roots that have delalloc inodes. */ |
1454 | * all of the inodes that have delalloc bytes. It is possible for | 1454 | struct list_head delalloc_roots; |
1455 | * this list to be empty even when there is still dirty data=ordered | ||
1456 | * extents waiting to finish IO. | ||
1457 | */ | ||
1458 | struct list_head delalloc_inodes; | ||
1459 | 1455 | ||
1460 | /* | 1456 | /* |
1461 | * there is a pool of worker threads for checksumming during writes | 1457 | * there is a pool of worker threads for checksumming during writes |
@@ -1747,6 +1743,16 @@ struct btrfs_root { | |||
1747 | 1743 | ||
1748 | spinlock_t root_item_lock; | 1744 | spinlock_t root_item_lock; |
1749 | atomic_t refs; | 1745 | atomic_t refs; |
1746 | |||
1747 | spinlock_t delalloc_lock; | ||
1748 | /* | ||
1749 | * all of the inodes that have delalloc bytes. It is possible for | ||
1750 | * this list to be empty even when there is still dirty data=ordered | ||
1751 | * extents waiting to finish IO. | ||
1752 | */ | ||
1753 | struct list_head delalloc_inodes; | ||
1754 | struct list_head delalloc_root; | ||
1755 | u64 nr_delalloc_inodes; | ||
1750 | }; | 1756 | }; |
1751 | 1757 | ||
1752 | struct btrfs_ioctl_defrag_range_args { | 1758 | struct btrfs_ioctl_defrag_range_args { |
@@ -3550,6 +3556,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
3550 | u32 min_type); | 3556 | u32 min_type); |
3551 | 3557 | ||
3552 | int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput); | 3558 | int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput); |
3559 | int btrfs_start_all_delalloc_inodes(struct btrfs_fs_info *fs_info, | ||
3560 | int delay_iput); | ||
3553 | int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end, | 3561 | int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end, |
3554 | struct extent_state **cached_state); | 3562 | struct extent_state **cached_state); |
3555 | int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, | 3563 | int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 65241f32d3f8..2af312b6fb1f 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c | |||
@@ -470,7 +470,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, | |||
470 | * flush all outstanding I/O and inode extent mappings before the | 470 | * flush all outstanding I/O and inode extent mappings before the |
471 | * copy operation is declared as being finished | 471 | * copy operation is declared as being finished |
472 | */ | 472 | */ |
473 | ret = btrfs_start_delalloc_inodes(root, 0); | 473 | ret = btrfs_start_all_delalloc_inodes(root->fs_info, 0); |
474 | if (ret) { | 474 | if (ret) { |
475 | mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); | 475 | mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); |
476 | return ret; | 476 | return ret; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 90b643e07f3c..2748c7ccdd51 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1191,6 +1191,7 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
1191 | root->objectid = objectid; | 1191 | root->objectid = objectid; |
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->name = NULL; | 1195 | root->name = NULL; |
1195 | root->inode_tree = RB_ROOT; | 1196 | root->inode_tree = RB_ROOT; |
1196 | INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC); | 1197 | INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC); |
@@ -1199,10 +1200,13 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
1199 | 1200 | ||
1200 | INIT_LIST_HEAD(&root->dirty_list); | 1201 | INIT_LIST_HEAD(&root->dirty_list); |
1201 | INIT_LIST_HEAD(&root->root_list); | 1202 | INIT_LIST_HEAD(&root->root_list); |
1203 | INIT_LIST_HEAD(&root->delalloc_inodes); | ||
1204 | INIT_LIST_HEAD(&root->delalloc_root); | ||
1202 | INIT_LIST_HEAD(&root->logged_list[0]); | 1205 | INIT_LIST_HEAD(&root->logged_list[0]); |
1203 | INIT_LIST_HEAD(&root->logged_list[1]); | 1206 | INIT_LIST_HEAD(&root->logged_list[1]); |
1204 | spin_lock_init(&root->orphan_lock); | 1207 | spin_lock_init(&root->orphan_lock); |
1205 | spin_lock_init(&root->inode_lock); | 1208 | spin_lock_init(&root->inode_lock); |
1209 | spin_lock_init(&root->delalloc_lock); | ||
1206 | spin_lock_init(&root->accounting_lock); | 1210 | spin_lock_init(&root->accounting_lock); |
1207 | spin_lock_init(&root->log_extents_lock[0]); | 1211 | spin_lock_init(&root->log_extents_lock[0]); |
1208 | spin_lock_init(&root->log_extents_lock[1]); | 1212 | spin_lock_init(&root->log_extents_lock[1]); |
@@ -2140,9 +2144,9 @@ int open_ctree(struct super_block *sb, | |||
2140 | INIT_LIST_HEAD(&fs_info->trans_list); | 2144 | INIT_LIST_HEAD(&fs_info->trans_list); |
2141 | INIT_LIST_HEAD(&fs_info->dead_roots); | 2145 | INIT_LIST_HEAD(&fs_info->dead_roots); |
2142 | INIT_LIST_HEAD(&fs_info->delayed_iputs); | 2146 | INIT_LIST_HEAD(&fs_info->delayed_iputs); |
2143 | INIT_LIST_HEAD(&fs_info->delalloc_inodes); | 2147 | INIT_LIST_HEAD(&fs_info->delalloc_roots); |
2144 | INIT_LIST_HEAD(&fs_info->caching_block_groups); | 2148 | INIT_LIST_HEAD(&fs_info->caching_block_groups); |
2145 | spin_lock_init(&fs_info->delalloc_lock); | 2149 | spin_lock_init(&fs_info->delalloc_root_lock); |
2146 | spin_lock_init(&fs_info->trans_lock); | 2150 | spin_lock_init(&fs_info->trans_lock); |
2147 | spin_lock_init(&fs_info->fs_roots_radix_lock); | 2151 | spin_lock_init(&fs_info->fs_roots_radix_lock); |
2148 | spin_lock_init(&fs_info->delayed_iput_lock); | 2152 | spin_lock_init(&fs_info->delayed_iput_lock); |
@@ -3803,24 +3807,49 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root) | |||
3803 | 3807 | ||
3804 | INIT_LIST_HEAD(&splice); | 3808 | INIT_LIST_HEAD(&splice); |
3805 | 3809 | ||
3806 | spin_lock(&root->fs_info->delalloc_lock); | 3810 | spin_lock(&root->delalloc_lock); |
3807 | list_splice_init(&root->fs_info->delalloc_inodes, &splice); | 3811 | list_splice_init(&root->delalloc_inodes, &splice); |
3808 | 3812 | ||
3809 | while (!list_empty(&splice)) { | 3813 | while (!list_empty(&splice)) { |
3810 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, | 3814 | btrfs_inode = list_first_entry(&splice, struct btrfs_inode, |
3811 | delalloc_inodes); | 3815 | delalloc_inodes); |
3812 | 3816 | ||
3813 | list_del_init(&btrfs_inode->delalloc_inodes); | 3817 | list_del_init(&btrfs_inode->delalloc_inodes); |
3814 | clear_bit(BTRFS_INODE_IN_DELALLOC_LIST, | 3818 | clear_bit(BTRFS_INODE_IN_DELALLOC_LIST, |
3815 | &btrfs_inode->runtime_flags); | 3819 | &btrfs_inode->runtime_flags); |
3816 | spin_unlock(&root->fs_info->delalloc_lock); | 3820 | spin_unlock(&root->delalloc_lock); |
3817 | 3821 | ||
3818 | btrfs_invalidate_inodes(btrfs_inode->root); | 3822 | btrfs_invalidate_inodes(btrfs_inode->root); |
3819 | 3823 | ||
3820 | spin_lock(&root->fs_info->delalloc_lock); | 3824 | spin_lock(&root->delalloc_lock); |
3821 | } | 3825 | } |
3822 | 3826 | ||
3823 | spin_unlock(&root->fs_info->delalloc_lock); | 3827 | spin_unlock(&root->delalloc_lock); |
3828 | } | ||
3829 | |||
3830 | static void btrfs_destroy_all_delalloc_inodes(struct btrfs_fs_info *fs_info) | ||
3831 | { | ||
3832 | struct btrfs_root *root; | ||
3833 | struct list_head splice; | ||
3834 | |||
3835 | INIT_LIST_HEAD(&splice); | ||
3836 | |||
3837 | spin_lock(&fs_info->delalloc_root_lock); | ||
3838 | list_splice_init(&fs_info->delalloc_roots, &splice); | ||
3839 | while (!list_empty(&splice)) { | ||
3840 | root = list_first_entry(&splice, struct btrfs_root, | ||
3841 | delalloc_root); | ||
3842 | list_del_init(&root->delalloc_root); | ||
3843 | root = btrfs_grab_fs_root(root); | ||
3844 | BUG_ON(!root); | ||
3845 | spin_unlock(&fs_info->delalloc_root_lock); | ||
3846 | |||
3847 | btrfs_destroy_delalloc_inodes(root); | ||
3848 | btrfs_put_fs_root(root); | ||
3849 | |||
3850 | spin_lock(&fs_info->delalloc_root_lock); | ||
3851 | } | ||
3852 | spin_unlock(&fs_info->delalloc_root_lock); | ||
3824 | } | 3853 | } |
3825 | 3854 | ||
3826 | static int btrfs_destroy_marked_extents(struct btrfs_root *root, | 3855 | static int btrfs_destroy_marked_extents(struct btrfs_root *root, |
@@ -3974,7 +4003,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3974 | btrfs_destroy_delayed_inodes(root); | 4003 | btrfs_destroy_delayed_inodes(root); |
3975 | btrfs_assert_delayed_root_empty(root); | 4004 | btrfs_assert_delayed_root_empty(root); |
3976 | 4005 | ||
3977 | btrfs_destroy_delalloc_inodes(root); | 4006 | btrfs_destroy_all_delalloc_inodes(root->fs_info); |
3978 | 4007 | ||
3979 | spin_lock(&root->fs_info->trans_lock); | 4008 | spin_lock(&root->fs_info->trans_lock); |
3980 | root->fs_info->running_transaction = NULL; | 4009 | root->fs_info->running_transaction = NULL; |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 04066c2cc711..f8ff06834e79 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3899,7 +3899,7 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root, | |||
3899 | * the filesystem is readonly(all dirty pages are written to | 3899 | * the filesystem is readonly(all dirty pages are written to |
3900 | * the disk). | 3900 | * the disk). |
3901 | */ | 3901 | */ |
3902 | btrfs_start_delalloc_inodes(root, 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_ordered_extents(root, 0); |
3905 | } | 3905 | } |
@@ -5030,14 +5030,14 @@ static int update_block_group(struct btrfs_root *root, | |||
5030 | int factor; | 5030 | int factor; |
5031 | 5031 | ||
5032 | /* block accounting for super block */ | 5032 | /* block accounting for super block */ |
5033 | spin_lock(&info->delalloc_lock); | 5033 | spin_lock(&info->delalloc_root_lock); |
5034 | old_val = btrfs_super_bytes_used(info->super_copy); | 5034 | old_val = btrfs_super_bytes_used(info->super_copy); |
5035 | if (alloc) | 5035 | if (alloc) |
5036 | old_val += num_bytes; | 5036 | old_val += num_bytes; |
5037 | else | 5037 | else |
5038 | old_val -= num_bytes; | 5038 | old_val -= num_bytes; |
5039 | btrfs_set_super_bytes_used(info->super_copy, old_val); | 5039 | btrfs_set_super_bytes_used(info->super_copy, old_val); |
5040 | spin_unlock(&info->delalloc_lock); | 5040 | spin_unlock(&info->delalloc_root_lock); |
5041 | 5041 | ||
5042 | while (total) { | 5042 | while (total) { |
5043 | cache = btrfs_lookup_block_group(info, bytenr); | 5043 | cache = btrfs_lookup_block_group(info, bytenr); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3817c1e49035..18191f193b47 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1528,6 +1528,46 @@ static void btrfs_merge_extent_hook(struct inode *inode, | |||
1528 | spin_unlock(&BTRFS_I(inode)->lock); | 1528 | spin_unlock(&BTRFS_I(inode)->lock); |
1529 | } | 1529 | } |
1530 | 1530 | ||
1531 | static void btrfs_add_delalloc_inodes(struct btrfs_root *root, | ||
1532 | struct inode *inode) | ||
1533 | { | ||
1534 | spin_lock(&root->delalloc_lock); | ||
1535 | if (list_empty(&BTRFS_I(inode)->delalloc_inodes)) { | ||
1536 | list_add_tail(&BTRFS_I(inode)->delalloc_inodes, | ||
1537 | &root->delalloc_inodes); | ||
1538 | set_bit(BTRFS_INODE_IN_DELALLOC_LIST, | ||
1539 | &BTRFS_I(inode)->runtime_flags); | ||
1540 | root->nr_delalloc_inodes++; | ||
1541 | if (root->nr_delalloc_inodes == 1) { | ||
1542 | spin_lock(&root->fs_info->delalloc_root_lock); | ||
1543 | BUG_ON(!list_empty(&root->delalloc_root)); | ||
1544 | list_add_tail(&root->delalloc_root, | ||
1545 | &root->fs_info->delalloc_roots); | ||
1546 | spin_unlock(&root->fs_info->delalloc_root_lock); | ||
1547 | } | ||
1548 | } | ||
1549 | spin_unlock(&root->delalloc_lock); | ||
1550 | } | ||
1551 | |||
1552 | static void btrfs_del_delalloc_inode(struct btrfs_root *root, | ||
1553 | struct inode *inode) | ||
1554 | { | ||
1555 | spin_lock(&root->delalloc_lock); | ||
1556 | if (!list_empty(&BTRFS_I(inode)->delalloc_inodes)) { | ||
1557 | list_del_init(&BTRFS_I(inode)->delalloc_inodes); | ||
1558 | clear_bit(BTRFS_INODE_IN_DELALLOC_LIST, | ||
1559 | &BTRFS_I(inode)->runtime_flags); | ||
1560 | root->nr_delalloc_inodes--; | ||
1561 | if (!root->nr_delalloc_inodes) { | ||
1562 | spin_lock(&root->fs_info->delalloc_root_lock); | ||
1563 | BUG_ON(list_empty(&root->delalloc_root)); | ||
1564 | list_del_init(&root->delalloc_root); | ||
1565 | spin_unlock(&root->fs_info->delalloc_root_lock); | ||
1566 | } | ||
1567 | } | ||
1568 | spin_unlock(&root->delalloc_lock); | ||
1569 | } | ||
1570 | |||
1531 | /* | 1571 | /* |
1532 | * extent_io.c set_bit_hook, used to track delayed allocation | 1572 | * extent_io.c set_bit_hook, used to track delayed allocation |
1533 | * bytes in this file, and to maintain the list of inodes that | 1573 | * bytes in this file, and to maintain the list of inodes that |
@@ -1560,16 +1600,8 @@ static void btrfs_set_bit_hook(struct inode *inode, | |||
1560 | spin_lock(&BTRFS_I(inode)->lock); | 1600 | spin_lock(&BTRFS_I(inode)->lock); |
1561 | BTRFS_I(inode)->delalloc_bytes += len; | 1601 | BTRFS_I(inode)->delalloc_bytes += len; |
1562 | if (do_list && !test_bit(BTRFS_INODE_IN_DELALLOC_LIST, | 1602 | if (do_list && !test_bit(BTRFS_INODE_IN_DELALLOC_LIST, |
1563 | &BTRFS_I(inode)->runtime_flags)) { | 1603 | &BTRFS_I(inode)->runtime_flags)) |
1564 | spin_lock(&root->fs_info->delalloc_lock); | 1604 | btrfs_add_delalloc_inodes(root, inode); |
1565 | if (list_empty(&BTRFS_I(inode)->delalloc_inodes)) { | ||
1566 | list_add_tail(&BTRFS_I(inode)->delalloc_inodes, | ||
1567 | &root->fs_info->delalloc_inodes); | ||
1568 | set_bit(BTRFS_INODE_IN_DELALLOC_LIST, | ||
1569 | &BTRFS_I(inode)->runtime_flags); | ||
1570 | } | ||
1571 | spin_unlock(&root->fs_info->delalloc_lock); | ||
1572 | } | ||
1573 | spin_unlock(&BTRFS_I(inode)->lock); | 1605 | spin_unlock(&BTRFS_I(inode)->lock); |
1574 | } | 1606 | } |
1575 | } | 1607 | } |
@@ -1612,15 +1644,8 @@ static void btrfs_clear_bit_hook(struct inode *inode, | |||
1612 | BTRFS_I(inode)->delalloc_bytes -= len; | 1644 | BTRFS_I(inode)->delalloc_bytes -= len; |
1613 | if (do_list && BTRFS_I(inode)->delalloc_bytes == 0 && | 1645 | if (do_list && BTRFS_I(inode)->delalloc_bytes == 0 && |
1614 | test_bit(BTRFS_INODE_IN_DELALLOC_LIST, | 1646 | test_bit(BTRFS_INODE_IN_DELALLOC_LIST, |
1615 | &BTRFS_I(inode)->runtime_flags)) { | 1647 | &BTRFS_I(inode)->runtime_flags)) |
1616 | spin_lock(&root->fs_info->delalloc_lock); | 1648 | btrfs_del_delalloc_inode(root, inode); |
1617 | if (!list_empty(&BTRFS_I(inode)->delalloc_inodes)) { | ||
1618 | list_del_init(&BTRFS_I(inode)->delalloc_inodes); | ||
1619 | clear_bit(BTRFS_INODE_IN_DELALLOC_LIST, | ||
1620 | &BTRFS_I(inode)->runtime_flags); | ||
1621 | } | ||
1622 | spin_unlock(&root->fs_info->delalloc_lock); | ||
1623 | } | ||
1624 | spin_unlock(&BTRFS_I(inode)->lock); | 1649 | spin_unlock(&BTRFS_I(inode)->lock); |
1625 | } | 1650 | } |
1626 | } | 1651 | } |
@@ -8338,7 +8363,7 @@ void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work) | |||
8338 | * some fairly slow code that needs optimization. This walks the list | 8363 | * some fairly slow code that needs optimization. This walks the list |
8339 | * of all the inodes with pending delalloc and forces them to disk. | 8364 | * of all the inodes with pending delalloc and forces them to disk. |
8340 | */ | 8365 | */ |
8341 | int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) | 8366 | static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput) |
8342 | { | 8367 | { |
8343 | struct btrfs_inode *binode; | 8368 | struct btrfs_inode *binode; |
8344 | struct inode *inode; | 8369 | struct inode *inode; |
@@ -8347,30 +8372,23 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) | |||
8347 | struct list_head splice; | 8372 | struct list_head splice; |
8348 | int ret = 0; | 8373 | int ret = 0; |
8349 | 8374 | ||
8350 | if (root->fs_info->sb->s_flags & MS_RDONLY) | ||
8351 | return -EROFS; | ||
8352 | |||
8353 | INIT_LIST_HEAD(&works); | 8375 | INIT_LIST_HEAD(&works); |
8354 | INIT_LIST_HEAD(&splice); | 8376 | INIT_LIST_HEAD(&splice); |
8355 | 8377 | ||
8356 | spin_lock(&root->fs_info->delalloc_lock); | 8378 | spin_lock(&root->delalloc_lock); |
8357 | list_splice_init(&root->fs_info->delalloc_inodes, &splice); | 8379 | list_splice_init(&root->delalloc_inodes, &splice); |
8358 | while (!list_empty(&splice)) { | 8380 | while (!list_empty(&splice)) { |
8359 | binode = list_entry(splice.next, struct btrfs_inode, | 8381 | binode = list_entry(splice.next, struct btrfs_inode, |
8360 | delalloc_inodes); | 8382 | delalloc_inodes); |
8361 | 8383 | ||
8362 | list_del_init(&binode->delalloc_inodes); | 8384 | list_move_tail(&binode->delalloc_inodes, |
8363 | 8385 | &root->delalloc_inodes); | |
8364 | inode = igrab(&binode->vfs_inode); | 8386 | inode = igrab(&binode->vfs_inode); |
8365 | if (!inode) { | 8387 | if (!inode) { |
8366 | clear_bit(BTRFS_INODE_IN_DELALLOC_LIST, | 8388 | cond_resched_lock(&root->delalloc_lock); |
8367 | &binode->runtime_flags); | ||
8368 | continue; | 8389 | continue; |
8369 | } | 8390 | } |
8370 | 8391 | spin_unlock(&root->delalloc_lock); | |
8371 | list_add_tail(&binode->delalloc_inodes, | ||
8372 | &root->fs_info->delalloc_inodes); | ||
8373 | spin_unlock(&root->fs_info->delalloc_lock); | ||
8374 | 8392 | ||
8375 | work = btrfs_alloc_delalloc_work(inode, 0, delay_iput); | 8393 | work = btrfs_alloc_delalloc_work(inode, 0, delay_iput); |
8376 | if (unlikely(!work)) { | 8394 | if (unlikely(!work)) { |
@@ -8382,16 +8400,39 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) | |||
8382 | &work->work); | 8400 | &work->work); |
8383 | 8401 | ||
8384 | cond_resched(); | 8402 | cond_resched(); |
8385 | spin_lock(&root->fs_info->delalloc_lock); | 8403 | spin_lock(&root->delalloc_lock); |
8386 | } | 8404 | } |
8387 | spin_unlock(&root->fs_info->delalloc_lock); | 8405 | spin_unlock(&root->delalloc_lock); |
8388 | 8406 | ||
8389 | list_for_each_entry_safe(work, next, &works, list) { | 8407 | list_for_each_entry_safe(work, next, &works, list) { |
8390 | list_del_init(&work->list); | 8408 | list_del_init(&work->list); |
8391 | btrfs_wait_and_free_delalloc_work(work); | 8409 | btrfs_wait_and_free_delalloc_work(work); |
8392 | } | 8410 | } |
8411 | return 0; | ||
8412 | out: | ||
8413 | list_for_each_entry_safe(work, next, &works, list) { | ||
8414 | list_del_init(&work->list); | ||
8415 | btrfs_wait_and_free_delalloc_work(work); | ||
8416 | } | ||
8417 | |||
8418 | if (!list_empty_careful(&splice)) { | ||
8419 | spin_lock(&root->delalloc_lock); | ||
8420 | list_splice_tail(&splice, &root->delalloc_inodes); | ||
8421 | spin_unlock(&root->delalloc_lock); | ||
8422 | } | ||
8423 | return ret; | ||
8424 | } | ||
8393 | 8425 | ||
8394 | /* the filemap_flush will queue IO into the worker threads, but | 8426 | int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) |
8427 | { | ||
8428 | int ret; | ||
8429 | |||
8430 | if (root->fs_info->sb->s_flags & MS_RDONLY) | ||
8431 | return -EROFS; | ||
8432 | |||
8433 | ret = __start_delalloc_inodes(root, delay_iput); | ||
8434 | /* | ||
8435 | * the filemap_flush will queue IO into the worker threads, but | ||
8395 | * we have to make sure the IO is actually started and that | 8436 | * we have to make sure the IO is actually started and that |
8396 | * ordered extents get created before we return | 8437 | * ordered extents get created before we return |
8397 | */ | 8438 | */ |
@@ -8403,17 +8444,55 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) | |||
8403 | atomic_read(&root->fs_info->async_delalloc_pages) == 0)); | 8444 | atomic_read(&root->fs_info->async_delalloc_pages) == 0)); |
8404 | } | 8445 | } |
8405 | atomic_dec(&root->fs_info->async_submit_draining); | 8446 | atomic_dec(&root->fs_info->async_submit_draining); |
8406 | return 0; | 8447 | return ret; |
8407 | out: | 8448 | } |
8408 | list_for_each_entry_safe(work, next, &works, list) { | 8449 | |
8409 | list_del_init(&work->list); | 8450 | int btrfs_start_all_delalloc_inodes(struct btrfs_fs_info *fs_info, |
8410 | btrfs_wait_and_free_delalloc_work(work); | 8451 | int delay_iput) |
8452 | { | ||
8453 | struct btrfs_root *root; | ||
8454 | struct list_head splice; | ||
8455 | int ret; | ||
8456 | |||
8457 | if (fs_info->sb->s_flags & MS_RDONLY) | ||
8458 | return -EROFS; | ||
8459 | |||
8460 | INIT_LIST_HEAD(&splice); | ||
8461 | |||
8462 | spin_lock(&fs_info->delalloc_root_lock); | ||
8463 | list_splice_init(&fs_info->delalloc_roots, &splice); | ||
8464 | while (!list_empty(&splice)) { | ||
8465 | root = list_first_entry(&splice, struct btrfs_root, | ||
8466 | delalloc_root); | ||
8467 | root = btrfs_grab_fs_root(root); | ||
8468 | BUG_ON(!root); | ||
8469 | list_move_tail(&root->delalloc_root, | ||
8470 | &fs_info->delalloc_roots); | ||
8471 | spin_unlock(&fs_info->delalloc_root_lock); | ||
8472 | |||
8473 | ret = __start_delalloc_inodes(root, delay_iput); | ||
8474 | btrfs_put_fs_root(root); | ||
8475 | if (ret) | ||
8476 | goto out; | ||
8477 | |||
8478 | spin_lock(&fs_info->delalloc_root_lock); | ||
8411 | } | 8479 | } |
8480 | spin_unlock(&fs_info->delalloc_root_lock); | ||
8412 | 8481 | ||
8482 | atomic_inc(&fs_info->async_submit_draining); | ||
8483 | while (atomic_read(&fs_info->nr_async_submits) || | ||
8484 | atomic_read(&fs_info->async_delalloc_pages)) { | ||
8485 | wait_event(fs_info->async_submit_wait, | ||
8486 | (atomic_read(&fs_info->nr_async_submits) == 0 && | ||
8487 | atomic_read(&fs_info->async_delalloc_pages) == 0)); | ||
8488 | } | ||
8489 | atomic_dec(&fs_info->async_submit_draining); | ||
8490 | return 0; | ||
8491 | out: | ||
8413 | if (!list_empty_careful(&splice)) { | 8492 | if (!list_empty_careful(&splice)) { |
8414 | spin_lock(&root->fs_info->delalloc_lock); | 8493 | spin_lock(&fs_info->delalloc_root_lock); |
8415 | list_splice_tail(&splice, &root->fs_info->delalloc_inodes); | 8494 | list_splice_tail(&splice, &fs_info->delalloc_roots); |
8416 | spin_unlock(&root->fs_info->delalloc_lock); | 8495 | spin_unlock(&fs_info->delalloc_root_lock); |
8417 | } | 8496 | } |
8418 | return ret; | 8497 | return ret; |
8419 | } | 8498 | } |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index f46b4cca4fa2..f6e1b54f05d8 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -4159,7 +4159,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
4159 | (unsigned long long)rc->block_group->key.objectid, | 4159 | (unsigned long long)rc->block_group->key.objectid, |
4160 | (unsigned long long)rc->block_group->flags); | 4160 | (unsigned long long)rc->block_group->flags); |
4161 | 4161 | ||
4162 | ret = btrfs_start_delalloc_inodes(fs_info->tree_root, 0); | 4162 | ret = btrfs_start_all_delalloc_inodes(fs_info, 0); |
4163 | if (ret < 0) { | 4163 | if (ret < 0) { |
4164 | err = ret; | 4164 | err = ret; |
4165 | goto out; | 4165 | goto out; |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index f157752efc47..4b6311181412 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1502,7 +1502,7 @@ static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans, | |||
1502 | } | 1502 | } |
1503 | 1503 | ||
1504 | if (flush_on_commit || snap_pending) { | 1504 | if (flush_on_commit || snap_pending) { |
1505 | ret = btrfs_start_delalloc_inodes(root, 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_ordered_extents(root, 1); |