Commit dce580ca authored by Naohiro Aota's avatar Naohiro Aota Committed by David Sterba

btrfs: factor out create_chunk()

Factor out create_chunk() from __btrfs_alloc_chunk(). This function
finally creates a chunk. There is no functional changes.
Reviewed-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 5badf512
...@@ -5019,91 +5019,53 @@ static int decide_stripe_size(struct btrfs_fs_devices *fs_devices, ...@@ -5019,91 +5019,53 @@ static int decide_stripe_size(struct btrfs_fs_devices *fs_devices,
} }
} }
static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, static int create_chunk(struct btrfs_trans_handle *trans,
u64 start, u64 type) struct alloc_chunk_ctl *ctl,
struct btrfs_device_info *devices_info)
{ {
struct btrfs_fs_info *info = trans->fs_info; struct btrfs_fs_info *info = trans->fs_info;
struct btrfs_fs_devices *fs_devices = info->fs_devices;
struct map_lookup *map = NULL; struct map_lookup *map = NULL;
struct extent_map_tree *em_tree; struct extent_map_tree *em_tree;
struct extent_map *em; struct extent_map *em;
struct btrfs_device_info *devices_info = NULL; u64 start = ctl->start;
struct alloc_chunk_ctl ctl; u64 type = ctl->type;
int ret; int ret;
int i; int i;
int j; int j;
if (!alloc_profile_is_valid(type, 0)) { map = kmalloc(map_lookup_size(ctl->num_stripes), GFP_NOFS);
ASSERT(0); if (!map)
return -EINVAL;
}
if (list_empty(&fs_devices->alloc_list)) {
if (btrfs_test_opt(info, ENOSPC_DEBUG))
btrfs_debug(info, "%s: no writable device", __func__);
return -ENOSPC;
}
if (!(type & BTRFS_BLOCK_GROUP_TYPE_MASK)) {
btrfs_err(info, "invalid chunk type 0x%llx requested", type);
ASSERT(0);
return -EINVAL;
}
ctl.start = start;
ctl.type = type;
init_alloc_chunk_ctl(fs_devices, &ctl);
devices_info = kcalloc(fs_devices->rw_devices, sizeof(*devices_info),
GFP_NOFS);
if (!devices_info)
return -ENOMEM; return -ENOMEM;
map->num_stripes = ctl->num_stripes;
ret = gather_device_info(fs_devices, &ctl, devices_info); for (i = 0; i < ctl->ndevs; ++i) {
if (ret < 0) for (j = 0; j < ctl->dev_stripes; ++j) {
goto error; int s = i * ctl->dev_stripes + j;
ret = decide_stripe_size(fs_devices, &ctl, devices_info);
if (ret < 0)
goto error;
map = kmalloc(map_lookup_size(ctl.num_stripes), GFP_NOFS);
if (!map) {
ret = -ENOMEM;
goto error;
}
map->num_stripes = ctl.num_stripes;
for (i = 0; i < ctl.ndevs; ++i) {
for (j = 0; j < ctl.dev_stripes; ++j) {
int s = i * ctl.dev_stripes + j;
map->stripes[s].dev = devices_info[i].dev; map->stripes[s].dev = devices_info[i].dev;
map->stripes[s].physical = devices_info[i].dev_offset + map->stripes[s].physical = devices_info[i].dev_offset +
j * ctl.stripe_size; j * ctl->stripe_size;
} }
} }
map->stripe_len = BTRFS_STRIPE_LEN; map->stripe_len = BTRFS_STRIPE_LEN;
map->io_align = BTRFS_STRIPE_LEN; map->io_align = BTRFS_STRIPE_LEN;
map->io_width = BTRFS_STRIPE_LEN; map->io_width = BTRFS_STRIPE_LEN;
map->type = type; map->type = type;
map->sub_stripes = ctl.sub_stripes; map->sub_stripes = ctl->sub_stripes;
trace_btrfs_chunk_alloc(info, map, start, ctl.chunk_size); trace_btrfs_chunk_alloc(info, map, start, ctl->chunk_size);
em = alloc_extent_map(); em = alloc_extent_map();
if (!em) { if (!em) {
kfree(map); kfree(map);
ret = -ENOMEM; return -ENOMEM;
goto error;
} }
set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags); set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
em->map_lookup = map; em->map_lookup = map;
em->start = start; em->start = start;
em->len = ctl.chunk_size; em->len = ctl->chunk_size;
em->block_start = 0; em->block_start = 0;
em->block_len = em->len; em->block_len = em->len;
em->orig_block_len = ctl.stripe_size; em->orig_block_len = ctl->stripe_size;
em_tree = &info->mapping_tree; em_tree = &info->mapping_tree;
write_lock(&em_tree->lock); write_lock(&em_tree->lock);
...@@ -5111,11 +5073,11 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -5111,11 +5073,11 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
if (ret) { if (ret) {
write_unlock(&em_tree->lock); write_unlock(&em_tree->lock);
free_extent_map(em); free_extent_map(em);
goto error; return ret;
} }
write_unlock(&em_tree->lock); write_unlock(&em_tree->lock);
ret = btrfs_make_block_group(trans, 0, type, start, ctl.chunk_size); ret = btrfs_make_block_group(trans, 0, type, start, ctl->chunk_size);
if (ret) if (ret)
goto error_del_extent; goto error_del_extent;
...@@ -5123,20 +5085,19 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -5123,20 +5085,19 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
struct btrfs_device *dev = map->stripes[i].dev; struct btrfs_device *dev = map->stripes[i].dev;
btrfs_device_set_bytes_used(dev, btrfs_device_set_bytes_used(dev,
dev->bytes_used + ctl.stripe_size); dev->bytes_used + ctl->stripe_size);
if (list_empty(&dev->post_commit_list)) if (list_empty(&dev->post_commit_list))
list_add_tail(&dev->post_commit_list, list_add_tail(&dev->post_commit_list,
&trans->transaction->dev_update_list); &trans->transaction->dev_update_list);
} }
atomic64_sub(ctl.stripe_size * map->num_stripes, atomic64_sub(ctl->stripe_size * map->num_stripes,
&info->free_chunk_space); &info->free_chunk_space);
free_extent_map(em); free_extent_map(em);
check_raid56_incompat_flag(info, type); check_raid56_incompat_flag(info, type);
check_raid1c34_incompat_flag(info, type); check_raid1c34_incompat_flag(info, type);
kfree(devices_info);
return 0; return 0;
error_del_extent: error_del_extent:
...@@ -5148,7 +5109,56 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -5148,7 +5109,56 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
free_extent_map(em); free_extent_map(em);
/* One for the tree reference */ /* One for the tree reference */
free_extent_map(em); free_extent_map(em);
error:
return ret;
}
static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
u64 start, u64 type)
{
struct btrfs_fs_info *info = trans->fs_info;
struct btrfs_fs_devices *fs_devices = info->fs_devices;
struct btrfs_device_info *devices_info = NULL;
struct alloc_chunk_ctl ctl;
int ret;
if (!alloc_profile_is_valid(type, 0)) {
ASSERT(0);
return -EINVAL;
}
if (list_empty(&fs_devices->alloc_list)) {
if (btrfs_test_opt(info, ENOSPC_DEBUG))
btrfs_debug(info, "%s: no writable device", __func__);
return -ENOSPC;
}
if (!(type & BTRFS_BLOCK_GROUP_TYPE_MASK)) {
btrfs_err(info, "invalid chunk type 0x%llx requested", type);
ASSERT(0);
return -EINVAL;
}
ctl.start = start;
ctl.type = type;
init_alloc_chunk_ctl(fs_devices, &ctl);
devices_info = kcalloc(fs_devices->rw_devices, sizeof(*devices_info),
GFP_NOFS);
if (!devices_info)
return -ENOMEM;
ret = gather_device_info(fs_devices, &ctl, devices_info);
if (ret < 0)
goto out;
ret = decide_stripe_size(fs_devices, &ctl, devices_info);
if (ret < 0)
goto out;
ret = create_chunk(trans, &ctl, devices_info);
out:
kfree(devices_info); kfree(devices_info);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment