Commit 10e958d5 authored by Nikolay Borisov's avatar Nikolay Borisov Committed by David Sterba

btrfs: Call btrfs_pin_reserved_extent only during active transaction

Calling btrfs_pin_reserved_extent makes sense only with a valid
transaction since pinned extents are processed from transaction commit
in btrfs_finish_extent_commit. In case of error it's sufficient to
adjust the reserved counter to account for log tree extents allocated in
the last transaction.

This commit moves btrfs_pin_reserved_extent to be called only with valid
transaction handle and otherwise uses the newly introduced
unaccount_log_buffer to adjust "reserved". If this is not done if a
failure occurs before transaction is committed WARN_ON are going to be
triggered on unmount. This was especially pronounced with generic/475
test.
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 6787bb9f
...@@ -2695,12 +2695,10 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, ...@@ -2695,12 +2695,10 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
struct walk_control *wc) struct walk_control *wc)
{ {
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
u64 root_owner;
u64 bytenr; u64 bytenr;
u64 ptr_gen; u64 ptr_gen;
struct extent_buffer *next; struct extent_buffer *next;
struct extent_buffer *cur; struct extent_buffer *cur;
struct extent_buffer *parent;
u32 blocksize; u32 blocksize;
int ret = 0; int ret = 0;
...@@ -2720,9 +2718,6 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, ...@@ -2720,9 +2718,6 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
btrfs_node_key_to_cpu(cur, &first_key, path->slots[*level]); btrfs_node_key_to_cpu(cur, &first_key, path->slots[*level]);
blocksize = fs_info->nodesize; blocksize = fs_info->nodesize;
parent = path->nodes[*level];
root_owner = btrfs_header_owner(parent);
next = btrfs_find_create_tree_block(fs_info, bytenr); next = btrfs_find_create_tree_block(fs_info, bytenr);
if (IS_ERR(next)) if (IS_ERR(next))
return PTR_ERR(next); return PTR_ERR(next);
...@@ -2750,18 +2745,16 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, ...@@ -2750,18 +2745,16 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
btrfs_clean_tree_block(next); btrfs_clean_tree_block(next);
btrfs_wait_tree_block_writeback(next); btrfs_wait_tree_block_writeback(next);
btrfs_tree_unlock(next); btrfs_tree_unlock(next);
ret = btrfs_pin_reserved_extent(fs_info,
bytenr, blocksize);
if (ret) {
free_extent_buffer(next);
return ret;
}
} else { } else {
if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
clear_extent_buffer_dirty(next); clear_extent_buffer_dirty(next);
} unaccount_log_buffer(fs_info, bytenr);
WARN_ON(root_owner !=
BTRFS_TREE_LOG_OBJECTID);
ret = btrfs_pin_reserved_extent(fs_info,
bytenr, blocksize);
if (ret) {
free_extent_buffer(next);
return ret;
} }
} }
free_extent_buffer(next); free_extent_buffer(next);
...@@ -2792,7 +2785,6 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, ...@@ -2792,7 +2785,6 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
struct walk_control *wc) struct walk_control *wc)
{ {
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
u64 root_owner;
int i; int i;
int slot; int slot;
int ret; int ret;
...@@ -2805,13 +2797,6 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, ...@@ -2805,13 +2797,6 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
WARN_ON(*level == 0); WARN_ON(*level == 0);
return 0; return 0;
} else { } else {
struct extent_buffer *parent;
if (path->nodes[*level] == root->node)
parent = path->nodes[*level];
else
parent = path->nodes[*level + 1];
root_owner = btrfs_header_owner(parent);
ret = wc->process_func(root, path->nodes[*level], wc, ret = wc->process_func(root, path->nodes[*level], wc,
btrfs_header_generation(path->nodes[*level]), btrfs_header_generation(path->nodes[*level]),
*level); *level);
...@@ -2829,17 +2814,18 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, ...@@ -2829,17 +2814,18 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
btrfs_clean_tree_block(next); btrfs_clean_tree_block(next);
btrfs_wait_tree_block_writeback(next); btrfs_wait_tree_block_writeback(next);
btrfs_tree_unlock(next); btrfs_tree_unlock(next);
ret = btrfs_pin_reserved_extent(fs_info,
path->nodes[*level]->start,
path->nodes[*level]->len);
if (ret)
return ret;
} else { } else {
if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
clear_extent_buffer_dirty(next); clear_extent_buffer_dirty(next);
}
WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); unaccount_log_buffer(fs_info,
ret = btrfs_pin_reserved_extent(fs_info, path->nodes[*level]->start);
path->nodes[*level]->start, }
path->nodes[*level]->len);
if (ret)
return ret;
} }
free_extent_buffer(path->nodes[*level]); free_extent_buffer(path->nodes[*level]);
path->nodes[*level] = NULL; path->nodes[*level] = NULL;
...@@ -2910,15 +2896,15 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, ...@@ -2910,15 +2896,15 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
btrfs_clean_tree_block(next); btrfs_clean_tree_block(next);
btrfs_wait_tree_block_writeback(next); btrfs_wait_tree_block_writeback(next);
btrfs_tree_unlock(next); btrfs_tree_unlock(next);
ret = btrfs_pin_reserved_extent(fs_info,
next->start, next->len);
if (ret)
goto out;
} else { } else {
if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags))
clear_extent_buffer_dirty(next); clear_extent_buffer_dirty(next);
unaccount_log_buffer(fs_info, next->start);
} }
ret = btrfs_pin_reserved_extent(fs_info, next->start,
next->len);
if (ret)
goto out;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment