Commit d3316c82 authored by Nikolay Borisov's avatar Nikolay Borisov Committed by David Sterba

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: default avatarNikolay Borisov <nborisov@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 89cbf5f6
...@@ -952,7 +952,9 @@ static noinline int backref_in_log(struct btrfs_root *log, ...@@ -952,7 +952,9 @@ static noinline int backref_in_log(struct btrfs_root *log,
return -ENOMEM; return -ENOMEM;
ret = btrfs_search_slot(NULL, log, key, path, 0, 0); ret = btrfs_search_slot(NULL, log, key, path, 0, 0);
if (ret != 0) { if (ret < 0) {
goto out;
} else if (ret == 1) {
ret = 0; ret = 0;
goto out; goto out;
} }
...@@ -1026,10 +1028,13 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, ...@@ -1026,10 +1028,13 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
(unsigned long)(victim_ref + 1), (unsigned long)(victim_ref + 1),
victim_name_len); victim_name_len);
if (!backref_in_log(log_root, &search_key, ret = backref_in_log(log_root, &search_key,
parent_objectid, parent_objectid, victim_name,
victim_name, victim_name_len);
victim_name_len)) { if (ret < 0) {
kfree(victim_name);
return ret;
} else if (!ret) {
inc_nlink(&inode->vfs_inode); inc_nlink(&inode->vfs_inode);
btrfs_release_path(path); btrfs_release_path(path);
...@@ -1091,10 +1096,12 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, ...@@ -1091,10 +1096,12 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
search_key.offset = btrfs_extref_hash(parent_objectid, search_key.offset = btrfs_extref_hash(parent_objectid,
victim_name, victim_name,
victim_name_len); victim_name_len);
ret = 0; ret = backref_in_log(log_root, &search_key,
if (!backref_in_log(log_root, &search_key,
parent_objectid, victim_name, parent_objectid, victim_name,
victim_name_len)) { victim_name_len);
if (ret < 0) {
return ret;
} else if (!ret) {
ret = -ENOENT; ret = -ENOENT;
victim_parent = read_one_inode(root, victim_parent = read_one_inode(root,
parent_objectid); parent_objectid);
...@@ -1869,16 +1876,19 @@ static bool name_in_log_ref(struct btrfs_root *log_root, ...@@ -1869,16 +1876,19 @@ static bool name_in_log_ref(struct btrfs_root *log_root,
const u64 dirid, const u64 ino) const u64 dirid, const u64 ino)
{ {
struct btrfs_key search_key; struct btrfs_key search_key;
int ret;
search_key.objectid = ino; search_key.objectid = ino;
search_key.type = BTRFS_INODE_REF_KEY; search_key.type = BTRFS_INODE_REF_KEY;
search_key.offset = dirid; search_key.offset = dirid;
if (backref_in_log(log_root, &search_key, dirid, name, name_len)) ret = backref_in_log(log_root, &search_key, dirid, name, name_len);
if (ret == 1)
return true; return true;
search_key.type = BTRFS_INODE_EXTREF_KEY; search_key.type = BTRFS_INODE_EXTREF_KEY;
search_key.offset = btrfs_extref_hash(dirid, name, name_len); search_key.offset = btrfs_extref_hash(dirid, name, name_len);
if (backref_in_log(log_root, &search_key, dirid, name, name_len)) ret = backref_in_log(log_root, &search_key, dirid, name, name_len);
if (ret == 1)
return true; return true;
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment