diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2008-08-19 22:33:04 +0100 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:06 -0400 |
commit | d54a83901055bb0bffca64fa09fce4d897274870 (patch) | |
tree | 1fb297e08014eaf28416f4e4fe2058d1e6bb6e1b /fs/btrfs/export.c | |
parent | 2d4d9fbd6efa858dfa009518fca1ab85a73fd848 (diff) | |
download | lwn-d54a83901055bb0bffca64fa09fce4d897274870.tar.gz lwn-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>
Diffstat (limited to 'fs/btrfs/export.c')
-rw-r--r-- | fs/btrfs/export.c | 31 |
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 = { |