mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 22:51:35 +00:00
btrfs: factor out decide_stripe_size()
Factor out decide_stripe_size() from __btrfs_alloc_chunk(). This function calculates the actual stripe size to allocate. decide_stripe_size() handles the common case to round down the 'ndevs' to 'devs_increment' and check the upper and lower limitation of 'ndevs'. decide_stripe_size_regular() decides the size of a stripe and the size of a chunk. The policy is to maximize the number of stripes. This commit has no functional changes. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
560156cb25
commit
5badf512ec
@ -4943,6 +4943,82 @@ static int gather_device_info(struct btrfs_fs_devices *fs_devices,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decide_stripe_size_regular(struct alloc_chunk_ctl *ctl,
|
||||
struct btrfs_device_info *devices_info)
|
||||
{
|
||||
/* Number of stripes that count for block group size */
|
||||
int data_stripes;
|
||||
|
||||
/*
|
||||
* The primary goal is to maximize the number of stripes, so use as
|
||||
* many devices as possible, even if the stripes are not maximum sized.
|
||||
*
|
||||
* The DUP profile stores more than one stripe per device, the
|
||||
* max_avail is the total size so we have to adjust.
|
||||
*/
|
||||
ctl->stripe_size = div_u64(devices_info[ctl->ndevs - 1].max_avail,
|
||||
ctl->dev_stripes);
|
||||
ctl->num_stripes = ctl->ndevs * ctl->dev_stripes;
|
||||
|
||||
/* This will have to be fixed for RAID1 and RAID10 over more drives */
|
||||
data_stripes = (ctl->num_stripes - ctl->nparity) / ctl->ncopies;
|
||||
|
||||
/*
|
||||
* Use the number of data stripes to figure out how big this chunk is
|
||||
* really going to be in terms of logical address space, and compare
|
||||
* that answer with the max chunk size. If it's higher, we try to
|
||||
* reduce stripe_size.
|
||||
*/
|
||||
if (ctl->stripe_size * data_stripes > ctl->max_chunk_size) {
|
||||
/*
|
||||
* Reduce stripe_size, round it up to a 16MB boundary again and
|
||||
* then use it, unless it ends up being even bigger than the
|
||||
* previous value we had already.
|
||||
*/
|
||||
ctl->stripe_size = min(round_up(div_u64(ctl->max_chunk_size,
|
||||
data_stripes), SZ_16M),
|
||||
ctl->stripe_size);
|
||||
}
|
||||
|
||||
/* Align to BTRFS_STRIPE_LEN */
|
||||
ctl->stripe_size = round_down(ctl->stripe_size, BTRFS_STRIPE_LEN);
|
||||
ctl->chunk_size = ctl->stripe_size * data_stripes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decide_stripe_size(struct btrfs_fs_devices *fs_devices,
|
||||
struct alloc_chunk_ctl *ctl,
|
||||
struct btrfs_device_info *devices_info)
|
||||
{
|
||||
struct btrfs_fs_info *info = fs_devices->fs_info;
|
||||
|
||||
/*
|
||||
* Round down to number of usable stripes, devs_increment can be any
|
||||
* number so we can't use round_down() that requires power of 2, while
|
||||
* rounddown is safe.
|
||||
*/
|
||||
ctl->ndevs = rounddown(ctl->ndevs, ctl->devs_increment);
|
||||
|
||||
if (ctl->ndevs < ctl->devs_min) {
|
||||
if (btrfs_test_opt(info, ENOSPC_DEBUG)) {
|
||||
btrfs_debug(info,
|
||||
"%s: not enough devices with free space: have=%d minimum required=%d",
|
||||
__func__, ctl->ndevs, ctl->devs_min);
|
||||
}
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
ctl->ndevs = min(ctl->ndevs, ctl->devs_max);
|
||||
|
||||
switch (fs_devices->chunk_alloc_policy) {
|
||||
case BTRFS_CHUNK_ALLOC_REGULAR:
|
||||
return decide_stripe_size_regular(ctl, devices_info);
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
||||
u64 start, u64 type)
|
||||
{
|
||||
@ -4953,8 +5029,6 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
||||
struct extent_map *em;
|
||||
struct btrfs_device_info *devices_info = NULL;
|
||||
struct alloc_chunk_ctl ctl;
|
||||
/* Number of stripes that count for block group size */
|
||||
int data_stripes;
|
||||
int ret;
|
||||
int i;
|
||||
int j;
|
||||
@ -4989,61 +5063,9 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Round down to number of usable stripes, devs_increment can be any
|
||||
* number so we can't use round_down()
|
||||
*/
|
||||
ctl.ndevs -= ctl.ndevs % ctl.devs_increment;
|
||||
|
||||
if (ctl.ndevs < ctl.devs_min) {
|
||||
ret = -ENOSPC;
|
||||
if (btrfs_test_opt(info, ENOSPC_DEBUG)) {
|
||||
btrfs_debug(info,
|
||||
"%s: not enough devices with free space: have=%d minimum required=%d",
|
||||
__func__, ctl.ndevs, ctl.devs_min);
|
||||
}
|
||||
ret = decide_stripe_size(fs_devices, &ctl, devices_info);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ctl.ndevs = min(ctl.ndevs, ctl.devs_max);
|
||||
|
||||
/*
|
||||
* The primary goal is to maximize the number of stripes, so use as
|
||||
* many devices as possible, even if the stripes are not maximum sized.
|
||||
*
|
||||
* The DUP profile stores more than one stripe per device, the
|
||||
* max_avail is the total size so we have to adjust.
|
||||
*/
|
||||
ctl.stripe_size = div_u64(devices_info[ctl.ndevs - 1].max_avail,
|
||||
ctl.dev_stripes);
|
||||
ctl.num_stripes = ctl.ndevs * ctl.dev_stripes;
|
||||
|
||||
/*
|
||||
* this will have to be fixed for RAID1 and RAID10 over
|
||||
* more drives
|
||||
*/
|
||||
data_stripes = (ctl.num_stripes - ctl.nparity) / ctl.ncopies;
|
||||
|
||||
/*
|
||||
* Use the number of data stripes to figure out how big this chunk
|
||||
* is really going to be in terms of logical address space,
|
||||
* and compare that answer with the max chunk size. If it's higher,
|
||||
* we try to reduce stripe_size.
|
||||
*/
|
||||
if (ctl.stripe_size * data_stripes > ctl.max_chunk_size) {
|
||||
/*
|
||||
* Reduce stripe_size, round it up to a 16MB boundary again and
|
||||
* then use it, unless it ends up being even bigger than the
|
||||
* previous value we had already.
|
||||
*/
|
||||
ctl.stripe_size =
|
||||
min(round_up(div_u64(ctl.max_chunk_size, data_stripes),
|
||||
SZ_16M),
|
||||
ctl.stripe_size);
|
||||
}
|
||||
|
||||
/* align to BTRFS_STRIPE_LEN */
|
||||
ctl.stripe_size = round_down(ctl.stripe_size, BTRFS_STRIPE_LEN);
|
||||
|
||||
map = kmalloc(map_lookup_size(ctl.num_stripes), GFP_NOFS);
|
||||
if (!map) {
|
||||
@ -5067,8 +5089,6 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
||||
map->type = type;
|
||||
map->sub_stripes = ctl.sub_stripes;
|
||||
|
||||
ctl.chunk_size = ctl.stripe_size * data_stripes;
|
||||
|
||||
trace_btrfs_chunk_alloc(info, map, start, ctl.chunk_size);
|
||||
|
||||
em = alloc_extent_map();
|
||||
|
Loading…
Reference in New Issue
Block a user