From 13a6cff8b6b5ee3cb71997cbb7ea92bfa3575d11 Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Tue, 6 Apr 2021 17:05:49 +0900 Subject: [PATCH] btrfs-progs: rewrite btrfs_alloc_data_chunk() using create_chunk() btrfs_alloc_data_chunk() and create_chunk() have the most part in common. Let's rewrite btrfs_alloc_data_chunk() using create_chunk(). There are two differences between btrfs_alloc_data_chunk() and create_chunk(). create_chunk() uses find_next_chunk() to decide the logical address of the chunk, and it uses btrfs_alloc_dev_extent() to decide the physical address of a device extent. On the other hand, btrfs_alloc_data_chunk() uses *start for both logical and physical addresses. To support the btrfs_alloc_data_chunk()'s use case, we use ctl->start and ctl->dev_offset. If these values are set (non-zero), use the specified values as the address. It is safe to use 0 to indicate the value is not set here. Because both lower addresses of logical (0..BTRFS_FIRST_CHUNK_TREE_OBJECT_ID) and physical (0..BTRFS_BLOCK_RESERVED_1M_FOR_SUPER) are reserved. Reviewed-by: Johannes Thumshirn Signed-off-by: Naohiro Aota Signed-off-by: David Sterba --- kernel-shared/volumes.c | 136 +++++++++++++--------------------------- 1 file changed, 43 insertions(+), 93 deletions(-) diff --git a/kernel-shared/volumes.c b/kernel-shared/volumes.c index 0afd3b2d..c493479e 100644 --- a/kernel-shared/volumes.c +++ b/kernel-shared/volumes.c @@ -161,6 +161,7 @@ struct alloc_chunk_ctl { u64 max_chunk_size; int stripe_len; int total_devs; + u64 dev_offset; }; struct stripe { @@ -1058,6 +1059,7 @@ static void init_alloc_chunk_ctl(struct btrfs_fs_info *info, ctl->max_chunk_size = 4 * ctl->calc_size; ctl->stripe_len = BTRFS_STRIPE_LEN; ctl->total_devs = btrfs_super_num_devices(info->super_copy); + ctl->dev_offset = 0; switch (info->fs_devices->chunk_alloc_policy) { case BTRFS_CHUNK_ALLOC_REGULAR: @@ -1137,9 +1139,14 @@ static int create_chunk(struct btrfs_trans_handle *trans, struct btrfs_key key; u64 offset; - ret = find_next_chunk(info, &offset); - if (ret) - return ret; + if (!ctl->start) { + ret = find_next_chunk(info, &offset); + if (ret) + return ret; + } else { + offset = ctl->start; + } + key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; key.type = BTRFS_CHUNK_ITEM_KEY; key.offset = offset; @@ -1170,10 +1177,18 @@ static int create_chunk(struct btrfs_trans_handle *trans, (index == ctl->num_stripes - 1)) list_move(&device->dev_list, dev_list); - ret = btrfs_alloc_dev_extent(trans, device, key.offset, - ctl->calc_size, &dev_offset); - if (ret < 0) - goto out_chunk_map; + if (!ctl->dev_offset) { + ret = btrfs_alloc_dev_extent(trans, device, key.offset, + ctl->calc_size, &dev_offset); + if (ret < 0) + goto out_chunk_map; + } else { + dev_offset = ctl->dev_offset; + ret = btrfs_insert_dev_extent(trans, device, key.offset, + ctl->calc_size, + ctl->dev_offset); + BUG_ON(ret); + } device->bytes_used += ctl->calc_size; ret = btrfs_update_device(trans, device); @@ -1330,23 +1345,10 @@ again: int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans, struct btrfs_fs_info *info, u64 *start, u64 num_bytes) { - u64 dev_offset; - struct btrfs_root *extent_root = info->extent_root; - struct btrfs_root *chunk_root = info->chunk_root; - struct btrfs_stripe *stripes; - struct btrfs_device *device = NULL; - struct btrfs_chunk *chunk; struct list_head *dev_list = &info->fs_devices->devices; - struct list_head *cur; - struct map_lookup *map; - u64 calc_size = SZ_8M; - int num_stripes = 1; - int sub_stripes = 1; - int ret; - int index; - int stripe_len = BTRFS_STRIPE_LEN; - struct btrfs_key key; - + struct list_head private_devs; + struct btrfs_device *device; + struct alloc_chunk_ctl ctl; if (*start != round_down(*start, info->sectorsize)) { error("DATA chunk start not sectorsize aligned: %llu", @@ -1354,78 +1356,26 @@ int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans, return -EINVAL; } - key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; - key.type = BTRFS_CHUNK_ITEM_KEY; - key.offset = *start; - dev_offset = *start; + ctl.start = *start; + ctl.type = BTRFS_BLOCK_GROUP_DATA; + ctl.num_stripes = 1; + ctl.max_stripes = 1; + ctl.min_stripes = 1; + ctl.sub_stripes = 1; + ctl.calc_size = num_bytes; + ctl.min_stripe_size = num_bytes; + ctl.num_bytes = num_bytes; + ctl.max_chunk_size = num_bytes; + ctl.stripe_len = BTRFS_STRIPE_LEN; + ctl.total_devs = btrfs_super_num_devices(info->super_copy); + ctl.dev_offset = *start; - chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS); - if (!chunk) - return -ENOMEM; + INIT_LIST_HEAD(&private_devs); + /* Build a list containing one device */ + device = list_entry(dev_list->next, struct btrfs_device, dev_list); + list_move(&device->dev_list, &private_devs); - map = kmalloc(btrfs_map_lookup_size(num_stripes), GFP_NOFS); - if (!map) { - kfree(chunk); - return -ENOMEM; - } - - stripes = &chunk->stripe; - calc_size = num_bytes; - - index = 0; - cur = dev_list->next; - device = list_entry(cur, struct btrfs_device, dev_list); - - while (index < num_stripes) { - struct btrfs_stripe *stripe; - - ret = btrfs_insert_dev_extent(trans, device, key.offset, calc_size, - dev_offset); - BUG_ON(ret); - - device->bytes_used += calc_size; - ret = btrfs_update_device(trans, device); - BUG_ON(ret); - - map->stripes[index].dev = device; - map->stripes[index].physical = dev_offset; - stripe = stripes + index; - btrfs_set_stack_stripe_devid(stripe, device->devid); - btrfs_set_stack_stripe_offset(stripe, dev_offset); - memcpy(stripe->dev_uuid, device->uuid, BTRFS_UUID_SIZE); - index++; - } - - /* key was set above */ - btrfs_set_stack_chunk_length(chunk, num_bytes); - btrfs_set_stack_chunk_owner(chunk, extent_root->root_key.objectid); - btrfs_set_stack_chunk_stripe_len(chunk, stripe_len); - btrfs_set_stack_chunk_type(chunk, BTRFS_BLOCK_GROUP_DATA); - btrfs_set_stack_chunk_num_stripes(chunk, num_stripes); - btrfs_set_stack_chunk_io_align(chunk, stripe_len); - btrfs_set_stack_chunk_io_width(chunk, stripe_len); - btrfs_set_stack_chunk_sector_size(chunk, info->sectorsize); - btrfs_set_stack_chunk_sub_stripes(chunk, sub_stripes); - map->sector_size = info->sectorsize; - map->stripe_len = stripe_len; - map->io_align = stripe_len; - map->io_width = stripe_len; - map->type = BTRFS_BLOCK_GROUP_DATA; - map->num_stripes = num_stripes; - map->sub_stripes = sub_stripes; - - ret = btrfs_insert_item(trans, chunk_root, &key, chunk, - btrfs_chunk_item_size(num_stripes)); - BUG_ON(ret); - - map->ce.start = key.offset; - map->ce.size = num_bytes; - - ret = insert_cache_extent(&info->mapping_tree.cache_tree, &map->ce); - BUG_ON(ret); - - kfree(chunk); - return ret; + return create_chunk(trans, info, &ctl, &private_devs); } int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)