Skip to content

Commit

Permalink
Btrfs: prevent looping forever in finish_current_insert and del_pendi…
Browse files Browse the repository at this point in the history
…ng_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>
  • Loading branch information
Chris Mason committed Oct 30, 2008
1 parent 09fde3c commit 87ef2bb
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 24 deletions.
54 changes: 30 additions & 24 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ struct pending_extent_op {
};

static int finish_current_insert(struct btrfs_trans_handle *trans, struct
btrfs_root *extent_root);
btrfs_root *extent_root, int all);
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
btrfs_root *extent_root);
btrfs_root *extent_root, int all);
static struct btrfs_block_group_cache *
__btrfs_find_block_group(struct btrfs_root *root,
struct btrfs_block_group_cache *hint,
Expand Down Expand Up @@ -711,8 +711,8 @@ static int __btrfs_update_extent_ref(struct btrfs_trans_handle *trans,
parent, ref_root, ref_generation,
owner_objectid);
BUG_ON(ret);
finish_current_insert(trans, extent_root);
del_pending_extents(trans, extent_root);
finish_current_insert(trans, extent_root, 0);
del_pending_extents(trans, extent_root, 0);
out:
btrfs_free_path(path);
return ret;
Expand Down Expand Up @@ -784,8 +784,8 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
ref_root, ref_generation,
owner_objectid);
BUG_ON(ret);
finish_current_insert(trans, root->fs_info->extent_root);
del_pending_extents(trans, root->fs_info->extent_root);
finish_current_insert(trans, root->fs_info->extent_root, 0);
del_pending_extents(trans, root->fs_info->extent_root, 0);

btrfs_free_path(path);
return 0;
Expand All @@ -810,8 +810,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
finish_current_insert(trans, root->fs_info->extent_root);
del_pending_extents(trans, root->fs_info->extent_root);
finish_current_insert(trans, root->fs_info->extent_root, 1);
del_pending_extents(trans, root->fs_info->extent_root, 1);
return 0;
}

Expand Down Expand Up @@ -1292,8 +1292,8 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
btrfs_mark_buffer_dirty(leaf);
btrfs_release_path(extent_root, path);
fail:
finish_current_insert(trans, extent_root);
pending_ret = del_pending_extents(trans, extent_root);
finish_current_insert(trans, extent_root, 0);
pending_ret = del_pending_extents(trans, extent_root, 0);
if (ret)
return ret;
if (pending_ret)
Expand Down Expand Up @@ -1690,7 +1690,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
}

static int finish_current_insert(struct btrfs_trans_handle *trans,
struct btrfs_root *extent_root)
struct btrfs_root *extent_root, int all)
{
u64 start;
u64 end;
Expand All @@ -1714,7 +1714,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
&end, EXTENT_WRITEBACK);
if (ret) {
mutex_unlock(&info->extent_ins_mutex);
if (search) {
if (search && all) {
search = 0;
continue;
}
Expand All @@ -1723,7 +1723,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,

ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS);
if (!ret) {
search = end+1;
search = end + 1;
mutex_unlock(&info->extent_ins_mutex);
cond_resched();
continue;
Expand Down Expand Up @@ -1785,7 +1785,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
}
kfree(extent_op);
unlock_extent(&info->extent_ins, start, end, GFP_NOFS);
search = 0;
if (all)
search = 0;
else
search = end + 1;

cond_resched();
}
Expand Down Expand Up @@ -1992,7 +1995,7 @@ static int __free_extent(struct btrfs_trans_handle *trans,
#endif
}
btrfs_free_path(path);
finish_current_insert(trans, extent_root);
finish_current_insert(trans, extent_root, 0);
return ret;
}

Expand All @@ -2001,7 +2004,7 @@ static int __free_extent(struct btrfs_trans_handle *trans,
* them from the extent map
*/
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
btrfs_root *extent_root)
btrfs_root *extent_root, int all)
{
int ret;
int err = 0;
Expand All @@ -2023,7 +2026,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
EXTENT_WRITEBACK);
if (ret) {
mutex_unlock(&info->extent_ins_mutex);
if (search) {
if (all && search) {
search = 0;
continue;
}
Expand Down Expand Up @@ -2088,7 +2091,10 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
err = ret;
unlock_extent(extent_ins, start, end, GFP_NOFS);

search = 0;
if (all)
search = 0;
else
search = end + 1;
cond_resched();
}
return err;
Expand Down Expand Up @@ -2155,8 +2161,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
root_objectid, ref_generation,
owner_objectid, pin, pin == 0);

finish_current_insert(trans, root->fs_info->extent_root);
pending_ret = del_pending_extents(trans, root->fs_info->extent_root);
finish_current_insert(trans, root->fs_info->extent_root, 0);
pending_ret = del_pending_extents(trans, root->fs_info->extent_root, 0);
return ret ? ret : pending_ret;
}

Expand Down Expand Up @@ -2580,8 +2586,8 @@ static int __btrfs_alloc_reserved_extent(struct btrfs_trans_handle *trans,
trans->alloc_exclude_start = 0;
trans->alloc_exclude_nr = 0;
btrfs_free_path(path);
finish_current_insert(trans, extent_root);
pending_ret = del_pending_extents(trans, extent_root);
finish_current_insert(trans, extent_root, 0);
pending_ret = del_pending_extents(trans, extent_root, 0);

if (ret)
goto out;
Expand Down Expand Up @@ -5229,8 +5235,8 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
sizeof(cache->item));
BUG_ON(ret);

finish_current_insert(trans, extent_root);
ret = del_pending_extents(trans, extent_root);
finish_current_insert(trans, extent_root, 0);
ret = del_pending_extents(trans, extent_root, 0);
BUG_ON(ret);
set_avail_alloc_bits(extent_root->fs_info, type);

Expand Down
12 changes: 12 additions & 0 deletions fs/btrfs/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,10 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
u64 old_root_bytenr;
struct btrfs_root *tree_root = root->fs_info->tree_root;

btrfs_extent_post_op(trans, root);
btrfs_write_dirty_block_groups(trans, root);
btrfs_extent_post_op(trans, root);

while(1) {
old_root_bytenr = btrfs_root_bytenr(&root->root_item);
if (old_root_bytenr == root->node->start)
Expand All @@ -440,11 +443,15 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
btrfs_set_root_level(&root->root_item,
btrfs_header_level(root->node));
btrfs_set_root_generation(&root->root_item, trans->transid);

btrfs_extent_post_op(trans, root);

ret = btrfs_update_root(trans, tree_root,
&root->root_key,
&root->root_item);
BUG_ON(ret);
btrfs_write_dirty_block_groups(trans, root);
btrfs_extent_post_op(trans, root);
}
return 0;
}
Expand All @@ -459,15 +466,20 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
struct list_head *next;
struct extent_buffer *eb;

btrfs_extent_post_op(trans, fs_info->tree_root);

eb = btrfs_lock_root_node(fs_info->tree_root);
btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb, 0);
btrfs_tree_unlock(eb);
free_extent_buffer(eb);

btrfs_extent_post_op(trans, fs_info->tree_root);

while(!list_empty(&fs_info->dirty_cowonly_roots)) {
next = fs_info->dirty_cowonly_roots.next;
list_del_init(next);
root = list_entry(next, struct btrfs_root, dirty_list);

update_cowonly_root(trans, root);
}
return 0;
Expand Down

0 comments on commit 87ef2bb

Please sign in to comment.