On 2018年02月02日 17:20, Su Yue wrote:
>
>
> On 02/02/2018 04:19 PM, Qu Wenruo wrote:
>> We used to have two chunk allocators, btrfs_alloc_chunk() and
>> btrfs_alloc_data_chunk(), the former is the more generic one, while the
>> later is only used in mkfs and convert, to allocate SINGLE data chunk.
>>
>> Although btrfs_alloc_data_chunk() has some special hacks to cooperate
>> with convert, it's quite simple to integrity it into the generic chunk
>> allocator.
>>
>> So merge them into one btrfs_alloc_chunk(), with extra @convert
>> parameter and necessary comment, to make code less duplicated and less
>> thing to maintain.
>>
>> Signed-off-by: Qu Wenruo <wqu@xxxxxxxx>
>> ---
>> convert/main.c | 6 +-
>> extent-tree.c | 2 +-
>> mkfs/main.c | 8 +--
>> volumes.c | 219
>> ++++++++++++++++++++++-----------------------------------
[snip]
>> diff --git a/volumes.c b/volumes.c
>> index 677d085de96c..9ee4650351c3 100644
>> --- a/volumes.c
>> +++ b/volumes.c
>> @@ -836,9 +836,23 @@ error:
>> - 2 * sizeof(struct btrfs_chunk)) \
>> / sizeof(struct btrfs_stripe) + 1)
>> +/*
>> + * Alloc a chunk, will insert dev extents, chunk item.
>> + * NOTE: This function will not insert block group item nor mark newly
>> + * allocated chunk available for later allocation.
>> + * Block group item and free space update is handled by
>> btrfs_make_block_group()
>> + *
>> + * @start: return value of allocated chunk start bytenr.
>> + * @num_bytes: return value of allocated chunk size
>> + * @type: chunk type (including both profile and type)
>> + * @convert: if the chunk is allocated for convert case.
>> + * If @convert is true, chunk allocator will skip device extent
>> + * search, but use *start and *num_bytes as chunk
>> start/num_bytes
>> + * and devive offset, to build a 1:1 chunk mapping for convert.
>> + */
>> int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
>> struct btrfs_fs_info *info, u64 *start,
>> - u64 *num_bytes, u64 type)
>> + u64 *num_bytes, u64 type, bool convert)
>> {
>> u64 dev_offset;
>> struct btrfs_root *extent_root = info->extent_root;
>> @@ -868,10 +882,38 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle
>> *trans,
>> struct btrfs_key key;
>> u64 offset;
>> - if (list_empty(dev_list)) {
>> + if (list_empty(dev_list))
>> return -ENOSPC;
>> +
>> + if (convert) {
>> + /* For convert, profile must be SINGLE */
>> + if (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
> Maybe BTRFS_RAID_SINGLE?
Here we're using type and raid index is not introduced yet, so what
we're doing is correct.
Thanks,
Qu
>
> Thanks,
> Su
>
>> + error("convert only suports SINGLE profile");
>> + return -EINVAL;
>> + }
>> + if (!IS_ALIGNED(*start, info->sectorsize)) {
>> + error("chunk start not aligned, start=%llu sectorsize=%u",
>> + *start, info->sectorsize);
>> + return -EINVAL;
>> + }
>> + if (!IS_ALIGNED(*num_bytes, info->sectorsize)) {
>> + error("chunk size not aligned, size=%llu sectorsize=%u",
>> + *num_bytes, info->sectorsize);
>> + return -EINVAL;
>> + }
>> + calc_size = *num_bytes;
>> + offset = *start;
>> + /*
>> + * For convert, we use 1:1 chunk mapping specified by @start and
>> + * @num_bytes, so there is no need to go through dev_extent
>> + * searching.
>> + */
>> + goto alloc_chunk;
>> }
>> + /*
>> + * Chunk size calculation part.
>> + */
>> if (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
>> if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
>> calc_size = SZ_8M;
>> @@ -942,6 +984,9 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle
>> *trans,
>> percent_max =
>> div_factor(btrfs_super_total_bytes(info->super_copy), 1);
>> max_chunk_size = min(percent_max, max_chunk_size);
>> + /*
>> + * Reserve space from each device.
>> + */
>> again:
>> if (chunk_bytes_by_type(type, calc_size, num_stripes,
>> sub_stripes) >
>> max_chunk_size) {
>> @@ -972,7 +1017,8 @@ again:
>> return ret;
>> cur = cur->next;
>> if (avail >= min_free) {
>> - list_move_tail(&device->dev_list, &private_devs);
>> + list_move_tail(&device->dev_list,
>> + &private_devs);
>> index++;
>> if (type & BTRFS_BLOCK_GROUP_DUP)
>> index++;
>> @@ -999,9 +1045,16 @@ again:
>> }
>> return -ENOSPC;
>> }
>> - ret = find_next_chunk(info, &offset);
>> - if (ret)
>> - return ret;
>> +
>> + /*
>> + * Fill chunk mapping and chunk stripes
>> + */
>> +alloc_chunk:
>> + if (!convert) {
>> + ret = find_next_chunk(info, &offset);
>> + if (ret)
>> + return ret;
>> + }
>> key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
>> key.type = BTRFS_CHUNK_ITEM_KEY;
>> key.offset = offset;
>> @@ -1022,17 +1075,31 @@ again:
>> index = 0;
>> while(index < num_stripes) {
>> struct btrfs_stripe *stripe;
>> - BUG_ON(list_empty(&private_devs));
>> - cur = private_devs.next;
>> - device = list_entry(cur, struct btrfs_device, dev_list);
>> - /* loop over this device again if we're doing a dup group */
>> - if (!(type & BTRFS_BLOCK_GROUP_DUP) ||
>> - (index == num_stripes - 1))
>> - list_move_tail(&device->dev_list, dev_list);
>> + if (!convert) {
>> + if (list_empty(&private_devs))
>> + return -ENODEV;
>> + cur = private_devs.next;
>> + device = list_entry(cur, struct btrfs_device, dev_list);
>> + if (!(type & BTRFS_BLOCK_GROUP_DUP) ||
>> + (index == num_stripes - 1)) {
>> + /*
>> + * loop over this device again if we're doing a
>> + * dup group
>> + */
>> + list_move_tail(&device->dev_list, dev_list);
>> + }
>> + } else {
>> + /* Only SINGLE is accepted in convert case */
>> + BUG_ON(num_stripes > 1);
>> + device = list_entry(dev_list->next, struct btrfs_device,
>> + dev_list);
>> + key.offset = *start;
>> + dev_offset = *start;
>> + }
>> ret = btrfs_alloc_dev_extent(trans, device, key.offset,
>> - calc_size, &dev_offset, 0);
>> + calc_size, &dev_offset, convert);
>> if (ret < 0)
>> goto out_chunk_map;
>> @@ -1049,7 +1116,7 @@ again:
>> memcpy(stripe->dev_uuid, device->uuid, BTRFS_UUID_SIZE);
>> index++;
>> }
>> - BUG_ON(!list_empty(&private_devs));
>> + BUG_ON(!convert && !list_empty(&private_devs));
>> /* key was set above */
>> btrfs_set_stack_chunk_length(chunk, *num_bytes);
>> @@ -1069,6 +1136,9 @@ again:
>> map->num_stripes = num_stripes;
>> map->sub_stripes = sub_stripes;
>> + /*
>> + * Insert chunk item and chunk mapping.
>> + */
>> ret = btrfs_insert_item(trans, chunk_root, &key, chunk,
>> btrfs_chunk_item_size(num_stripes));
>> BUG_ON(ret);
>> @@ -1098,125 +1168,6 @@ out_chunk:
>> return ret;
>> }
>> -/*
>> - * Alloc a DATA chunk with SINGLE profile.
>> - *
>> - * If 'convert' is set, it will alloc a chunk with 1:1 mapping
>> - * (btrfs logical bytenr == on-disk bytenr)
>> - * For that case, caller must make sure the chunk and dev_extent are not
>> - * occupied.
>> - */
>> -int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans,
>> - struct btrfs_fs_info *info, u64 *start,
>> - u64 num_bytes, u64 type, int convert)
>> -{
>> - 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 = 0;
>> - int ret;
>> - int index;
>> - int stripe_len = BTRFS_STRIPE_LEN;
>> - struct btrfs_key key;
>> -
>> - key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
>> - key.type = BTRFS_CHUNK_ITEM_KEY;
>> - if (convert) {
>> - if (*start != round_down(*start, info->sectorsize)) {
>> - error("DATA chunk start not sectorsize aligned: %llu",
>> - (unsigned long long)*start);
>> - return -EINVAL;
>> - }
>> - key.offset = *start;
>> - dev_offset = *start;
>> - } else {
>> - u64 tmp;
>> -
>> - ret = find_next_chunk(info, &tmp);
>> - key.offset = tmp;
>> - if (ret)
>> - return ret;
>> - }
>> -
>> - chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS);
>> - if (!chunk)
>> - return -ENOMEM;
>> -
>> - 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_alloc_dev_extent(trans, device, key.offset,
>> - calc_size, &dev_offset, convert);
>> - 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, type);
>> - 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 = type;
>> - 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);
>> - if (!convert)
>> - *start = key.offset;
>> -
>> - 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;
>> -}
>> -
>> int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64
>> len)
>> {
>> struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
>> diff --git a/volumes.h b/volumes.h
>> index 11572e78c04f..7bbdf615d31a 100644
>> --- a/volumes.h
>> +++ b/volumes.h
>> @@ -208,10 +208,7 @@ int btrfs_read_sys_array(struct btrfs_fs_info
>> *fs_info);
>> int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info);
>> int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
>> struct btrfs_fs_info *fs_info, u64 *start,
>> - u64 *num_bytes, u64 type);
>> -int btrfs_alloc_data_chunk(struct btrfs_trans_handle *trans,
>> - struct btrfs_fs_info *fs_info, u64 *start,
>> - u64 num_bytes, u64 type, int convert);
>> + u64 *num_bytes, u64 type, bool convert);
>> int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
>> int flags);
>> int btrfs_close_devices(struct btrfs_fs_devices *fs_devices);
>>
>
>
Attachment:
signature.asc
Description: OpenPGP digital signature
