diff mbox series

[07/26] btrfs-progs: zoned: introduce max_zone_append_size

Message ID 1023703371dbf8239f11f7fe8061b26dde480511.1619416549.git.naohiro.aota@wdc.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: zoned: zoned block device support | expand

Commit Message

Naohiro Aota April 26, 2021, 6:27 a.m. UTC
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(+)

Comments

Johannes Thumshirn April 26, 2021, 7:51 a.m. UTC | #1
Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
diff mbox series

Patch

diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index aab631a44785..5023db474784 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -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)
diff --git a/kernel-shared/zoned.c b/kernel-shared/zoned.c
index 7cb5262ba481..ee879a57b716 100644
--- a/kernel-shared/zoned.c
+++ b/kernel-shared/zoned.c
@@ -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;
diff --git a/kernel-shared/zoned.h b/kernel-shared/zoned.h
index a6134babdf41..fcf2ccf34f26 100644
--- a/kernel-shared/zoned.h
+++ b/kernel-shared/zoned.h
@@ -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;
 };