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 ref 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 refs 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
98060e1611
commit
06f77c659e
@@ -1041,6 +1041,59 @@ static noinline int backref_in_log(struct btrfs_root *log,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int unlink_refs_not_in_log(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_path *path,
|
||||
struct btrfs_root *log_root,
|
||||
struct btrfs_key *search_key,
|
||||
struct btrfs_inode *dir,
|
||||
struct btrfs_inode *inode,
|
||||
u64 parent_objectid)
|
||||
{
|
||||
struct extent_buffer *leaf = path->nodes[0];
|
||||
unsigned long ptr;
|
||||
unsigned long ptr_end;
|
||||
|
||||
/*
|
||||
* Check all the names in this back reference to see if they are in the
|
||||
* log. If so, we allow them to stay otherwise they must be unlinked as
|
||||
* a conflict.
|
||||
*/
|
||||
ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
|
||||
ptr_end = ptr + btrfs_item_size(leaf, path->slots[0]);
|
||||
while (ptr < ptr_end) {
|
||||
struct fscrypt_str victim_name;
|
||||
struct btrfs_inode_ref *victim_ref;
|
||||
int ret;
|
||||
|
||||
victim_ref = (struct btrfs_inode_ref *)ptr;
|
||||
ret = read_alloc_one_name(leaf, (victim_ref + 1),
|
||||
btrfs_inode_ref_name_len(leaf, victim_ref),
|
||||
&victim_name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = backref_in_log(log_root, search_key, parent_objectid, &victim_name);
|
||||
if (ret) {
|
||||
kfree(victim_name.name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ptr = (unsigned long)(victim_ref + 1) + victim_name.len;
|
||||
continue;
|
||||
}
|
||||
|
||||
inc_nlink(&inode->vfs_inode);
|
||||
btrfs_release_path(path);
|
||||
|
||||
ret = unlink_inode_for_log_replay(trans, dir, inode, &victim_name);
|
||||
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,
|
||||
@@ -1065,54 +1118,19 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
} else if (ret == 0) {
|
||||
struct btrfs_inode_ref *victim_ref;
|
||||
unsigned long ptr;
|
||||
unsigned long ptr_end;
|
||||
|
||||
leaf = path->nodes[0];
|
||||
|
||||
/* are we trying to overwrite a back ref for the root directory
|
||||
* if so, just jump out, we're done
|
||||
/*
|
||||
* Are we trying to overwrite a back ref for the root directory?
|
||||
* If so, we're done.
|
||||
*/
|
||||
if (search_key.objectid == search_key.offset)
|
||||
return 1;
|
||||
|
||||
/* check all the names in this back reference to see
|
||||
* if they are in the log. if so, we allow them to stay
|
||||
* otherwise they must be unlinked as a conflict
|
||||
*/
|
||||
ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
|
||||
ptr_end = ptr + btrfs_item_size(leaf, path->slots[0]);
|
||||
while (ptr < ptr_end) {
|
||||
struct fscrypt_str victim_name;
|
||||
|
||||
victim_ref = (struct btrfs_inode_ref *)ptr;
|
||||
ret = read_alloc_one_name(leaf, (victim_ref + 1),
|
||||
btrfs_inode_ref_name_len(leaf, victim_ref),
|
||||
&victim_name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = backref_in_log(log_root, &search_key,
|
||||
parent_objectid, &victim_name);
|
||||
if (ret < 0) {
|
||||
kfree(victim_name.name);
|
||||
return ret;
|
||||
} else if (!ret) {
|
||||
inc_nlink(&inode->vfs_inode);
|
||||
btrfs_release_path(path);
|
||||
|
||||
ret = unlink_inode_for_log_replay(trans, dir, inode,
|
||||
&victim_name);
|
||||
kfree(victim_name.name);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto again;
|
||||
}
|
||||
kfree(victim_name.name);
|
||||
|
||||
ptr = (unsigned long)(victim_ref + 1) + victim_name.len;
|
||||
}
|
||||
ret = unlink_refs_not_in_log(trans, path, log_root, &search_key,
|
||||
dir, inode, parent_objectid);
|
||||
if (ret == -EAGAIN)
|
||||
goto again;
|
||||
else if (ret)
|
||||
return ret;
|
||||
}
|
||||
btrfs_release_path(path);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user