diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 2cf8da1116eb..bfe884f13934 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -187,6 +187,15 @@ void btrfs_clear_space_info_full(struct btrfs_fs_info *info) */ #define BTRFS_DEFAULT_ZONED_RECLAIM_THRESH (75) +/* + * Update default chunk size. + */ +void btrfs_update_space_info_chunk_size(struct btrfs_space_info *space_info, + u64 chunk_size) +{ + WRITE_ONCE(space_info->chunk_size, chunk_size); +} + static int create_space_info(struct btrfs_fs_info *info, u64 flags) { diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h index c096695598c1..e7de24a529cf 100644 --- a/fs/btrfs/space-info.h +++ b/fs/btrfs/space-info.h @@ -25,6 +25,8 @@ struct btrfs_space_info { u64 max_extent_size; /* This will hold the maximum extent size of the space info if we had an ENOSPC in the allocator. */ + /* Chunk size in bytes */ + u64 chunk_size; /* * Once a block group drops below this threshold (percents) we'll @@ -123,6 +125,8 @@ void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags, u64 total_bytes, u64 bytes_used, u64 bytes_readonly, u64 bytes_zone_unusable, struct btrfs_space_info **space_info); +void btrfs_update_space_info_chunk_size(struct btrfs_space_info *space_info, + u64 chunk_size); struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info, u64 flags); u64 __pure btrfs_space_info_used(struct btrfs_space_info *s_info, diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a2bb0928dc06..b7b7d254ecf0 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -5072,6 +5072,7 @@ static void init_alloc_chunk_ctl_policy_regular( struct alloc_chunk_ctl *ctl) { u64 type = ctl->type; + struct btrfs_space_info *space_info; if (type & BTRFS_BLOCK_GROUP_DATA) { ctl->max_stripe_size = SZ_1G; @@ -5095,7 +5096,17 @@ static void init_alloc_chunk_ctl_policy_regular( /* We don't want a chunk larger than 10% of writable space */ ctl->max_chunk_size = min(div_factor(fs_devices->total_rw_bytes, 1), ctl->max_chunk_size); + if(ctl->max_stripe_size > ctl->max_chunk_size) + ctl->max_stripe_size = ctl->max_chunk_size; + ctl->dev_extent_min = BTRFS_STRIPE_LEN * ctl->dev_stripes; + + if (ctl->type & BTRFS_BLOCK_GROUP_SYSTEM) + ctl->devs_max = min_t(int, ctl->devs_max, BTRFS_MAX_DEVS_SYS_CHUNK); + + space_info = btrfs_find_space_info(fs_devices->fs_info, ctl->type); + ASSERT(space_info); + btrfs_update_space_info_chunk_size(space_info, ctl->max_chunk_size); } static void init_alloc_chunk_ctl_policy_zoned( @@ -5108,6 +5119,7 @@ static void init_alloc_chunk_ctl_policy_zoned( int min_data_stripes = (min_num_stripes - ctl->nparity) / ctl->ncopies; u64 min_chunk_size = min_data_stripes * zone_size; u64 type = ctl->type; + struct btrfs_space_info *space_info; ctl->max_stripe_size = zone_size; if (type & BTRFS_BLOCK_GROUP_DATA) { @@ -5129,6 +5141,10 @@ static void init_alloc_chunk_ctl_policy_zoned( min_chunk_size); ctl->max_chunk_size = min(limit, ctl->max_chunk_size); ctl->dev_extent_min = zone_size * ctl->dev_stripes; + + space_info = btrfs_find_space_info(fs_devices->fs_info, ctl->type); + ASSERT(space_info); + btrfs_update_space_info_chunk_size(space_info, ctl->max_chunk_size); } static void init_alloc_chunk_ctl(struct btrfs_fs_devices *fs_devices,