btrfs-progs: zoned: introduce max_zone_append_size
The zone append write command has a maximum IO size restriction it accepts. This is because a zone append write command cannot be split, as we ask the device to place the data into a specific target zone and the device responds with the actual written location of the data. Introduce max_zone_append_size to zone_info and fs_info to track the value, so we can limit all I/O to a zoned block device that we want to write using the zone append command to the device's limits. Zone append command is mandatory for zoned btrfs. So, reject a device with max_zone_append_size == 0. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
7e520022ff
commit
3c0f83e541
|
@ -1222,6 +1222,9 @@ struct btrfs_fs_info {
|
|||
u64 zone_size;
|
||||
u64 zoned;
|
||||
};
|
||||
|
||||
/* Max size to emit ZONE_APPEND write command */
|
||||
u64 max_zone_append_size;
|
||||
};
|
||||
|
||||
static inline bool btrfs_is_zoned(const struct btrfs_fs_info *fs_info)
|
||||
|
|
|
@ -58,6 +58,18 @@ u64 zone_size(const char *file)
|
|||
return strtoull((const char *)chunk, NULL, 10) << SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
u64 max_zone_append_size(const char *file)
|
||||
{
|
||||
char chunk[32];
|
||||
int ret;
|
||||
|
||||
ret = queue_param(file, "zone_append_max_bytes", chunk, sizeof(chunk));
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
|
||||
return strtoull((const char *)chunk, NULL, 10);
|
||||
}
|
||||
|
||||
#ifdef BTRFS_ZONED
|
||||
static int report_zones(int fd, const char *file,
|
||||
struct btrfs_zoned_device_info *zinfo)
|
||||
|
@ -101,9 +113,18 @@ static int report_zones(int fd, const char *file,
|
|||
|
||||
/* Allocate the zone information array */
|
||||
zinfo->zone_size = zone_bytes;
|
||||
zinfo->max_zone_append_size = max_zone_append_size(file);
|
||||
zinfo->nr_zones = device_size / zone_bytes;
|
||||
if (device_size & (zone_bytes - 1))
|
||||
zinfo->nr_zones++;
|
||||
|
||||
if (zoned_model(file) != ZONED_NONE &&
|
||||
zinfo->max_zone_append_size == 0) {
|
||||
error(
|
||||
"zoned: device %s does not support ZONE_APPEND command", file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
zinfo->zones = calloc(zinfo->nr_zones, sizeof(struct blk_zone));
|
||||
if (!zinfo->zones) {
|
||||
error("zoned: no memory for zone information");
|
||||
|
@ -246,6 +267,7 @@ int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info)
|
|||
u64 zoned_devices = 0;
|
||||
u64 nr_devices = 0;
|
||||
u64 zone_size = 0;
|
||||
u64 max_zone_append_size = 0;
|
||||
const bool incompat_zoned = btrfs_fs_incompat(fs_info, ZONED);
|
||||
int ret = 0;
|
||||
|
||||
|
@ -280,6 +302,11 @@ int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info)
|
|||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!max_zone_append_size ||
|
||||
(zone_info->max_zone_append_size &&
|
||||
zone_info->max_zone_append_size < max_zone_append_size))
|
||||
max_zone_append_size =
|
||||
zone_info->max_zone_append_size;
|
||||
}
|
||||
nr_devices++;
|
||||
}
|
||||
|
@ -319,6 +346,7 @@ int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info)
|
|||
}
|
||||
|
||||
fs_info->zone_size = zone_size;
|
||||
fs_info->max_zone_append_size = max_zone_append_size;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
|
|
@ -31,6 +31,7 @@ enum btrfs_zoned_model {
|
|||
struct btrfs_zoned_device_info {
|
||||
enum btrfs_zoned_model model;
|
||||
u64 zone_size;
|
||||
u64 max_zone_append_size;
|
||||
u32 nr_zones;
|
||||
struct blk_zone *zones;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue