mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
btrfs: zoned: always set max_active_zones for zoned devices
When a block device does not report a maximum number of open or active
zones, currently assign BTRFS_DEFAULT_MAX_ACTIVE_ZONES (128) to
the internal limit, if the device has more than
BTRFS_DEFAULT_MAX_ACTIVE_ZONES zones.
But if the device has less than BTRFS_DEFAULT_MAX_ACTIVE_ZONES the
internal max_active_zones limit will stay at 0, even if the device has
zone resource limits. Furthermore, if the device has a total number of
zones that is less than BTRFS_DEFAULT_MAX_ACTIVE_ZONE, max_active_zones
should be set to at most the number of zones.
Also move the max_active_zone calculation and setting into a dedicated
helper, to shrink btrfs_get_dev_zone_info().
Fixes: 04147d8394 ("btrfs: zoned: limit active zones to max_open_zones")
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
3f1cc3620e
commit
21a3533b99
|
|
@ -356,12 +356,33 @@ int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int btrfs_get_max_active_zones(struct btrfs_device *device,
|
||||
struct btrfs_zoned_device_info *zone_info)
|
||||
{
|
||||
struct block_device *bdev = device->bdev;
|
||||
int max_active_zones;
|
||||
|
||||
if (unlikely(zone_info->nr_zones < BTRFS_MIN_ACTIVE_ZONES)) {
|
||||
btrfs_err(device->fs_info, "zoned: not enough zones to mount filesystem: %u < %d",
|
||||
zone_info->nr_zones, BTRFS_MIN_ACTIVE_ZONES);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max_active_zones = min_not_zero(bdev_max_active_zones(bdev),
|
||||
bdev_max_open_zones(bdev));
|
||||
if (max_active_zones == 0)
|
||||
max_active_zones = min(zone_info->nr_zones / 4,
|
||||
BTRFS_DEFAULT_MAX_ACTIVE_ZONES);
|
||||
|
||||
zone_info->max_active_zones = max(max_active_zones, BTRFS_MIN_ACTIVE_ZONES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = device->fs_info;
|
||||
struct btrfs_zoned_device_info *zone_info = NULL;
|
||||
struct block_device *bdev = device->bdev;
|
||||
unsigned int max_active_zones;
|
||||
unsigned int nactive;
|
||||
sector_t nr_sectors;
|
||||
sector_t sector = 0;
|
||||
|
|
@ -426,19 +447,9 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
|
|||
if (!IS_ALIGNED(nr_sectors, zone_sectors))
|
||||
zone_info->nr_zones++;
|
||||
|
||||
max_active_zones = min_not_zero(bdev_max_active_zones(bdev),
|
||||
bdev_max_open_zones(bdev));
|
||||
if (!max_active_zones && zone_info->nr_zones > BTRFS_DEFAULT_MAX_ACTIVE_ZONES)
|
||||
max_active_zones = BTRFS_DEFAULT_MAX_ACTIVE_ZONES;
|
||||
if (max_active_zones && max_active_zones < BTRFS_MIN_ACTIVE_ZONES) {
|
||||
btrfs_err(fs_info,
|
||||
"zoned: %s: max active zones %u is too small, need at least %u active zones",
|
||||
rcu_dereference(device->name), max_active_zones,
|
||||
BTRFS_MIN_ACTIVE_ZONES);
|
||||
ret = -EINVAL;
|
||||
ret = btrfs_get_max_active_zones(device, zone_info);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
zone_info->max_active_zones = max_active_zones;
|
||||
|
||||
zone_info->seq_zones = bitmap_zalloc(zone_info->nr_zones, GFP_KERNEL);
|
||||
if (!zone_info->seq_zones) {
|
||||
|
|
@ -519,26 +530,29 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (max_active_zones) {
|
||||
if (unlikely(nactive > max_active_zones)) {
|
||||
if (bdev_max_active_zones(bdev) == 0) {
|
||||
max_active_zones = 0;
|
||||
zone_info->max_active_zones = 0;
|
||||
goto validate;
|
||||
}
|
||||
if (unlikely(nactive > zone_info->max_active_zones)) {
|
||||
if (bdev_max_active_zones(bdev) > 0) {
|
||||
btrfs_err(device->fs_info,
|
||||
"zoned: %u active zones on %s exceeds max_active_zones %u",
|
||||
nactive, rcu_dereference(device->name),
|
||||
max_active_zones);
|
||||
"zoned: %u active zones on %s exceeds max_active_zones %u",
|
||||
nactive, rcu_dereference(device->name),
|
||||
zone_info->max_active_zones);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is for backward compatibility with old filesystems that
|
||||
* have a lot of active zones because the device doesn't report
|
||||
* a maximum number of zones and we previously didn't care for
|
||||
* the limit.
|
||||
*/
|
||||
zone_info->max_active_zones = 0;
|
||||
} else {
|
||||
atomic_set(&zone_info->active_zones_left,
|
||||
max_active_zones - nactive);
|
||||
zone_info->max_active_zones - nactive);
|
||||
set_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &fs_info->flags);
|
||||
}
|
||||
|
||||
validate:
|
||||
/* Validate superblock log */
|
||||
nr_zones = BTRFS_NR_SB_LOG_ZONES;
|
||||
for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user