Commit 8ad6fcab authored by Chris Mason's avatar Chris Mason

Btrfs: fix the inode ref searches done by btrfs_search_path_in_tree

This is used by the inode lookup ioctl to follow all the backrefs up
to the subvol root.  But the search being done would sometimes land one
past the last item in the leaf instead of finding the backref.

This changes the search to look for the highest possible backref and hop
back one item.  It also fixes a leaked path on failure to find the root.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 1b53ac4d
...@@ -1147,12 +1147,13 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info, ...@@ -1147,12 +1147,13 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
root = btrfs_read_fs_root_no_name(info, &key); root = btrfs_read_fs_root_no_name(info, &key);
if (IS_ERR(root)) { if (IS_ERR(root)) {
printk(KERN_ERR "could not find root %llu\n", tree_id); printk(KERN_ERR "could not find root %llu\n", tree_id);
return -ENOENT; ret = -ENOENT;
goto out;
} }
key.objectid = dirid; key.objectid = dirid;
key.type = BTRFS_INODE_REF_KEY; key.type = BTRFS_INODE_REF_KEY;
key.offset = 0; key.offset = (u64)-1;
while(1) { while(1) {
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
...@@ -1161,6 +1162,8 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info, ...@@ -1161,6 +1162,8 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
l = path->nodes[0]; l = path->nodes[0];
slot = path->slots[0]; slot = path->slots[0];
if (ret > 0 && slot > 0)
slot--;
btrfs_item_key_to_cpu(l, &key, slot); btrfs_item_key_to_cpu(l, &key, slot);
if (ret > 0 && (key.objectid != dirid || if (ret > 0 && (key.objectid != dirid ||
...@@ -1184,7 +1187,7 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info, ...@@ -1184,7 +1187,7 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
btrfs_release_path(root, path); btrfs_release_path(root, path);
key.objectid = key.offset; key.objectid = key.offset;
key.offset = 0; key.offset = (u64)-1;
dirid = key.objectid; dirid = key.objectid;
} }
......
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