summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2008-08-19 22:33:04 +0100
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:06 -0400
commitd54a83901055bb0bffca64fa09fce4d897274870 (patch)
tree1fb297e08014eaf28416f4e4fe2058d1e6bb6e1b
parent2d4d9fbd6efa858dfa009518fca1ab85a73fd848 (diff)
downloadlinux-stable-d54a83901055bb0bffca64fa09fce4d897274870.tar.gz
linux-stable-d54a83901055bb0bffca64fa09fce4d897274870.tar.bz2
linux-stable-d54a83901055bb0bffca64fa09fce4d897274870.zip
Clean up btrfs_get_parent() a little more, fix a free-after-free bug
Date: Tue, 19 Aug 2008 22:33:04 +0100 Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/export.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
index 36cbc6872fd0..292b0b24c302 100644
--- a/fs/btrfs/export.c
+++ b/fs/btrfs/export.c
@@ -165,23 +165,32 @@ static struct dentry *btrfs_get_parent(struct dentry *child)
key.offset = (u64)-1;
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ if (ret < 0) {
+ /* Error */
+ btrfs_free_path(path);
+ return ERR_PTR(ret);
+ }
leaf = path->nodes[0];
slot = path->slots[0];
- if (ret < 0 || slot == 0) {
- btrfs_free_path(path);
- goto out;
+ if (ret) {
+ /* btrfs_search_slot() returns the slot where we'd want to
+ insert a backref for parent inode #0xFFFFFFFFFFFFFFFF.
+ The _real_ backref, telling us what the parent inode
+ _actually_ is, will be in the slot _before_ the one
+ that btrfs_search_slot() returns. */
+ if (!slot) {
+ /* Unless there is _no_ key in the tree before... */
+ btrfs_free_path(path);
+ return ERR_PTR(-EIO);
+ }
+ slot--;
}
- /* btrfs_search_slot() returns the slot where we'd want to insert
- an INODE_REF_KEY for parent inode #0xFFFFFFFFFFFFFFFF. The _real_
- one, telling us what the parent inode _actually_ is, will be in
- the slot _before_ the one that btrfs_search_slot() returns. */
- slot--;
btrfs_item_key_to_cpu(leaf, &key, slot);
btrfs_free_path(path);
if (key.objectid != dir->i_ino || key.type != BTRFS_INODE_REF_KEY)
- goto out;
+ return ERR_PTR(-EINVAL);
objectid = key.offset;
@@ -201,10 +210,6 @@ static struct dentry *btrfs_get_parent(struct dentry *child)
parent = ERR_PTR(-ENOMEM);
return parent;
-
-out:
- btrfs_free_path(path);
- return ERR_PTR(-EINVAL);
}
const struct export_operations btrfs_export_ops = {