@@ -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)
@@ -102,9 +114,19 @@ 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: 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");
@@ -248,6 +270,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;
@@ -282,6 +305,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++;
}
@@ -321,6 +349,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;
@@ -29,6 +29,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;
};
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. Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> --- kernel-shared/ctree.h | 3 +++ kernel-shared/zoned.c | 29 +++++++++++++++++++++++++++++ kernel-shared/zoned.h | 1 + 3 files changed, 33 insertions(+)