Preparation for later btrfs_alloc_chunk() rework, Part 2
cover Preparation for later btrfs_alloc_chunk() rework, Part 2
This patchset, along with its prerequisite (patchset named:
"[PATCH 0/5] Cleanups for later btrfs_alloc_chunk() rework") can be fetched from github:
https://github.com/adam900710/btrfs-progs/tree/chunk_alloc_enospc
This patchset can still be treated as cleanup, but brings a much larger structure modification of btrfs_alloc_chunk().
The first patch will merge the original btrfs_alloc_data_chunk() with more generic btrfs_alloc_chunk().
And 2nd patch integrate btrfs_make_block_group() into btrfs_alloc_chunk(), provides the critical basis for later rework. (Later rework needs to update space info before any tree modification, so btrfs_make_block_group must be integrated)
Considering the importance of btrfs_alloc_chunk() in btrfs-progs, these 2 patches are separated out for a longer review window before larger rework.
Qu Wenruo (2):
btrfs-progs: Merge btrfs_alloc_data_chunk into btrfs_alloc_chunk
btrfs-progs: Make btrfs_alloc_chunk to handle block group creation
convert/main.c | 10 +-- extent-tree.c | 12 +--- mkfs/main.c | 42 ++--------- volumes.c | 222 +++++++++++++++++++++++---------------------------------- volumes.h | 5 +- 5 files changed, 102 insertions(+), 189 deletions(-)
Signature · 1 line
2.15.1
PATCH 1/2 btrfs-progs: Merge btrfs_alloc_data_chunk into btrfs_alloc_chunk
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.
--- convert/main.c | 6 +- extent-tree.c | 2 +- mkfs/main.c | 14 ++-- volumes.c | 220 ++++++++++++++++++++++----------------------------------- volumes.h | 5 +- 5 files changed, 98 insertions(+), 149 deletions(-)
convert/main.c +3 -3
@@ -910,9 +910,9 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans, len =min (max_chunk_size, cache->start + cache->size - cur); - ret =btrfs_alloc_data_chunk (trans, fs_info, - &cur_backup, len, -BTRFS_BLOCK_GROUP_DATA ,1 ); + ret =btrfs_alloc_chunk (trans, fs_info, + &cur_backup, &len, +BTRFS_BLOCK_GROUP_DATA , true);if (ret <0 )break ; ret = btrfs_make_block_group(trans, fs_info, 0,
extent-tree.c +1 -1
@@ -1907,7 +1907,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,return 0 ; ret =btrfs_alloc_chunk (trans, fs_info, &start, &num_bytes, - space_info->flags); + space_info->flags, false);if (ret == -ENOSPC ) { space_info->full =1 ;return 0 ;
mkfs/main.c +7 -7
@@ -92,7 +92,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size,BTRFS_BLOCK_GROUP_METADATA | -BTRFS_BLOCK_GROUP_DATA ); +BTRFS_BLOCK_GROUP_DATA , false);if (ret == -ENOSPC ) {error ("no space to allocate data/metadata chunk" ); goto err;
@@ -109,7 +109,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, }else { ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size, -BTRFS_BLOCK_GROUP_METADATA ); +BTRFS_BLOCK_GROUP_METADATA , false);if (ret == -ENOSPC ) {error ("no space to allocate metadata chunk" ); goto err;
@@ -143,7 +143,7 @@ static int create_data_block_groups(struct btrfs_trans_handle *trans,if (!mixed) { ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size, -BTRFS_BLOCK_GROUP_DATA ); +BTRFS_BLOCK_GROUP_DATA , false);if (ret == -ENOSPC ) {error ("no space to allocate data chunk" ); goto err;
@@ -251,7 +251,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,int ret; ret =btrfs_alloc_chunk (trans, fs_info, - &chunk_start, &chunk_size, type); + &chunk_start, &chunk_size, type, false);if (ret == -ENOSPC ) {error ("not enough free space to allocate chunk" );exit (1 );
@@ -1003,7 +1003,7 @@ static int create_chunks(struct btrfs_trans_handle *trans,for (i =0 ; i < num_of_meta_chunks; i++) { ret =btrfs_alloc_chunk (trans, fs_info, - &chunk_start, &chunk_size, meta_type); + &chunk_start, &chunk_size, meta_type, false);if (ret)return ret; ret = btrfs_make_block_group(trans, fs_info, 0,
@@ -1019,8 +1019,8 @@ static int create_chunks(struct btrfs_trans_handle *trans,if (size_of_data < minimum_data_chunk_size) size_of_data = minimum_data_chunk_size; - ret =btrfs_alloc_data_chunk (trans, fs_info, - &chunk_start, size_of_data, data_type,0 ); + ret =btrfs_alloc_chunk (trans, fs_info, + &chunk_start, &size_of_data, data_type, false);if (ret)return ret; ret = btrfs_make_block_group(trans, fs_info, 0,
volumes.c +86 -134
275 lines not on this page · raw message
volumes.h +1 -4
@@ -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);
Signature · 1 line
2.15.1
Re: [PATCH 1/2] btrfs-progs: Merge btrfs_alloc_data_chunk into btrfs_alloc_chunk
Quoted 141 lines · Qu Wenruo
We used to have two chunk allocators,
btrfs_alloc_chunk()andbtrfs_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 <[email protected]>--- convert/main.c | 6 +- extent-tree.c | 2 +- mkfs/main.c | 14 ++-- volumes.c | 220 ++++++++++++++++++++++----------------------------------- volumes.h | 5 +- 5 files changed, 98 insertions(+), 149 deletions(-)convert/main.c +3
-3@@ -910,9 +910,9 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans, len =min (max_chunk_size, cache->start + cache->size - cur); - ret =btrfs_alloc_data_chunk (trans, fs_info, - &cur_backup, len, -BTRFS_BLOCK_GROUP_DATA ,1 ); + ret =btrfs_alloc_chunk (trans, fs_info, + &cur_backup, &len, +BTRFS_BLOCK_GROUP_DATA , true);if (ret <0 )break ; ret = btrfs_make_block_group(trans, fs_info, 0,extent-tree.c +1
-1@@ -1907,7 +1907,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,return 0 ; ret =btrfs_alloc_chunk (trans, fs_info, &start, &num_bytes, - space_info->flags); + space_info->flags, false);if (ret == -ENOSPC ) { space_info->full =1 ;return 0 ;mkfs/main.c +7
-7@@ -92,7 +92,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size,BTRFS_BLOCK_GROUP_METADATA | -BTRFS_BLOCK_GROUP_DATA ); +BTRFS_BLOCK_GROUP_DATA , false);if (ret == -ENOSPC ) {error ("no space to allocate data/metadata chunk" ); goto err;@@ -109,7 +109,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, }else { ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size, -BTRFS_BLOCK_GROUP_METADATA ); +BTRFS_BLOCK_GROUP_METADATA , false);if (ret == -ENOSPC ) {error ("no space to allocate metadata chunk" ); goto err;@@ -143,7 +143,7 @@ static int create_data_block_groups(struct btrfs_trans_handle *trans,if (!mixed) { ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size, -BTRFS_BLOCK_GROUP_DATA ); +BTRFS_BLOCK_GROUP_DATA , false);if (ret == -ENOSPC ) {error ("no space to allocate data chunk" ); goto err;@@ -251,7 +251,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,int ret; ret =btrfs_alloc_chunk (trans, fs_info, - &chunk_start, &chunk_size, type); + &chunk_start, &chunk_size, type, false);if (ret == -ENOSPC ) {error ("not enough free space to allocate chunk" );exit (1 );@@ -1003,7 +1003,7 @@ static int create_chunks(struct btrfs_trans_handle *trans,for (i =0 ; i < num_of_meta_chunks; i++) { ret =btrfs_alloc_chunk (trans, fs_info, - &chunk_start, &chunk_size, meta_type); + &chunk_start, &chunk_size, meta_type, false);if (ret)return ret; ret = btrfs_make_block_group(trans, fs_info, 0,@@ -1019,8 +1019,8 @@ static int create_chunks(struct btrfs_trans_handle *trans,if (size_of_data < minimum_data_chunk_size) size_of_data = minimum_data_chunk_size; - ret =btrfs_alloc_data_chunk (trans, fs_info, - &chunk_start, size_of_data, data_type,0 ); + ret =btrfs_alloc_chunk (trans, fs_info, + &chunk_start, &size_of_data, data_type, false);if (ret)return ret; ret = btrfs_make_block_group(trans, fs_info, 0,volumes.c +15
-1@@ -844,9 +844,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;
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 893
Quoted 5 lines
volumes.c +1
-1@@ -876,10 +890,39 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,struct btrfs_key key;u64 offset; -if (list_empty (dev_list)) { +INIT_LIST_HEAD (&private_devs);
private_devs is initiated twice in the function.
It seems that you forgot to delete latter one.
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 898
Quoted 6 lines
volumes.c +3
-1+if (list_empty (dev_list))return -ENOSPC ; - } +if (convert) { +/* For convert, profile must be BTRFS_BLOCK_GROUP_DATA */
I wonder why not also check type like:
"if (type & BTRFS_BLOCK_GROUP_DATA) ..."
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 905
Quoted 7 lines
volumes.c +7
-0+if (type &BTRFS_BLOCK_GROUP_PROFILE_MASK ) { +error ("convert only suports SINGLE profile" ); +return -EINVAL ; + } +if (!IS_ALIGNED (*start, info->sectorsize)) { +error ("chunk start not aligned, start=%llu sectorsize=%u\n" , + *start, info->sectorsize);
error() breaks line itself. '\n' is unnecessary.
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 910
Quoted 5 lines
volumes.c +5
-0+return -EINVAL ; + } +if (!IS_ALIGNED (*num_bytes, info->sectorsize)) { +error ("chunk size not aligned, size=%llu sectorsize=%u\n" , + *num_bytes, info->sectorsize);
And line break here.
Other changes are nice to me.
Thanks,
Su
Quoted 251 lines
volumes.c +55
-131+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 ;@@ -950,6 +993,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) {@@ -980,7 +1026,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++;@@ -1007,9 +1054,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;@@ -1030,17 +1084,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;@@ -1077,6 +1145,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);@@ -1106,125 +1177,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;volumes.h +1
-4@@ -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);
Re: [PATCH 1/2] btrfs-progs: Merge btrfs_alloc_data_chunk into btrfs_alloc_chunk
Quoted 157 lines · Su Yue
Quoted 146 lines · Qu Wenruo
We used to have two chunk allocators,
btrfs_alloc_chunk()andbtrfs_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 <[email protected]>---
convert/main.c| 6 +-
extent-tree.c | 2 +-
mkfs/main.c | 14 ++--
volumes.c | 220
++++++++++++++++++++++-----------------------------------
volumes.h | 5 +-5 files changed, 98 insertions(+), 149 deletions(-)convert/main.c +3
-3@@ -910,9 +910,9 @@ static int make_convert_data_block_groups(structbtrfs_trans_handle *trans, len = min(max_chunk_size, cache->start + cache->size - cur); - ret = btrfs_alloc_data_chunk(trans, fs_info, - &cur_backup, len, - BTRFS_BLOCK_GROUP_DATA, 1); + ret = btrfs_alloc_chunk(trans, fs_info, + &cur_backup, &len, + BTRFS_BLOCK_GROUP_DATA, true); if (ret < 0) break; ret = btrfs_make_block_group(trans, fs_info, 0,extent-tree.c +1
-1@@ -1907,7 +1907,7 @@ static int do_chunk_alloc(structbtrfs_trans_handle *trans, return 0; ret = btrfs_alloc_chunk(trans, fs_info, &start, &num_bytes, - space_info->flags); + space_info->flags, false); if (ret == -ENOSPC) { space_info->full = 1; return 0;mkfs/main.c +0
-0@@ -92,7 +92,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, ret = btrfs_alloc_chunk(trans, fs_info, &chunk_start, &chunk_size,
BTRFS_BLOCK_GROUP_METADATA|
-BTRFS_BLOCK_GROUP_DATA);
+BTRFS_BLOCK_GROUP_DATA, false); if (ret ==-ENOSPC) {
error("no space to allocate data/metadata chunk"); goto err;mkfs/main.c +1
-1@@ -109,7 +109,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, } else { ret = btrfs_alloc_chunk(trans, fs_info, &chunk_start, &chunk_size, - BTRFS_BLOCK_GROUP_METADATA); + BTRFS_BLOCK_GROUP_METADATA, false); if (ret == -ENOSPC) { error("no space to allocate metadata chunk");goto err;
mkfs/main.c +1
-1@@ -143,7 +143,7 @@ static int create_data_block_groups(struct btrfs_trans_handle *trans, if (!mixed) { ret = btrfs_alloc_chunk(trans, fs_info, &chunk_start, &chunk_size, - BTRFS_BLOCK_GROUP_DATA); + BTRFS_BLOCK_GROUP_DATA, false); if (ret == -ENOSPC) { error("no space to allocate data chunk");goto err;
mkfs/main.c +4
-4@@ -251,7 +251,7 @@ static int create_one_raid_group(structbtrfs_trans_handle *trans, int ret; ret = btrfs_alloc_chunk(trans, fs_info, - &chunk_start, &chunk_size, type); + &chunk_start, &chunk_size, type, false); if (ret == -ENOSPC) { error("not enough free space to allocate chunk"); exit(1);@@ -1003,7 +1003,7 @@ static int create_chunks(struct btrfs_trans_handle *trans, for (i = 0; i < num_of_meta_chunks; i++) { ret = btrfs_alloc_chunk(trans, fs_info, - &chunk_start, &chunk_size, meta_type); + &chunk_start, &chunk_size, meta_type, false); if (ret) return ret; ret = btrfs_make_block_group(trans, fs_info, 0,@@ -1019,8 +1019,8 @@ static int create_chunks(struct btrfs_trans_handle *trans, if (size_of_data < minimum_data_chunk_size) size_of_data = minimum_data_chunk_size; - ret = btrfs_alloc_data_chunk(trans, fs_info, - &chunk_start, size_of_data, data_type, 0); + ret = btrfs_alloc_chunk(trans, fs_info, + &chunk_start, &size_of_data, data_type, false); if (ret) return ret; ret = btrfs_make_block_group(trans, fs_info, 0,volumes.c +12
-0@@ -844,9 +844,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(structbtrfs_trans_handle*trans, structbtrfs_fs_info*info, u64 *start,
- u64*num_bytes, u64 type)
+ u64*num_bytes, u64 type, bool convert)
{
u64dev_offset;
structbtrfs_root*extent_root=info->extent_root;volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle · line 893
Quoted 5 lines
volumes.c +1
-1@@ -876,10 +890,39 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, struct btrfs_key key; u64 offset; - if (list_empty(dev_list)) { + INIT_LIST_HEAD(&private_devs);
private_devsis initiated twice in the function.
It seems that you forgot to delete latter one.
Quoted 8 lines
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 898
Quoted 5 lines
volumes.c +3
-1+ if (list_empty(dev_list)) return -ENOSPC; - } + if (convert) { + /* For convert, profile must be BTRFS_BLOCK_GROUP_DATA */I wonder why not also check type like:
"if (type &BTRFS_BLOCK_GROUP_DATA) ..."
Sorry, Should be "if (type & BTRFS_BLOCK_GROUP_DATA == 0) ..."
Thanks,
Su
Quoted 269 lines
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 905
Quoted 8 lines
volumes.c +7
-0+ if (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) { + error("convert only suports SINGLE profile"); + return -EINVAL; + } + if (!IS_ALIGNED(*start, info->sectorsize)) { + error("chunk start not aligned, start=%llu sectorsize=%u\n", + *start, info->sectorsize);
error()breaks line itself. '\n' is unnecessary.volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 910
Quoted 5 lines
volumes.c +5
-0+ return -EINVAL; + } + if (!IS_ALIGNED(*num_bytes, info->sectorsize)) { + error("chunk size not aligned, size=%llu sectorsize=%u\n", + *num_bytes, info->sectorsize);And line break here.
Other changes are nice to me.
Thanks,
SuQuoted 247 lines
volumes.c +18
-0+ 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;@@ -950,6 +993,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) {volumes.c +37
-131@@ -980,7 +1026,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++;@@ -1007,9 +1054,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;@@ -1030,17 +1084,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;@@ -1077,6 +1145,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);@@ -1106,125 +1177,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;volumes.h +1
-4@@ -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);
Re: [PATCH 1/2] btrfs-progs: Merge btrfs_alloc_data_chunk into btrfs_alloc_chunk
In reply to Su YueQuoted 149 lines · Su Yue
Quoted 146 lines · Qu Wenruo
We used to have two chunk allocators,
btrfs_alloc_chunk()andbtrfs_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 <[email protected]>---
convert/main.c| 6 +-
extent-tree.c | 2 +-
mkfs/main.c | 14 ++--
volumes.c | 220
++++++++++++++++++++++-----------------------------------
volumes.h | 5 +-5 files changed, 98 insertions(+), 149 deletions(-)convert/main.c +3
-3@@ -910,9 +910,9 @@ static int make_convert_data_block_groups(structbtrfs_trans_handle *trans, len = min(max_chunk_size, cache->start + cache->size - cur); - ret = btrfs_alloc_data_chunk(trans, fs_info, - &cur_backup, len, - BTRFS_BLOCK_GROUP_DATA, 1); + ret = btrfs_alloc_chunk(trans, fs_info, + &cur_backup, &len, + BTRFS_BLOCK_GROUP_DATA, true); if (ret < 0) break; ret = btrfs_make_block_group(trans, fs_info, 0,extent-tree.c +1
-1@@ -1907,7 +1907,7 @@ static int do_chunk_alloc(structbtrfs_trans_handle *trans, return 0; ret = btrfs_alloc_chunk(trans, fs_info, &start, &num_bytes, - space_info->flags); + space_info->flags, false); if (ret == -ENOSPC) { space_info->full = 1; return 0;mkfs/main.c +0
-0@@ -92,7 +92,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, ret = btrfs_alloc_chunk(trans, fs_info, &chunk_start, &chunk_size,
BTRFS_BLOCK_GROUP_METADATA|
-BTRFS_BLOCK_GROUP_DATA);
+BTRFS_BLOCK_GROUP_DATA, false); if (ret ==-ENOSPC) {
error("no space to allocate data/metadata chunk"); goto err;mkfs/main.c +1
-1@@ -109,7 +109,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, } else { ret = btrfs_alloc_chunk(trans, fs_info, &chunk_start, &chunk_size, - BTRFS_BLOCK_GROUP_METADATA); + BTRFS_BLOCK_GROUP_METADATA, false); if (ret == -ENOSPC) { error("no space to allocate metadata chunk");goto err;
mkfs/main.c +1
-1@@ -143,7 +143,7 @@ static int create_data_block_groups(struct btrfs_trans_handle *trans, if (!mixed) { ret = btrfs_alloc_chunk(trans, fs_info, &chunk_start, &chunk_size, - BTRFS_BLOCK_GROUP_DATA); + BTRFS_BLOCK_GROUP_DATA, false); if (ret == -ENOSPC) { error("no space to allocate data chunk");goto err;
mkfs/main.c +4
-3@@ -251,7 +251,7 @@ static int create_one_raid_group(structbtrfs_trans_handle *trans, int ret; ret = btrfs_alloc_chunk(trans, fs_info, - &chunk_start, &chunk_size, type); + &chunk_start, &chunk_size, type, false); if (ret == -ENOSPC) { error("not enough free space to allocate chunk"); exit(1);@@ -1003,7 +1003,7 @@ static int create_chunks(struct btrfs_trans_handle *trans, for (i = 0; i < num_of_meta_chunks; i++) { ret = btrfs_alloc_chunk(trans, fs_info, - &chunk_start, &chunk_size, meta_type); + &chunk_start, &chunk_size, meta_type, false); if (ret) return ret; ret = btrfs_make_block_group(trans, fs_info, 0,@@ -1019,8 +1019,8 @@ static int create_chunks(struct btrfs_trans_handle *trans, if (size_of_data < minimum_data_chunk_size) size_of_data = minimum_data_chunk_size; - ret = btrfs_alloc_data_chunk(trans, fs_info, - &chunk_start, size_of_data, data_type, 0); + ret = btrfs_alloc_chunk(trans, fs_info, + &chunk_start, &size_of_data, data_type, false); if (ret) return ret;ret = btrfs_make_block_group(trans,
fs_info, 0,volumes.c +0
-0@@ -844,9 +844,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 bybtrfs_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_bytesas chunk start/num_bytes
+ * and devive offset, to build a 1:1 chunk mapping for convert.
+ */
int btrfs_alloc_chunk(structbtrfs_trans_handle*trans, structbtrfs_fs_info*info, u64 *start,
- u64*num_bytes, u64 type)
+ u64*num_bytes, u64 type, bool convert)
{
u64dev_offset;
structbtrfs_root*extent_root=info->extent_root;volumes.c +0
-0@@ -876,10 +890,39 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle
Quoted 8 lines
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 893
Quoted 5 lines
volumes.c +1
-0*trans, struct btrfs_key key; u64 offset; - if (list_empty(dev_list)) { + INIT_LIST_HEAD(&private_devs);
private_devsis initiated twice in the function.
It seems that you forgot to delete latter one.
That's completely fine, since @private_devs is empty anyway. Reinitiliazing it won't cause any problem.
On the other hand, if you don't init @private_devs, you will easily hit BUG_ON(!list_empty(private_devs));
But since the unconditionally re-init seems a little annoying, I could move it do convert branch, or just enhance the later BUG_ON() to skip the check for convert == true case.
Quoted 8 lines
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 898
Quoted 5 lines
volumes.c +2
-1+ if (list_empty(dev_list)) return -ENOSPC; - } + if (convert) { + /* For convert, profile must be BTRFS_BLOCK_GROUP_DATA */I wonder why not also check type like:
"if (type &BTRFS_BLOCK_GROUP_DATA) ..."
Well, wrong comment.
Here I mean SINGLE profile, so the code is wrong but with wrong comment.
Quoted 10 lines
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 905
Quoted 8 lines
volumes.c +7
-0+ if (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) { + error("convert only suports SINGLE profile"); + return -EINVAL; + } + if (!IS_ALIGNED(*start, info->sectorsize)) { + error("chunk start not aligned, start=%llu sectorsize=%u\n", + *start, info->sectorsize);
error()breaks line itself. '\n' is unnecessary.
Yep, I forgot that.
Will update them soon.
Thanks,
Qu
Quoted 265 lines
volumes.c int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, · line 910
Quoted 5 lines
volumes.c +5
-0+ return -EINVAL; + } + if (!IS_ALIGNED(*num_bytes, info->sectorsize)) { + error("chunk size not aligned, size=%llu sectorsize=%u\n", + *num_bytes, info->sectorsize);And line break here.
Other changes are nice to me.
Thanks,
SuQuoted 250 lines
volumes.c +15
-0+ 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;@@ -950,6 +993,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) {volumes.c +12
-7@@ -980,7 +1026,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++;@@ -1007,9 +1054,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;@@ -1030,17 +1084,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)
gotoout_chunk_map;
@@ -1077,6 +1145,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);volumes.c +0
-0@@ -1106,125 +1177,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 anddev_extentare not
- * occupied.
- */volumes.c +0
-111-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)
{
structbtrfs_mapping_tree*map_tree=&fs_info->mapping_tree;volumes.h +1
-4@@ -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);
PATCH v2 1/2 btrfs-progs: Merge btrfs_alloc_data_chunk into btrfs_alloc_chunk
In reply to Qu WenruoWe 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.
---
changelog:
v2:
Instead of re-init @private_devs list, change the later BUG_ON() for convert case.
Update wrong comment to reflect the code.
Remove unnecessary new-line in error().
--- convert/main.c | 6 +- extent-tree.c | 2 +- mkfs/main.c | 14 ++-- volumes.c | 221 ++++++++++++++++++++++----------------------------------- volumes.h | 5 +- 5 files changed, 98 insertions(+), 150 deletions(-)
convert/main.c +3 -3
@@ -910,9 +910,9 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans, len =min (max_chunk_size, cache->start + cache->size - cur); - ret =btrfs_alloc_data_chunk (trans, fs_info, - &cur_backup, len, -BTRFS_BLOCK_GROUP_DATA ,1 ); + ret =btrfs_alloc_chunk (trans, fs_info, + &cur_backup, &len, +BTRFS_BLOCK_GROUP_DATA , true);if (ret <0 )break ; ret = btrfs_make_block_group(trans, fs_info, 0,
extent-tree.c +1 -1
@@ -1907,7 +1907,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,return 0 ; ret =btrfs_alloc_chunk (trans, fs_info, &start, &num_bytes, - space_info->flags); + space_info->flags, false);if (ret == -ENOSPC ) { space_info->full =1 ;return 0 ;
mkfs/main.c +7 -7
@@ -92,7 +92,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size,BTRFS_BLOCK_GROUP_METADATA | -BTRFS_BLOCK_GROUP_DATA ); +BTRFS_BLOCK_GROUP_DATA , false);if (ret == -ENOSPC ) {error ("no space to allocate data/metadata chunk" ); goto err;
@@ -109,7 +109,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, }else { ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size, -BTRFS_BLOCK_GROUP_METADATA ); +BTRFS_BLOCK_GROUP_METADATA , false);if (ret == -ENOSPC ) {error ("no space to allocate metadata chunk" ); goto err;
@@ -143,7 +143,7 @@ static int create_data_block_groups(struct btrfs_trans_handle *trans,if (!mixed) { ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size, -BTRFS_BLOCK_GROUP_DATA ); +BTRFS_BLOCK_GROUP_DATA , false);if (ret == -ENOSPC ) {error ("no space to allocate data chunk" ); goto err;
@@ -251,7 +251,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,int ret; ret =btrfs_alloc_chunk (trans, fs_info, - &chunk_start, &chunk_size, type); + &chunk_start, &chunk_size, type, false);if (ret == -ENOSPC ) {error ("not enough free space to allocate chunk" );exit (1 );
@@ -1003,7 +1003,7 @@ static int create_chunks(struct btrfs_trans_handle *trans,for (i =0 ; i < num_of_meta_chunks; i++) { ret =btrfs_alloc_chunk (trans, fs_info, - &chunk_start, &chunk_size, meta_type); + &chunk_start, &chunk_size, meta_type, false);if (ret)return ret; ret = btrfs_make_block_group(trans, fs_info, 0,
@@ -1019,8 +1019,8 @@ static int create_chunks(struct btrfs_trans_handle *trans,if (size_of_data < minimum_data_chunk_size) size_of_data = minimum_data_chunk_size; - ret =btrfs_alloc_data_chunk (trans, fs_info, - &chunk_start, size_of_data, data_type,0 ); + ret =btrfs_alloc_chunk (trans, fs_info, + &chunk_start, &size_of_data, data_type, false);if (ret)return ret; ret = btrfs_make_block_group(trans, fs_info, 0,
volumes.c +86 -135
282 lines not on this page · raw message
volumes.h +1 -4
@@ -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);
Signature · 1 line
2.15.1
Re: [PATCH v2 1/2] btrfs-progs: Merge btrfs_alloc_data_chunk into btrfs_alloc_chunk
Quoted 8 lines · Qu Wenruo
We used to have two chunk allocators,
btrfs_alloc_chunk()andbtrfs_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.
Quoted 5 lines
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 <[email protected]>
Looks good to me.
Quoted 417 lines
---
changelog:
v2:
Instead of re-init @private_devs list, change the laterBUG_ON()for convert case.
Update wrong comment to reflect the code.
Remove unnecessary new-line inerror().--- convert/main.c | 6 +- extent-tree.c | 2 +- mkfs/main.c | 14 ++-- volumes.c | 221 ++++++++++++++++++++++----------------------------------- volumes.h | 5 +- 5 files changed, 98 insertions(+), 150 deletions(-)convert/main.c +3
-3@@ -910,9 +910,9 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans, len =min (max_chunk_size, cache->start + cache->size - cur); - ret =btrfs_alloc_data_chunk (trans, fs_info, - &cur_backup, len, -BTRFS_BLOCK_GROUP_DATA ,1 ); + ret =btrfs_alloc_chunk (trans, fs_info, + &cur_backup, &len, +BTRFS_BLOCK_GROUP_DATA , true);if (ret <0 )break ; ret = btrfs_make_block_group(trans, fs_info, 0,extent-tree.c +1
-1@@ -1907,7 +1907,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,return 0 ; ret =btrfs_alloc_chunk (trans, fs_info, &start, &num_bytes, - space_info->flags); + space_info->flags, false);if (ret == -ENOSPC ) { space_info->full =1 ;return 0 ;mkfs/main.c +7
-7@@ -92,7 +92,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size,BTRFS_BLOCK_GROUP_METADATA | -BTRFS_BLOCK_GROUP_DATA ); +BTRFS_BLOCK_GROUP_DATA , false);if (ret == -ENOSPC ) {error ("no space to allocate data/metadata chunk" ); goto err;@@ -109,7 +109,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, }else { ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size, -BTRFS_BLOCK_GROUP_METADATA ); +BTRFS_BLOCK_GROUP_METADATA , false);if (ret == -ENOSPC ) {error ("no space to allocate metadata chunk" ); goto err;@@ -143,7 +143,7 @@ static int create_data_block_groups(struct btrfs_trans_handle *trans,if (!mixed) { ret =btrfs_alloc_chunk (trans, fs_info, &chunk_start, &chunk_size, -BTRFS_BLOCK_GROUP_DATA ); +BTRFS_BLOCK_GROUP_DATA , false);if (ret == -ENOSPC ) {error ("no space to allocate data chunk" ); goto err;@@ -251,7 +251,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,int ret; ret =btrfs_alloc_chunk (trans, fs_info, - &chunk_start, &chunk_size, type); + &chunk_start, &chunk_size, type, false);if (ret == -ENOSPC ) {error ("not enough free space to allocate chunk" );exit (1 );@@ -1003,7 +1003,7 @@ static int create_chunks(struct btrfs_trans_handle *trans,for (i =0 ; i < num_of_meta_chunks; i++) { ret =btrfs_alloc_chunk (trans, fs_info, - &chunk_start, &chunk_size, meta_type); + &chunk_start, &chunk_size, meta_type, false);if (ret)return ret; ret = btrfs_make_block_group(trans, fs_info, 0,@@ -1019,8 +1019,8 @@ static int create_chunks(struct btrfs_trans_handle *trans,if (size_of_data < minimum_data_chunk_size) size_of_data = minimum_data_chunk_size; - ret =btrfs_alloc_data_chunk (trans, fs_info, - &chunk_start, size_of_data, data_type,0 ); + ret =btrfs_alloc_chunk (trans, fs_info, + &chunk_start, &size_of_data, data_type, false);if (ret)return ret; ret = btrfs_make_block_group(trans, fs_info, 0,volumes.c +86
-135@@ -844,9 +844,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;@@ -876,10 +890,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 ) { +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 ;@@ -950,6 +992,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) {@@ -980,7 +1025,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++;@@ -1007,9 +1053,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;@@ -1030,17 +1083,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;@@ -1057,7 +1124,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);@@ -1077,6 +1144,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);@@ -1106,125 +1176,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;volumes.h +1
-4@@ -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);
PATCH 2/2 btrfs-progs: Make btrfs_alloc_chunk to handle block group creation
In reply to Qu WenruoBefore this patch, chunk allocation is split into 2 parts:
1) Chunk allocation
Handled by btrfs_alloc_chunk(), which will insert chunk and device extent items.
2) Block group allocation
Handled by btrfs_make_block_group(), which will insert block group item and update space info.
However for chunk allocation, we don't really need to split these operations as all btrfs_alloc_chunk() has btrfs_make_block_group() followed.
So it's reasonable to merge btrfs_make_block_group() call into btrfs_alloc_chunk() to save several lines, and provides the basis for later btrfs_alloc_chunk() rework.
--- convert/main.c | 4 ---- extent-tree.c | 10 ++-------- mkfs/main.c | 28 ---------------------------- volumes.c | 10 ++++++---- 4 files changed, 8 insertions(+), 44 deletions(-)
convert/main.c +0 -4
@@ -915,10 +915,6 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans, BTRFS_BLOCK_GROUP_DATA, true);if (ret <0 )break ; - ret =btrfs_make_block_group (trans, fs_info,0 , -BTRFS_BLOCK_GROUP_DATA , cur, len); -if (ret <0 ) -break ; cur += len; } }
extent-tree.c +2 -8
@@ -1910,15 +1910,9 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, space_info->flags, false);if (ret == -ENOSPC ) { space_info->full =1 ; -return 0 ; +return ret; } - -BUG_ON (ret); - - ret =btrfs_make_block_group (trans, fs_info,0 , space_info->flags, - start, num_bytes); -BUG_ON (ret); -return 0 ; +return ret; } static int update_block_group(struct btrfs_trans_handle *trans,
mkfs/main.c +0 -28
@@ -97,12 +97,6 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed,error ("no space to allocate data/metadata chunk" ); goto err; } -if (ret) -return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , -BTRFS_BLOCK_GROUP_METADATA | -BTRFS_BLOCK_GROUP_DATA , - chunk_start, chunk_size);if (ret)return ret; allocation->mixed += chunk_size;
@@ -116,12 +110,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, }if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , -BTRFS_BLOCK_GROUP_METADATA , - chunk_start, chunk_size); allocation->metadata += chunk_size; -if (ret) -return ret; } root->fs_info->system_allocs =0 ;
@@ -150,12 +139,7 @@ static int create_data_block_groups(struct btrfs_trans_handle *trans, }if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , -BTRFS_BLOCK_GROUP_DATA , - chunk_start, chunk_size); allocation->data += chunk_size; -if (ret) -return ret; } err:
@@ -259,9 +243,6 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , - type, chunk_start, chunk_size); - type &=BTRFS_BLOCK_GROUP_TYPE_MASK ;if (type ==BTRFS_BLOCK_GROUP_DATA ) { allocation->data += chunk_size;
@@ -1006,12 +987,7 @@ static int create_chunks(struct btrfs_trans_handle *trans, &chunk_start, &chunk_size, meta_type, false);if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , - meta_type, chunk_start, - chunk_size); allocation->metadata += chunk_size; -if (ret) -return ret;set_extent_dirty (&root->fs_info->free_space_cache, chunk_start, chunk_start + chunk_size -1 ); }
@@ -1023,11 +999,7 @@ static int create_chunks(struct btrfs_trans_handle *trans, &chunk_start, &size_of_data, data_type, false);if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , - data_type, chunk_start, size_of_data); allocation->data += size_of_data; -if (ret) -return ret;set_extent_dirty (&root->fs_info->free_space_cache, chunk_start, chunk_start + size_of_data -1 );return ret;
volumes.c +6 -4
@@ -845,10 +845,9 @@ error: / 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() +* Alloc a chunk, will insert dev extents, chunk item, and insert new +* block group and update space info (so that extent allocator can use +* newly allocated chunk). * * @start: return value of allocated chunk start bytenr. * @num_bytes: return value of allocated chunk size
@@ -1168,6 +1167,9 @@ alloc_chunk: }kfree (chunk); + + ret =btrfs_make_block_group (trans, info,0 , type, map->ce.start, + map->ce.size);return ret; out_chunk_map:
Signature · 1 line
2.15.1
Re: [PATCH 2/2] btrfs-progs: Make btrfs_alloc_chunk to handle block group creation
Quoted 14 lines · Qu Wenruo
Before this patch, chunk allocation is split into 2 parts:
1) Chunk allocation
Handled bybtrfs_alloc_chunk(), which will insert chunk and device extent items.2) Block group allocation
Handled bybtrfs_make_block_group(), which will insert block group item and update space info.However for chunk allocation, we don't really need to split these operations as all
btrfs_alloc_chunk()hasbtrfs_make_block_group()followed.
Quoted 5 lines
So it's reasonable to merge
btrfs_make_block_group()call intobtrfs_alloc_chunk()to save several lines, and provides the basis for laterbtrfs_alloc_chunk()rework.Signed-off-by Qu Wenruo <[email protected]>
Looks good to me.
Quoted 151 lines
--- convert/main.c | 4 ---- extent-tree.c | 10 ++-------- mkfs/main.c | 28 ---------------------------- volumes.c | 10 ++++++---- 4 files changed, 8 insertions(+), 44 deletions(-)convert/main.c +0
-4@@ -915,10 +915,6 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans, BTRFS_BLOCK_GROUP_DATA, true);if (ret <0 )break ; - ret =btrfs_make_block_group (trans, fs_info,0 , -BTRFS_BLOCK_GROUP_DATA , cur, len); -if (ret <0 ) -break ; cur += len; } }extent-tree.c +2
-8@@ -1910,15 +1910,9 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, space_info->flags, false);if (ret == -ENOSPC ) { space_info->full =1 ; -return 0 ; +return ret; } - -BUG_ON (ret); - - ret =btrfs_make_block_group (trans, fs_info,0 , space_info->flags, - start, num_bytes); -BUG_ON (ret); -return 0 ; +return ret; } static int update_block_group(struct btrfs_trans_handle *trans,mkfs/main.c +0
-28@@ -97,12 +97,6 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed,error ("no space to allocate data/metadata chunk" ); goto err; } -if (ret) -return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , -BTRFS_BLOCK_GROUP_METADATA | -BTRFS_BLOCK_GROUP_DATA , - chunk_start, chunk_size);if (ret)return ret; allocation->mixed += chunk_size;@@ -116,12 +110,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, }if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , -BTRFS_BLOCK_GROUP_METADATA , - chunk_start, chunk_size); allocation->metadata += chunk_size; -if (ret) -return ret; } root->fs_info->system_allocs =0 ;@@ -150,12 +139,7 @@ static int create_data_block_groups(struct btrfs_trans_handle *trans, }if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , -BTRFS_BLOCK_GROUP_DATA , - chunk_start, chunk_size); allocation->data += chunk_size; -if (ret) -return ret; } err:@@ -259,9 +243,6 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , - type, chunk_start, chunk_size); - type &=BTRFS_BLOCK_GROUP_TYPE_MASK ;if (type ==BTRFS_BLOCK_GROUP_DATA ) { allocation->data += chunk_size;@@ -1006,12 +987,7 @@ static int create_chunks(struct btrfs_trans_handle *trans, &chunk_start, &chunk_size, meta_type, false);if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , - meta_type, chunk_start, - chunk_size); allocation->metadata += chunk_size; -if (ret) -return ret;set_extent_dirty (&root->fs_info->free_space_cache, chunk_start, chunk_start + chunk_size -1 ); }@@ -1023,11 +999,7 @@ static int create_chunks(struct btrfs_trans_handle *trans, &chunk_start, &size_of_data, data_type, false);if (ret)return ret; - ret =btrfs_make_block_group (trans, fs_info,0 , - data_type, chunk_start, size_of_data); allocation->data += size_of_data; -if (ret) -return ret;set_extent_dirty (&root->fs_info->free_space_cache, chunk_start, chunk_start + size_of_data -1 );return ret;volumes.c +6
-4@@ -845,10 +845,9 @@ error: / 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() +* Alloc a chunk, will insert dev extents, chunk item, and insert new +* block group and update space info (so that extent allocator can use +* newly allocated chunk). * * @start: return value of allocated chunk start bytenr. * @num_bytes: return value of allocated chunk size @@ -1168,6 +1167,9 @@ alloc_chunk: }kfree (chunk); + + ret =btrfs_make_block_group (trans, info,0 , type, map->ce.start, + map->ce.size);return ret; out_chunk_map: