aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-01-29 15:03:37 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-20 12:59:10 -0500
commit0448748849ef7c593be40e2c1404f7974bd3aac6 (patch)
treee964e58dc077f4f5576213e3210b8792d9794745 /fs
parent87533c475187c1420794a2e164bc67a7974f1327 (diff)
Btrfs: fix chunk allocation error handling
If we error out allocating a dev extent we will have already created the block group and such which will cause problems since the allocator may have tried to allocate out of the block group that no longer exists. This will cause BUG_ON()'s in the bio submission path. This also makes a failure to allocate a dev extent a non-abort error, we will just clean up the dev extents we did allocate and exit. Now if we fail to delete the dev extents we will abort since we can't have half of the dev extents hanging around, but this will make us much less likely to abort. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/volumes.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 8c9ea4cd66bb..13efbcf03122 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3825,12 +3825,6 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3825 if (ret) 3825 if (ret)
3826 goto error; 3826 goto error;
3827 3827
3828 ret = btrfs_make_block_group(trans, extent_root, 0, type,
3829 BTRFS_FIRST_CHUNK_TREE_OBJECTID,
3830 start, num_bytes);
3831 if (ret)
3832 goto error;
3833
3834 for (i = 0; i < map->num_stripes; ++i) { 3828 for (i = 0; i < map->num_stripes; ++i) {
3835 struct btrfs_device *device; 3829 struct btrfs_device *device;
3836 u64 dev_offset; 3830 u64 dev_offset;
@@ -3842,15 +3836,33 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3842 info->chunk_root->root_key.objectid, 3836 info->chunk_root->root_key.objectid,
3843 BTRFS_FIRST_CHUNK_TREE_OBJECTID, 3837 BTRFS_FIRST_CHUNK_TREE_OBJECTID,
3844 start, dev_offset, stripe_size); 3838 start, dev_offset, stripe_size);
3845 if (ret) { 3839 if (ret)
3846 btrfs_abort_transaction(trans, extent_root, ret); 3840 goto error_dev_extent;
3847 goto error; 3841 }
3848 } 3842
3843 ret = btrfs_make_block_group(trans, extent_root, 0, type,
3844 BTRFS_FIRST_CHUNK_TREE_OBJECTID,
3845 start, num_bytes);
3846 if (ret) {
3847 i = map->num_stripes - 1;
3848 goto error_dev_extent;
3849 } 3849 }
3850 3850
3851 kfree(devices_info); 3851 kfree(devices_info);
3852 return 0; 3852 return 0;
3853 3853
3854error_dev_extent:
3855 for (; i >= 0; i--) {
3856 struct btrfs_device *device;
3857 int err;
3858
3859 device = map->stripes[i].dev;
3860 err = btrfs_free_dev_extent(trans, device, start);
3861 if (err) {
3862 btrfs_abort_transaction(trans, extent_root, err);
3863 break;
3864 }
3865 }
3854error: 3866error:
3855 kfree(map); 3867 kfree(map);
3856 kfree(devices_info); 3868 kfree(devices_info);