diff options
| author | David Woodhouse <David.Woodhouse@intel.com> | 2008-08-19 17:33:04 -0400 |
|---|---|---|
| committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:06 -0400 |
| commit | d54a83901055bb0bffca64fa09fce4d897274870 (patch) | |
| tree | 1fb297e08014eaf28416f4e4fe2058d1e6bb6e1b | |
| parent | 2d4d9fbd6efa858dfa009518fca1ab85a73fd848 (diff) | |
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.c | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c index 36cbc6872fd..292b0b24c30 100644 --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c | |||
| @@ -165,23 +165,32 @@ static struct dentry *btrfs_get_parent(struct dentry *child) | |||
| 165 | key.offset = (u64)-1; | 165 | key.offset = (u64)-1; |
| 166 | 166 | ||
| 167 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 167 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
| 168 | if (ret < 0) { | ||
| 169 | /* Error */ | ||
| 170 | btrfs_free_path(path); | ||
| 171 | return ERR_PTR(ret); | ||
| 172 | } | ||
| 168 | leaf = path->nodes[0]; | 173 | leaf = path->nodes[0]; |
| 169 | slot = path->slots[0]; | 174 | slot = path->slots[0]; |
| 170 | if (ret < 0 || slot == 0) { | 175 | if (ret) { |
| 171 | btrfs_free_path(path); | 176 | /* btrfs_search_slot() returns the slot where we'd want to |
| 172 | goto out; | 177 | insert a backref for parent inode #0xFFFFFFFFFFFFFFFF. |
| 178 | The _real_ backref, telling us what the parent inode | ||
| 179 | _actually_ is, will be in the slot _before_ the one | ||
| 180 | that btrfs_search_slot() returns. */ | ||
| 181 | if (!slot) { | ||
| 182 | /* Unless there is _no_ key in the tree before... */ | ||
| 183 | btrfs_free_path(path); | ||
| 184 | return ERR_PTR(-EIO); | ||
| 185 | } | ||
| 186 | slot--; | ||
| 173 | } | 187 | } |
| 174 | /* btrfs_search_slot() returns the slot where we'd want to insert | ||
| 175 | an INODE_REF_KEY for parent inode #0xFFFFFFFFFFFFFFFF. The _real_ | ||
| 176 | one, telling us what the parent inode _actually_ is, will be in | ||
| 177 | the slot _before_ the one that btrfs_search_slot() returns. */ | ||
| 178 | slot--; | ||
| 179 | 188 | ||
| 180 | btrfs_item_key_to_cpu(leaf, &key, slot); | 189 | btrfs_item_key_to_cpu(leaf, &key, slot); |
| 181 | btrfs_free_path(path); | 190 | btrfs_free_path(path); |
| 182 | 191 | ||
| 183 | if (key.objectid != dir->i_ino || key.type != BTRFS_INODE_REF_KEY) | 192 | if (key.objectid != dir->i_ino || key.type != BTRFS_INODE_REF_KEY) |
| 184 | goto out; | 193 | return ERR_PTR(-EINVAL); |
| 185 | 194 | ||
| 186 | objectid = key.offset; | 195 | objectid = key.offset; |
| 187 | 196 | ||
| @@ -201,10 +210,6 @@ static struct dentry *btrfs_get_parent(struct dentry *child) | |||
| 201 | parent = ERR_PTR(-ENOMEM); | 210 | parent = ERR_PTR(-ENOMEM); |
| 202 | 211 | ||
| 203 | return parent; | 212 | return parent; |
| 204 | |||
| 205 | out: | ||
| 206 | btrfs_free_path(path); | ||
| 207 | return ERR_PTR(-EINVAL); | ||
| 208 | } | 213 | } |
| 209 | 214 | ||
| 210 | const struct export_operations btrfs_export_ops = { | 215 | const struct export_operations btrfs_export_ops = { |
