mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-13 17:39:23 -04:00
btrfs: split inode extref processing from __add_inode_ref() into a helper
The __add_inode_ref() function is quite big and with too much nesting, so move the code that processes inode extrefs into a helper function, to make the function easier to read and reduce the level of indentation too. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Qu Wenruo <wqu@suse.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:
committed by
David Sterba
parent
06f77c659e
commit
0c6f37eaa5
@@ -1094,6 +1094,73 @@ static int unlink_refs_not_in_log(struct btrfs_trans_handle *trans,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unlink_extrefs_not_in_log(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_path *path,
|
||||
struct btrfs_root *root,
|
||||
struct btrfs_root *log_root,
|
||||
struct btrfs_key *search_key,
|
||||
struct btrfs_inode *inode,
|
||||
u64 inode_objectid,
|
||||
u64 parent_objectid)
|
||||
{
|
||||
struct extent_buffer *leaf = path->nodes[0];
|
||||
const unsigned long base = btrfs_item_ptr_offset(leaf, path->slots[0]);
|
||||
const u32 item_size = btrfs_item_size(leaf, path->slots[0]);
|
||||
u32 cur_offset = 0;
|
||||
|
||||
while (cur_offset < item_size) {
|
||||
struct btrfs_inode_extref *extref;
|
||||
struct btrfs_inode *victim_parent;
|
||||
struct fscrypt_str victim_name;
|
||||
int ret;
|
||||
|
||||
extref = (struct btrfs_inode_extref *)(base + cur_offset);
|
||||
victim_name.len = btrfs_inode_extref_name_len(leaf, extref);
|
||||
|
||||
if (btrfs_inode_extref_parent(leaf, extref) != parent_objectid)
|
||||
goto next;
|
||||
|
||||
ret = read_alloc_one_name(leaf, &extref->name, victim_name.len,
|
||||
&victim_name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
search_key->objectid = inode_objectid;
|
||||
search_key->type = BTRFS_INODE_EXTREF_KEY;
|
||||
search_key->offset = btrfs_extref_hash(parent_objectid,
|
||||
victim_name.name,
|
||||
victim_name.len);
|
||||
ret = backref_in_log(log_root, search_key, parent_objectid, &victim_name);
|
||||
if (ret) {
|
||||
kfree(victim_name.name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
next:
|
||||
cur_offset += victim_name.len + sizeof(*extref);
|
||||
continue;
|
||||
}
|
||||
|
||||
victim_parent = btrfs_iget_logging(parent_objectid, root);
|
||||
if (IS_ERR(victim_parent)) {
|
||||
kfree(victim_name.name);
|
||||
return PTR_ERR(victim_parent);
|
||||
}
|
||||
|
||||
inc_nlink(&inode->vfs_inode);
|
||||
btrfs_release_path(path);
|
||||
|
||||
ret = unlink_inode_for_log_replay(trans, victim_parent, inode,
|
||||
&victim_name);
|
||||
iput(&victim_parent->vfs_inode);
|
||||
kfree(victim_name.name);
|
||||
if (ret)
|
||||
return ret;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct btrfs_path *path,
|
||||
@@ -1104,7 +1171,6 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
|
||||
u64 ref_index, struct fscrypt_str *name)
|
||||
{
|
||||
int ret;
|
||||
struct extent_buffer *leaf;
|
||||
struct btrfs_dir_item *di;
|
||||
struct btrfs_key search_key;
|
||||
struct btrfs_inode_extref *extref;
|
||||
@@ -1139,62 +1205,13 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
|
||||
if (IS_ERR(extref)) {
|
||||
return PTR_ERR(extref);
|
||||
} else if (extref) {
|
||||
u32 item_size;
|
||||
u32 cur_offset = 0;
|
||||
unsigned long base;
|
||||
struct btrfs_inode *victim_parent;
|
||||
|
||||
leaf = path->nodes[0];
|
||||
|
||||
item_size = btrfs_item_size(leaf, path->slots[0]);
|
||||
base = btrfs_item_ptr_offset(leaf, path->slots[0]);
|
||||
|
||||
while (cur_offset < item_size) {
|
||||
struct fscrypt_str victim_name;
|
||||
|
||||
extref = (struct btrfs_inode_extref *)(base + cur_offset);
|
||||
victim_name.len = btrfs_inode_extref_name_len(leaf, extref);
|
||||
|
||||
if (btrfs_inode_extref_parent(leaf, extref) != parent_objectid)
|
||||
goto next;
|
||||
|
||||
ret = read_alloc_one_name(leaf, &extref->name,
|
||||
victim_name.len, &victim_name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
search_key.objectid = inode_objectid;
|
||||
search_key.type = BTRFS_INODE_EXTREF_KEY;
|
||||
search_key.offset = btrfs_extref_hash(parent_objectid,
|
||||
victim_name.name,
|
||||
victim_name.len);
|
||||
ret = backref_in_log(log_root, &search_key,
|
||||
parent_objectid, &victim_name);
|
||||
if (ret < 0) {
|
||||
kfree(victim_name.name);
|
||||
return ret;
|
||||
} else if (!ret) {
|
||||
victim_parent = btrfs_iget_logging(parent_objectid, root);
|
||||
if (IS_ERR(victim_parent)) {
|
||||
ret = PTR_ERR(victim_parent);
|
||||
} else {
|
||||
inc_nlink(&inode->vfs_inode);
|
||||
btrfs_release_path(path);
|
||||
|
||||
ret = unlink_inode_for_log_replay(trans,
|
||||
victim_parent,
|
||||
inode, &victim_name);
|
||||
iput(&victim_parent->vfs_inode);
|
||||
}
|
||||
kfree(victim_name.name);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto again;
|
||||
}
|
||||
kfree(victim_name.name);
|
||||
next:
|
||||
cur_offset += victim_name.len + sizeof(*extref);
|
||||
}
|
||||
ret = unlink_extrefs_not_in_log(trans, path, root, log_root,
|
||||
&search_key, inode,
|
||||
inode_objectid, parent_objectid);
|
||||
if (ret == -EAGAIN)
|
||||
goto again;
|
||||
else if (ret)
|
||||
return ret;
|
||||
}
|
||||
btrfs_release_path(path);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user