aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-01-31 10:23:04 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-20 12:59:11 -0500
commit0f5d42b287f32417e54485d79f2318cf2970b37d (patch)
tree6f66c857c212a5d8faa4347c0f1d331e47492c01 /fs
parent0448748849ef7c593be40e2c1404f7974bd3aac6 (diff)
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')
-rw-r--r--fs/btrfs/volumes.c14
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,
3821 write_lock(&em_tree->lock); 3821 write_lock(&em_tree->lock);
3822 ret = add_extent_mapping(em_tree, em); 3822 ret = add_extent_mapping(em_tree, em);
3823 write_unlock(&em_tree->lock); 3823 write_unlock(&em_tree->lock);
3824 free_extent_map(em); 3824 if (ret) {
3825 if (ret) 3825 free_extent_map(em);
3826 goto error; 3826 goto error;
3827 }
3827 3828
3828 for (i = 0; i < map->num_stripes; ++i) { 3829 for (i = 0; i < map->num_stripes; ++i) {
3829 struct btrfs_device *device; 3830 struct btrfs_device *device;
@@ -3848,6 +3849,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3848 goto error_dev_extent; 3849 goto error_dev_extent;
3849 } 3850 }
3850 3851
3852 free_extent_map(em);
3851 kfree(devices_info); 3853 kfree(devices_info);
3852 return 0; 3854 return 0;
3853 3855
@@ -3863,6 +3865,14 @@ error_dev_extent:
3863 break; 3865 break;
3864 } 3866 }
3865 } 3867 }
3868 write_lock(&em_tree->lock);
3869 remove_extent_mapping(em_tree, em);
3870 write_unlock(&em_tree->lock);
3871
3872 /* One for our allocation */
3873 free_extent_map(em);
3874 /* One for the tree reference */
3875 free_extent_map(em);
3866error: 3876error:
3867 kfree(map); 3877 kfree(map);
3868 kfree(devices_info); 3878 kfree(devices_info);