diff options
author | Josef Bacik <jbacik@fusionio.com> | 2013-01-31 10:23:04 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-02-20 12:59:11 -0500 |
commit | 0f5d42b287f32417e54485d79f2318cf2970b37d (patch) | |
tree | 6f66c857c212a5d8faa4347c0f1d331e47492c01 /fs/btrfs | |
parent | 0448748849ef7c593be40e2c1404f7974bd3aac6 (diff) | |
download | linux-0f5d42b287f32417e54485d79f2318cf2970b37d.tar.gz linux-0f5d42b287f32417e54485d79f2318cf2970b37d.tar.bz2 linux-0f5d42b287f32417e54485d79f2318cf2970b37d.zip |
Btrfs: remove extent mapping if we fail to add chunk
I got a double free error when unmounting a file system that failed to add a
chunk during its operation. This is because we will kfree the mapping that
we created but leave the extent_map in the em_tree for chunks. So to fix
this just remove the extent_map when we error out so we don't run into this
problem. Thanks,
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/volumes.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 13efbcf03122..c7843349c795 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -3821,9 +3821,10 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, write_lock(&em_tree->lock); ret = add_extent_mapping(em_tree, em); write_unlock(&em_tree->lock); - free_extent_map(em); - if (ret) + if (ret) { + free_extent_map(em); goto error; + } for (i = 0; i < map->num_stripes; ++i) { struct btrfs_device *device; @@ -3848,6 +3849,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, goto error_dev_extent; } + free_extent_map(em); kfree(devices_info); return 0; @@ -3863,6 +3865,14 @@ error_dev_extent: break; } } + write_lock(&em_tree->lock); + remove_extent_mapping(em_tree, em); + write_unlock(&em_tree->lock); + + /* One for our allocation */ + free_extent_map(em); + /* One for the tree reference */ + free_extent_map(em); error: kfree(map); kfree(devices_info); |