aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-10-30 11:23:27 -0400
committerChris Mason <chris.mason@oracle.com>2008-10-30 11:23:27 -0400
commit87ef2bb46bfc4be0b40799e68115cbe28d80a1bd (patch)
tree8060158d9adee7ad2fc591c47ad1354b07237020 /fs/btrfs/extent-tree.c
parent09fde3c9ba360926ce021c184a1ee343f4d8fa19 (diff)
Btrfs: prevent looping forever in finish_current_insert and del_pending_extents
finish_current_insert and del_pending_extents process extent tree modifications that build up while we are changing the extent tree. It is a confusing bit of code that prevents recursion. Both functions run through a list of pending operations and both funcs add to the list of pending operations. If you have two procs in either one of them, they can end up looping forever making more work for each other. This patch makes them walk forward through the list of pending changes instead of always trying to process the entire list. At transaction commit time, we catch any changes that were left over. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c54
1 files changed, 30 insertions, 24 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 155c8dc56a22..fada9c22a021 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -45,9 +45,9 @@ struct pending_extent_op {
45}; 45};
46 46
47static int finish_current_insert(struct btrfs_trans_handle *trans, struct 47static int finish_current_insert(struct btrfs_trans_handle *trans, struct
48 btrfs_root *extent_root); 48 btrfs_root *extent_root, int all);
49static int del_pending_extents(struct btrfs_trans_handle *trans, struct 49static int del_pending_extents(struct btrfs_trans_handle *trans, struct
50 btrfs_root *extent_root); 50 btrfs_root *extent_root, int all);
51static struct btrfs_block_group_cache * 51static struct btrfs_block_group_cache *
52__btrfs_find_block_group(struct btrfs_root *root, 52__btrfs_find_block_group(struct btrfs_root *root,
53 struct btrfs_block_group_cache *hint, 53 struct btrfs_block_group_cache *hint,
@@ -711,8 +711,8 @@ static int __btrfs_update_extent_ref(struct btrfs_trans_handle *trans,
711 parent, ref_root, ref_generation, 711 parent, ref_root, ref_generation,
712 owner_objectid); 712 owner_objectid);
713 BUG_ON(ret); 713 BUG_ON(ret);
714 finish_current_insert(trans, extent_root); 714 finish_current_insert(trans, extent_root, 0);
715 del_pending_extents(trans, extent_root); 715 del_pending_extents(trans, extent_root, 0);
716out: 716out:
717 btrfs_free_path(path); 717 btrfs_free_path(path);
718 return ret; 718 return ret;
@@ -784,8 +784,8 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
784 ref_root, ref_generation, 784 ref_root, ref_generation,
785 owner_objectid); 785 owner_objectid);
786 BUG_ON(ret); 786 BUG_ON(ret);
787 finish_current_insert(trans, root->fs_info->extent_root); 787 finish_current_insert(trans, root->fs_info->extent_root, 0);
788 del_pending_extents(trans, root->fs_info->extent_root); 788 del_pending_extents(trans, root->fs_info->extent_root, 0);
789 789
790 btrfs_free_path(path); 790 btrfs_free_path(path);
791 return 0; 791 return 0;
@@ -810,8 +810,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
810int btrfs_extent_post_op(struct btrfs_trans_handle *trans, 810int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
811 struct btrfs_root *root) 811 struct btrfs_root *root)
812{ 812{
813 finish_current_insert(trans, root->fs_info->extent_root); 813 finish_current_insert(trans, root->fs_info->extent_root, 1);
814 del_pending_extents(trans, root->fs_info->extent_root); 814 del_pending_extents(trans, root->fs_info->extent_root, 1);
815 return 0; 815 return 0;
816} 816}
817 817
@@ -1292,8 +1292,8 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
1292 btrfs_mark_buffer_dirty(leaf); 1292 btrfs_mark_buffer_dirty(leaf);
1293 btrfs_release_path(extent_root, path); 1293 btrfs_release_path(extent_root, path);
1294fail: 1294fail:
1295 finish_current_insert(trans, extent_root); 1295 finish_current_insert(trans, extent_root, 0);
1296 pending_ret = del_pending_extents(trans, extent_root); 1296 pending_ret = del_pending_extents(trans, extent_root, 0);
1297 if (ret) 1297 if (ret)
1298 return ret; 1298 return ret;
1299 if (pending_ret) 1299 if (pending_ret)
@@ -1690,7 +1690,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
1690} 1690}
1691 1691
1692static int finish_current_insert(struct btrfs_trans_handle *trans, 1692static int finish_current_insert(struct btrfs_trans_handle *trans,
1693 struct btrfs_root *extent_root) 1693 struct btrfs_root *extent_root, int all)
1694{ 1694{
1695 u64 start; 1695 u64 start;
1696 u64 end; 1696 u64 end;
@@ -1714,7 +1714,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
1714 &end, EXTENT_WRITEBACK); 1714 &end, EXTENT_WRITEBACK);
1715 if (ret) { 1715 if (ret) {
1716 mutex_unlock(&info->extent_ins_mutex); 1716 mutex_unlock(&info->extent_ins_mutex);
1717 if (search) { 1717 if (search && all) {
1718 search = 0; 1718 search = 0;
1719 continue; 1719 continue;
1720 } 1720 }
@@ -1723,7 +1723,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
1723 1723
1724 ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS); 1724 ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS);
1725 if (!ret) { 1725 if (!ret) {
1726 search = end+1; 1726 search = end + 1;
1727 mutex_unlock(&info->extent_ins_mutex); 1727 mutex_unlock(&info->extent_ins_mutex);
1728 cond_resched(); 1728 cond_resched();
1729 continue; 1729 continue;
@@ -1785,7 +1785,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
1785 } 1785 }
1786 kfree(extent_op); 1786 kfree(extent_op);
1787 unlock_extent(&info->extent_ins, start, end, GFP_NOFS); 1787 unlock_extent(&info->extent_ins, start, end, GFP_NOFS);
1788 search = 0; 1788 if (all)
1789 search = 0;
1790 else
1791 search = end + 1;
1789 1792
1790 cond_resched(); 1793 cond_resched();
1791 } 1794 }
@@ -1992,7 +1995,7 @@ static int __free_extent(struct btrfs_trans_handle *trans,
1992#endif 1995#endif
1993 } 1996 }
1994 btrfs_free_path(path); 1997 btrfs_free_path(path);
1995 finish_current_insert(trans, extent_root); 1998 finish_current_insert(trans, extent_root, 0);
1996 return ret; 1999 return ret;
1997} 2000}
1998 2001
@@ -2001,7 +2004,7 @@ static int __free_extent(struct btrfs_trans_handle *trans,
2001 * them from the extent map 2004 * them from the extent map
2002 */ 2005 */
2003static int del_pending_extents(struct btrfs_trans_handle *trans, struct 2006static int del_pending_extents(struct btrfs_trans_handle *trans, struct
2004 btrfs_root *extent_root) 2007 btrfs_root *extent_root, int all)
2005{ 2008{
2006 int ret; 2009 int ret;
2007 int err = 0; 2010 int err = 0;
@@ -2023,7 +2026,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
2023 EXTENT_WRITEBACK); 2026 EXTENT_WRITEBACK);
2024 if (ret) { 2027 if (ret) {
2025 mutex_unlock(&info->extent_ins_mutex); 2028 mutex_unlock(&info->extent_ins_mutex);
2026 if (search) { 2029 if (all && search) {
2027 search = 0; 2030 search = 0;
2028 continue; 2031 continue;
2029 } 2032 }
@@ -2088,7 +2091,10 @@ free_extent:
2088 err = ret; 2091 err = ret;
2089 unlock_extent(extent_ins, start, end, GFP_NOFS); 2092 unlock_extent(extent_ins, start, end, GFP_NOFS);
2090 2093
2091 search = 0; 2094 if (all)
2095 search = 0;
2096 else
2097 search = end + 1;
2092 cond_resched(); 2098 cond_resched();
2093 } 2099 }
2094 return err; 2100 return err;
@@ -2155,8 +2161,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
2155 root_objectid, ref_generation, 2161 root_objectid, ref_generation,
2156 owner_objectid, pin, pin == 0); 2162 owner_objectid, pin, pin == 0);
2157 2163
2158 finish_current_insert(trans, root->fs_info->extent_root); 2164 finish_current_insert(trans, root->fs_info->extent_root, 0);
2159 pending_ret = del_pending_extents(trans, root->fs_info->extent_root); 2165 pending_ret = del_pending_extents(trans, root->fs_info->extent_root, 0);
2160 return ret ? ret : pending_ret; 2166 return ret ? ret : pending_ret;
2161} 2167}
2162 2168
@@ -2580,8 +2586,8 @@ static int __btrfs_alloc_reserved_extent(struct btrfs_trans_handle *trans,
2580 trans->alloc_exclude_start = 0; 2586 trans->alloc_exclude_start = 0;
2581 trans->alloc_exclude_nr = 0; 2587 trans->alloc_exclude_nr = 0;
2582 btrfs_free_path(path); 2588 btrfs_free_path(path);
2583 finish_current_insert(trans, extent_root); 2589 finish_current_insert(trans, extent_root, 0);
2584 pending_ret = del_pending_extents(trans, extent_root); 2590 pending_ret = del_pending_extents(trans, extent_root, 0);
2585 2591
2586 if (ret) 2592 if (ret)
2587 goto out; 2593 goto out;
@@ -5229,8 +5235,8 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
5229 sizeof(cache->item)); 5235 sizeof(cache->item));
5230 BUG_ON(ret); 5236 BUG_ON(ret);
5231 5237
5232 finish_current_insert(trans, extent_root); 5238 finish_current_insert(trans, extent_root, 0);
5233 ret = del_pending_extents(trans, extent_root); 5239 ret = del_pending_extents(trans, extent_root, 0);
5234 BUG_ON(ret); 5240 BUG_ON(ret);
5235 set_avail_alloc_bits(extent_root->fs_info, type); 5241 set_avail_alloc_bits(extent_root->fs_info, type);
5236 5242