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:
Filipe Manana
2025-06-23 12:54:40 +01:00
committed by David Sterba
parent 06f77c659e
commit 0c6f37eaa5

View File

@@ -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);