*/
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;
* 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;
* 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;
};
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;
}
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;
}
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;
}
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)
{
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)
* 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;
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) {
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) {
/* 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)
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
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;
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);
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;
}
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;
}
* 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;
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;