aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 321ec0de0733..7d1b21df698d 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -336,6 +336,9 @@ struct walk_control {
*/
struct btrfs_root *root;
+ /* The log tree we are currently processing (not NULL for any stage). */
+ struct btrfs_root *log;
+
/* the trans handle for the current replay */
struct btrfs_trans_handle *trans;
@@ -344,17 +347,17 @@ struct walk_control {
* passed in, and it must be checked or read if you need the data
* inside it
*/
- int (*process_func)(struct btrfs_root *log, struct extent_buffer *eb,
+ int (*process_func)(struct extent_buffer *eb,
struct walk_control *wc, u64 gen, int level);
};
/*
* process_func used to pin down extents, write them or wait on them
*/
-static int process_one_buffer(struct btrfs_root *log,
- struct extent_buffer *eb,
+static int process_one_buffer(struct extent_buffer *eb,
struct walk_control *wc, u64 gen, int level)
{
+ struct btrfs_root *log = wc->log;
struct btrfs_trans_handle *trans = wc->trans;
struct btrfs_fs_info *fs_info = log->fs_info;
int ret = 0;
@@ -2569,7 +2572,7 @@ out:
* only in the log (references come from either directory items or inode
* back refs).
*/
-static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
+static int replay_one_buffer(struct extent_buffer *eb,
struct walk_control *wc, u64 gen, int level)
{
int nritems;
@@ -2579,6 +2582,7 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
};
struct btrfs_path *path;
struct btrfs_root *root = wc->root;
+ struct btrfs_root *log = wc->log;
struct btrfs_trans_handle *trans = wc->trans;
struct btrfs_key key;
int i;
@@ -2779,11 +2783,10 @@ static int clean_log_buffer(struct btrfs_trans_handle *trans,
}
static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
- struct btrfs_root *log,
struct btrfs_path *path, int *level,
struct walk_control *wc)
{
- struct btrfs_fs_info *fs_info = log->fs_info;
+ struct btrfs_fs_info *fs_info = wc->log->fs_info;
u64 bytenr;
u64 ptr_gen;
struct extent_buffer *next;
@@ -2821,7 +2824,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
}
if (*level == 1) {
- ret = wc->process_func(log, next, wc, ptr_gen, *level - 1);
+ ret = wc->process_func(next, wc, ptr_gen, *level - 1);
if (ret) {
free_extent_buffer(next);
return ret;
@@ -2872,7 +2875,6 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
}
static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
- struct btrfs_root *log,
struct btrfs_path *path, int *level,
struct walk_control *wc)
{
@@ -2888,7 +2890,7 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
WARN_ON(*level == 0);
return 0;
} else {
- ret = wc->process_func(log, path->nodes[*level], wc,
+ ret = wc->process_func(path->nodes[*level], wc,
btrfs_header_generation(path->nodes[*level]),
*level);
if (ret)
@@ -2912,9 +2914,9 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
* the tree freeing any blocks that have a ref count of zero after being
* decremented.
*/
-static int walk_log_tree(struct btrfs_trans_handle *trans,
- struct btrfs_root *log, struct walk_control *wc)
+static int walk_log_tree(struct btrfs_trans_handle *trans, struct walk_control *wc)
{
+ struct btrfs_root *log = wc->log;
int ret = 0;
int wret;
int level;
@@ -2932,7 +2934,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
path->slots[level] = 0;
while (1) {
- wret = walk_down_log_tree(trans, log, path, &level, wc);
+ wret = walk_down_log_tree(trans, path, &level, wc);
if (wret > 0)
break;
if (wret < 0) {
@@ -2940,7 +2942,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
goto out;
}
- wret = walk_up_log_tree(trans, log, path, &level, wc);
+ wret = walk_up_log_tree(trans, path, &level, wc);
if (wret > 0)
break;
if (wret < 0) {
@@ -2951,7 +2953,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
/* was the root node processed? if not, catch it here */
if (path->nodes[orig_level]) {
- ret = wc->process_func(log, path->nodes[orig_level], wc,
+ ret = wc->process_func(path->nodes[orig_level], wc,
btrfs_header_generation(path->nodes[orig_level]),
orig_level);
if (ret)
@@ -3423,11 +3425,12 @@ static void free_log_tree(struct btrfs_trans_handle *trans,
int ret;
struct walk_control wc = {
.free = true,
- .process_func = process_one_buffer
+ .process_func = process_one_buffer,
+ .log = log,
};
if (log->node) {
- ret = walk_log_tree(trans, log, &wc);
+ ret = walk_log_tree(trans, &wc);
if (ret) {
/*
* We weren't able to traverse the entire log tree, the
@@ -7441,8 +7444,10 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
wc.trans = trans;
wc.pin = true;
+ wc.log = log_root_tree;
- ret = walk_log_tree(trans, log_root_tree, &wc);
+ ret = walk_log_tree(trans, &wc);
+ wc.log = NULL;
if (ret) {
btrfs_abort_transaction(trans, ret);
goto error;
@@ -7454,7 +7459,6 @@ again:
key.offset = (u64)-1;
while (1) {
- struct btrfs_root *log;
struct btrfs_key found_key;
ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0);
@@ -7474,9 +7478,10 @@ again:
if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID)
break;
- log = btrfs_read_tree_root(log_root_tree, &found_key);
- if (IS_ERR(log)) {
- ret = PTR_ERR(log);
+ wc.log = btrfs_read_tree_root(log_root_tree, &found_key);
+ if (IS_ERR(wc.log)) {
+ ret = PTR_ERR(wc.log);
+ wc.log = NULL;
btrfs_abort_transaction(trans, ret);
goto error;
}
@@ -7486,7 +7491,8 @@ again:
ret = PTR_ERR(wc.root);
wc.root = NULL;
if (ret != -ENOENT) {
- btrfs_put_root(log);
+ btrfs_put_root(wc.log);
+ wc.log = NULL;
btrfs_abort_transaction(trans, ret);
goto error;
}
@@ -7502,23 +7508,24 @@ again:
* block from being modified, and we'll just bail for
* each subsequent pass.
*/
- ret = btrfs_pin_extent_for_log_replay(trans, log->node);
+ ret = btrfs_pin_extent_for_log_replay(trans, wc.log->node);
if (ret) {
- btrfs_put_root(log);
+ btrfs_put_root(wc.log);
+ wc.log = NULL;
btrfs_abort_transaction(trans, ret);
goto error;
}
goto next;
}
- wc.root->log_root = log;
+ wc.root->log_root = wc.log;
ret = btrfs_record_root_in_trans(trans, wc.root);
if (ret) {
btrfs_abort_transaction(trans, ret);
goto next;
}
- ret = walk_log_tree(trans, log, &wc);
+ ret = walk_log_tree(trans, &wc);
if (ret) {
btrfs_abort_transaction(trans, ret);
goto next;
@@ -7551,7 +7558,8 @@ next:
wc.root->log_root = NULL;
btrfs_put_root(wc.root);
}
- btrfs_put_root(log);
+ btrfs_put_root(wc.log);
+ wc.log = NULL;
if (ret)
goto error;