Skip to content

Commit a5f2f4d

Browse files
fdmananakdave
authored andcommitted
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. Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 4b3a54e commit a5f2f4d

File tree

1 file changed

+62
-44
lines changed

1 file changed

+62
-44
lines changed

fs/btrfs/tree-log.c

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,59 @@ static noinline int backref_in_log(struct btrfs_root *log,
10411041
return ret;
10421042
}
10431043

1044+
static int unlink_refs_not_in_log(struct btrfs_trans_handle *trans,
1045+
struct btrfs_path *path,
1046+
struct btrfs_root *log_root,
1047+
struct btrfs_key *search_key,
1048+
struct btrfs_inode *dir,
1049+
struct btrfs_inode *inode,
1050+
u64 parent_objectid)
1051+
{
1052+
struct extent_buffer *leaf = path->nodes[0];
1053+
unsigned long ptr;
1054+
unsigned long ptr_end;
1055+
1056+
/*
1057+
* Check all the names in this back reference to see if thet are in the
1058+
* log. If so, we allow them to stay otherwise they must be unlinked as
1059+
* a conflict.
1060+
*/
1061+
ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
1062+
ptr_end = ptr + btrfs_item_size(leaf, path->slots[0]);
1063+
while (ptr < ptr_end) {
1064+
struct fscrypt_str victim_name;
1065+
struct btrfs_inode_ref *victim_ref;
1066+
int ret;
1067+
1068+
victim_ref = (struct btrfs_inode_ref *)ptr;
1069+
ret = read_alloc_one_name(leaf, (victim_ref + 1),
1070+
btrfs_inode_ref_name_len(leaf, victim_ref),
1071+
&victim_name);
1072+
if (ret)
1073+
return ret;
1074+
1075+
ret = backref_in_log(log_root, search_key, parent_objectid, &victim_name);
1076+
if (ret) {
1077+
kfree(victim_name.name);
1078+
if (ret < 0)
1079+
return ret;
1080+
ptr = (unsigned long)(victim_ref + 1) + victim_name.len;
1081+
continue;
1082+
}
1083+
1084+
inc_nlink(&inode->vfs_inode);
1085+
btrfs_release_path(path);
1086+
1087+
ret = unlink_inode_for_log_replay(trans, dir, inode, &victim_name);
1088+
kfree(victim_name.name);
1089+
if (ret)
1090+
return ret;
1091+
return -EAGAIN;
1092+
}
1093+
1094+
return 0;
1095+
}
1096+
10441097
static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
10451098
struct btrfs_root *root,
10461099
struct btrfs_path *path,
@@ -1065,54 +1118,19 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
10651118
if (ret < 0) {
10661119
return ret;
10671120
} else if (ret == 0) {
1068-
struct btrfs_inode_ref *victim_ref;
1069-
unsigned long ptr;
1070-
unsigned long ptr_end;
1071-
1072-
leaf = path->nodes[0];
1073-
1074-
/* are we trying to overwrite a back ref for the root directory
1075-
* if so, just jump out, we're done
1121+
/*
1122+
* Are we trying to overwrite a back ref for the root directory?
1123+
* If so, we're done.
10761124
*/
10771125
if (search_key.objectid == search_key.offset)
10781126
return 1;
10791127

1080-
/* check all the names in this back reference to see
1081-
* if they are in the log. if so, we allow them to stay
1082-
* otherwise they must be unlinked as a conflict
1083-
*/
1084-
ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
1085-
ptr_end = ptr + btrfs_item_size(leaf, path->slots[0]);
1086-
while (ptr < ptr_end) {
1087-
struct fscrypt_str victim_name;
1088-
1089-
victim_ref = (struct btrfs_inode_ref *)ptr;
1090-
ret = read_alloc_one_name(leaf, (victim_ref + 1),
1091-
btrfs_inode_ref_name_len(leaf, victim_ref),
1092-
&victim_name);
1093-
if (ret)
1094-
return ret;
1095-
1096-
ret = backref_in_log(log_root, &search_key,
1097-
parent_objectid, &victim_name);
1098-
if (ret < 0) {
1099-
kfree(victim_name.name);
1100-
return ret;
1101-
} else if (!ret) {
1102-
inc_nlink(&inode->vfs_inode);
1103-
btrfs_release_path(path);
1104-
1105-
ret = unlink_inode_for_log_replay(trans, dir, inode,
1106-
&victim_name);
1107-
kfree(victim_name.name);
1108-
if (ret)
1109-
return ret;
1110-
goto again;
1111-
}
1112-
kfree(victim_name.name);
1113-
1114-
ptr = (unsigned long)(victim_ref + 1) + victim_name.len;
1115-
}
1128+
ret = unlink_refs_not_in_log(trans, path, log_root, &search_key,
1129+
dir, inode, parent_objectid);
1130+
if (ret == -EAGAIN)
1131+
goto again;
1132+
else if (ret)
1133+
return ret;
11161134
}
11171135
btrfs_release_path(path);
11181136

0 commit comments

Comments
 (0)