mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 02:39:48 +00:00
btrfs: factor out inode items copy loop from btrfs_log_inode()
The function btrfs_log_inode() is quite large and so is its loop which iterates the inode items from the fs/subvolume tree and copies them into a log tree. Because this is a large loop inside a very large function and because an upcoming patch in this series needs to add some more logic inside that loop, move the loop into a helper function to make it a bit more manageable. Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
a5eeb3d17b
commit
da447009a2
1 changed files with 138 additions and 136 deletions
|
@ -4941,6 +4941,138 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int copy_inode_items_to_log(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_inode *inode,
|
||||
struct btrfs_key *min_key,
|
||||
const struct btrfs_key *max_key,
|
||||
struct btrfs_path *path,
|
||||
struct btrfs_path *dst_path,
|
||||
const u64 logged_isize,
|
||||
const bool recursive_logging,
|
||||
const int inode_only,
|
||||
struct btrfs_log_ctx *ctx,
|
||||
bool *need_log_inode_item)
|
||||
{
|
||||
struct btrfs_root *root = inode->root;
|
||||
int ins_start_slot = 0;
|
||||
int ins_nr = 0;
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
ret = btrfs_search_forward(root, min_key, path, trans->transid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret > 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
again:
|
||||
/* Note, ins_nr might be > 0 here, cleanup outside the loop */
|
||||
if (min_key->objectid != max_key->objectid)
|
||||
break;
|
||||
if (min_key->type > max_key->type)
|
||||
break;
|
||||
|
||||
if (min_key->type == BTRFS_INODE_ITEM_KEY)
|
||||
*need_log_inode_item = false;
|
||||
|
||||
if ((min_key->type == BTRFS_INODE_REF_KEY ||
|
||||
min_key->type == BTRFS_INODE_EXTREF_KEY) &&
|
||||
inode->generation == trans->transid &&
|
||||
!recursive_logging) {
|
||||
u64 other_ino = 0;
|
||||
u64 other_parent = 0;
|
||||
|
||||
ret = btrfs_check_ref_name_override(path->nodes[0],
|
||||
path->slots[0], min_key, inode,
|
||||
&other_ino, &other_parent);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
} else if (ret > 0 && ctx &&
|
||||
other_ino != btrfs_ino(BTRFS_I(ctx->inode))) {
|
||||
if (ins_nr > 0) {
|
||||
ins_nr++;
|
||||
} else {
|
||||
ins_nr = 1;
|
||||
ins_start_slot = path->slots[0];
|
||||
}
|
||||
ret = copy_items(trans, inode, dst_path, path,
|
||||
ins_start_slot, ins_nr,
|
||||
inode_only, logged_isize);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ins_nr = 0;
|
||||
|
||||
ret = log_conflicting_inodes(trans, root, path,
|
||||
ctx, other_ino, other_parent);
|
||||
if (ret)
|
||||
return ret;
|
||||
btrfs_release_path(path);
|
||||
goto next_key;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip xattrs, we log them later with btrfs_log_all_xattrs() */
|
||||
if (min_key->type == BTRFS_XATTR_ITEM_KEY) {
|
||||
if (ins_nr == 0)
|
||||
goto next_slot;
|
||||
ret = copy_items(trans, inode, dst_path, path,
|
||||
ins_start_slot,
|
||||
ins_nr, inode_only, logged_isize);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ins_nr = 0;
|
||||
goto next_slot;
|
||||
}
|
||||
|
||||
if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) {
|
||||
ins_nr++;
|
||||
goto next_slot;
|
||||
} else if (!ins_nr) {
|
||||
ins_start_slot = path->slots[0];
|
||||
ins_nr = 1;
|
||||
goto next_slot;
|
||||
}
|
||||
|
||||
ret = copy_items(trans, inode, dst_path, path, ins_start_slot,
|
||||
ins_nr, inode_only, logged_isize);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ins_nr = 1;
|
||||
ins_start_slot = path->slots[0];
|
||||
next_slot:
|
||||
path->slots[0]++;
|
||||
if (path->slots[0] < btrfs_header_nritems(path->nodes[0])) {
|
||||
btrfs_item_key_to_cpu(path->nodes[0], min_key,
|
||||
path->slots[0]);
|
||||
goto again;
|
||||
}
|
||||
if (ins_nr) {
|
||||
ret = copy_items(trans, inode, dst_path, path,
|
||||
ins_start_slot, ins_nr, inode_only,
|
||||
logged_isize);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ins_nr = 0;
|
||||
}
|
||||
btrfs_release_path(path);
|
||||
next_key:
|
||||
if (min_key->offset < (u64)-1) {
|
||||
min_key->offset++;
|
||||
} else if (min_key->type < max_key->type) {
|
||||
min_key->type++;
|
||||
min_key->offset = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ins_nr)
|
||||
ret = copy_items(trans, inode, dst_path, path, ins_start_slot,
|
||||
ins_nr, inode_only, logged_isize);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* log a single inode in the tree log.
|
||||
* At least one parent directory for this inode must exist in the tree
|
||||
* or be logged already.
|
||||
|
@ -4970,9 +5102,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
|
|||
struct btrfs_root *log = root->log_root;
|
||||
int err = 0;
|
||||
int ret;
|
||||
int nritems;
|
||||
int ins_start_slot = 0;
|
||||
int ins_nr;
|
||||
bool fast_search = false;
|
||||
u64 ino = btrfs_ino(inode);
|
||||
struct extent_map_tree *em_tree = &inode->extent_tree;
|
||||
|
@ -5103,139 +5232,12 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
ins_nr = 0;
|
||||
ret = btrfs_search_forward(root, &min_key,
|
||||
path, trans->transid);
|
||||
if (ret < 0) {
|
||||
err = ret;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (ret != 0)
|
||||
break;
|
||||
again:
|
||||
/* note, ins_nr might be > 0 here, cleanup outside the loop */
|
||||
if (min_key.objectid != ino)
|
||||
break;
|
||||
if (min_key.type > max_key.type)
|
||||
break;
|
||||
|
||||
if (min_key.type == BTRFS_INODE_ITEM_KEY)
|
||||
need_log_inode_item = false;
|
||||
|
||||
if ((min_key.type == BTRFS_INODE_REF_KEY ||
|
||||
min_key.type == BTRFS_INODE_EXTREF_KEY) &&
|
||||
inode->generation == trans->transid &&
|
||||
!recursive_logging) {
|
||||
u64 other_ino = 0;
|
||||
u64 other_parent = 0;
|
||||
|
||||
ret = btrfs_check_ref_name_override(path->nodes[0],
|
||||
path->slots[0], &min_key, inode,
|
||||
&other_ino, &other_parent);
|
||||
if (ret < 0) {
|
||||
err = ret;
|
||||
goto out_unlock;
|
||||
} else if (ret > 0 && ctx &&
|
||||
other_ino != btrfs_ino(BTRFS_I(ctx->inode))) {
|
||||
if (ins_nr > 0) {
|
||||
ins_nr++;
|
||||
} else {
|
||||
ins_nr = 1;
|
||||
ins_start_slot = path->slots[0];
|
||||
}
|
||||
ret = copy_items(trans, inode, dst_path, path,
|
||||
ins_start_slot,
|
||||
ins_nr, inode_only,
|
||||
logged_isize);
|
||||
if (ret < 0) {
|
||||
err = ret;
|
||||
goto out_unlock;
|
||||
}
|
||||
ins_nr = 0;
|
||||
|
||||
err = log_conflicting_inodes(trans, root, path,
|
||||
ctx, other_ino, other_parent);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
btrfs_release_path(path);
|
||||
goto next_key;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip xattrs, we log them later with btrfs_log_all_xattrs() */
|
||||
if (min_key.type == BTRFS_XATTR_ITEM_KEY) {
|
||||
if (ins_nr == 0)
|
||||
goto next_slot;
|
||||
ret = copy_items(trans, inode, dst_path, path,
|
||||
ins_start_slot,
|
||||
ins_nr, inode_only, logged_isize);
|
||||
if (ret < 0) {
|
||||
err = ret;
|
||||
goto out_unlock;
|
||||
}
|
||||
ins_nr = 0;
|
||||
goto next_slot;
|
||||
}
|
||||
|
||||
if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) {
|
||||
ins_nr++;
|
||||
goto next_slot;
|
||||
} else if (!ins_nr) {
|
||||
ins_start_slot = path->slots[0];
|
||||
ins_nr = 1;
|
||||
goto next_slot;
|
||||
}
|
||||
|
||||
ret = copy_items(trans, inode, dst_path, path,
|
||||
ins_start_slot, ins_nr, inode_only,
|
||||
logged_isize);
|
||||
if (ret < 0) {
|
||||
err = ret;
|
||||
goto out_unlock;
|
||||
}
|
||||
ins_nr = 1;
|
||||
ins_start_slot = path->slots[0];
|
||||
next_slot:
|
||||
|
||||
nritems = btrfs_header_nritems(path->nodes[0]);
|
||||
path->slots[0]++;
|
||||
if (path->slots[0] < nritems) {
|
||||
btrfs_item_key_to_cpu(path->nodes[0], &min_key,
|
||||
path->slots[0]);
|
||||
goto again;
|
||||
}
|
||||
if (ins_nr) {
|
||||
ret = copy_items(trans, inode, dst_path, path,
|
||||
ins_start_slot,
|
||||
ins_nr, inode_only, logged_isize);
|
||||
if (ret < 0) {
|
||||
err = ret;
|
||||
goto out_unlock;
|
||||
}
|
||||
ins_nr = 0;
|
||||
}
|
||||
btrfs_release_path(path);
|
||||
next_key:
|
||||
if (min_key.offset < (u64)-1) {
|
||||
min_key.offset++;
|
||||
} else if (min_key.type < max_key.type) {
|
||||
min_key.type++;
|
||||
min_key.offset = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ins_nr) {
|
||||
ret = copy_items(trans, inode, dst_path, path,
|
||||
ins_start_slot, ins_nr, inode_only,
|
||||
logged_isize);
|
||||
if (ret < 0) {
|
||||
err = ret;
|
||||
goto out_unlock;
|
||||
}
|
||||
ins_nr = 0;
|
||||
}
|
||||
err = copy_inode_items_to_log(trans, inode, &min_key, &max_key,
|
||||
path, dst_path, logged_isize,
|
||||
recursive_logging, inode_only, ctx,
|
||||
&need_log_inode_item);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
btrfs_release_path(path);
|
||||
btrfs_release_path(dst_path);
|
||||
|
|
Loading…
Reference in a new issue