aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2010-03-18 12:23:10 -0400
committerChris Mason <chris.mason@oracle.com>2010-03-18 12:23:10 -0400
commit8ad6fcab564c5bc956bdc3dfa440ab152b6e780f (patch)
tree38670d63e5315650f3e6efe2a2a8025e945b4743 /fs/btrfs/ioctl.c
parent1b53ac4d1b75b23bdc2b54ace787b8f718a987ef (diff)
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: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 1e462de6556e..2845c6ceecd2 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1147,12 +1147,13 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
1147 root = btrfs_read_fs_root_no_name(info, &key); 1147 root = btrfs_read_fs_root_no_name(info, &key);
1148 if (IS_ERR(root)) { 1148 if (IS_ERR(root)) {
1149 printk(KERN_ERR "could not find root %llu\n", tree_id); 1149 printk(KERN_ERR "could not find root %llu\n", tree_id);
1150 return -ENOENT; 1150 ret = -ENOENT;
1151 goto out;
1151 } 1152 }
1152 1153
1153 key.objectid = dirid; 1154 key.objectid = dirid;
1154 key.type = BTRFS_INODE_REF_KEY; 1155 key.type = BTRFS_INODE_REF_KEY;
1155 key.offset = 0; 1156 key.offset = (u64)-1;
1156 1157
1157 while(1) { 1158 while(1) {
1158 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 1159 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 1162
1162 l = path->nodes[0]; 1163 l = path->nodes[0];
1163 slot = path->slots[0]; 1164 slot = path->slots[0];
1165 if (ret > 0 && slot > 0)
1166 slot--;
1164 btrfs_item_key_to_cpu(l, &key, slot); 1167 btrfs_item_key_to_cpu(l, &key, slot);
1165 1168
1166 if (ret > 0 && (key.objectid != dirid || 1169 if (ret > 0 && (key.objectid != dirid ||
@@ -1184,7 +1187,7 @@ static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
1184 1187
1185 btrfs_release_path(root, path); 1188 btrfs_release_path(root, path);
1186 key.objectid = key.offset; 1189 key.objectid = key.offset;
1187 key.offset = 0; 1190 key.offset = (u64)-1;
1188 dirid = key.objectid; 1191 dirid = key.objectid;
1189 1192
1190 } 1193 }