Skip to content

Commit d3316c8

Browse files
lorddoskiaskdave
authored andcommitted
btrfs: Properly handle backref_in_log retval
This function can return a negative error value if btrfs_search_slot errors for whatever reason or if btrfs_alloc_path runs out of memory. This is currently problemattic because backref_in_log is treated by its callers as if it returns boolean. Fix this by adding proper error handling in callers. That also enables the function to return the direct error code from btrfs_search_slot. Signed-off-by: Nikolay Borisov <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 89cbf5f commit d3316c8

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

fs/btrfs/tree-log.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,9 @@ static noinline int backref_in_log(struct btrfs_root *log,
952952
return -ENOMEM;
953953

954954
ret = btrfs_search_slot(NULL, log, key, path, 0, 0);
955-
if (ret != 0) {
955+
if (ret < 0) {
956+
goto out;
957+
} else if (ret == 1) {
956958
ret = 0;
957959
goto out;
958960
}
@@ -1026,10 +1028,13 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
10261028
(unsigned long)(victim_ref + 1),
10271029
victim_name_len);
10281030

1029-
if (!backref_in_log(log_root, &search_key,
1030-
parent_objectid,
1031-
victim_name,
1032-
victim_name_len)) {
1031+
ret = backref_in_log(log_root, &search_key,
1032+
parent_objectid, victim_name,
1033+
victim_name_len);
1034+
if (ret < 0) {
1035+
kfree(victim_name);
1036+
return ret;
1037+
} else if (!ret) {
10331038
inc_nlink(&inode->vfs_inode);
10341039
btrfs_release_path(path);
10351040

@@ -1091,10 +1096,12 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
10911096
search_key.offset = btrfs_extref_hash(parent_objectid,
10921097
victim_name,
10931098
victim_name_len);
1094-
ret = 0;
1095-
if (!backref_in_log(log_root, &search_key,
1096-
parent_objectid, victim_name,
1097-
victim_name_len)) {
1099+
ret = backref_in_log(log_root, &search_key,
1100+
parent_objectid, victim_name,
1101+
victim_name_len);
1102+
if (ret < 0) {
1103+
return ret;
1104+
} else if (!ret) {
10981105
ret = -ENOENT;
10991106
victim_parent = read_one_inode(root,
11001107
parent_objectid);
@@ -1869,16 +1876,19 @@ static bool name_in_log_ref(struct btrfs_root *log_root,
18691876
const u64 dirid, const u64 ino)
18701877
{
18711878
struct btrfs_key search_key;
1879+
int ret;
18721880

18731881
search_key.objectid = ino;
18741882
search_key.type = BTRFS_INODE_REF_KEY;
18751883
search_key.offset = dirid;
1876-
if (backref_in_log(log_root, &search_key, dirid, name, name_len))
1884+
ret = backref_in_log(log_root, &search_key, dirid, name, name_len);
1885+
if (ret == 1)
18771886
return true;
18781887

18791888
search_key.type = BTRFS_INODE_EXTREF_KEY;
18801889
search_key.offset = btrfs_extref_hash(dirid, name, name_len);
1881-
if (backref_in_log(log_root, &search_key, dirid, name, name_len))
1890+
ret = backref_in_log(log_root, &search_key, dirid, name, name_len);
1891+
if (ret == 1)
18821892
return true;
18831893

18841894
return false;

0 commit comments

Comments
 (0)