[PATCH 10/13] block: introduce BLKREPORTZONESV2 ioctl

Damien Le Moal
2025-10-31T06:17:12Z

Introduce the new BLKREPORTZONESV2 ioctl command to allow user
applications access to the fast zone report implemented by
blkdev_report_zones_cached(). This new ioctl is defined as number 142
and is documented in include/uapi/linux/fs.h.

Unlike the existing BLKREPORTZONES ioctl, this new ioctl uses the flags
field of struct blk_zone_report also as an inpiut. If as an input, the
user sets the flag BLK_ZONE_REP_CACHED, then
blkdev_report_zones_cached() is used to generate the zone report using
cached zone information. If this flag is not set, then BLKREPORTZONESV2
behaves in the same manner as BLKREPORTZONES and the zone report is
generated by accessing the zoned device.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
block/blk-zoned.c | 25 ++++++++++++++++++++++---
block/ioctl.c | 1 +
include/uapi/linux/blkzoned.h | 30 ++++++++++++++++++++++++++----
include/uapi/linux/fs.h | 2 +-
4 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index 0234bb7f41b3..c8335654b1cd 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -356,7 +356,12 @@ static int blkdev_copy_zone_to_user(struct blk_zone *zone, unsigned int idx,
}

/*
- * BLKREPORTZONE ioctl processing.
+ * Mask of valid input flags for BLKREPORTZONEV2 ioctl.
+ */
+#define BLK_ZONE_REPV2_INPUT_FLAGS (BLK_ZONE_REP_CACHED)
+
+/*
+ * BLKREPORTZONE and BLKREPORTZONEV2 ioctl processing.
* Called from blkdev_ioctl.
*/
int blkdev_report_zones_ioctl(struct block_device *bdev, unsigned int cmd,
@@ -380,8 +385,22 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, unsigned int cmd,
return -EINVAL;

args.zones = argp + sizeof(struct blk_zone_report);
- ret = blkdev_report_zones(bdev, rep.sector, rep.nr_zones,
- blkdev_copy_zone_to_user, &args);
+
+ switch (cmd) {
+ case BLKREPORTZONE:
+ ret = blkdev_report_zones(bdev, rep.sector, rep.nr_zones,
+ blkdev_copy_zone_to_user, &args);
+ break;
+ case BLKREPORTZONEV2:
+ if (rep.flags & ~BLK_ZONE_REPV2_INPUT_FLAGS)
+ return -EINVAL;
+ ret = blkdev_report_zones_cached(bdev, rep.sector, rep.nr_zones,
+ blkdev_copy_zone_to_user, &args);
+ break;
+ default:
+ return -EINVAL;
+ }
+
if (ret < 0)
return ret;

diff --git a/block/ioctl.c b/block/ioctl.c
index 3927ca4707d0..698629e4c619 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -581,6 +581,7 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
case BLKGETDISKSEQ:
return put_u64(argp, bdev->bd_disk->diskseq);
case BLKREPORTZONE:
+ case BLKREPORTZONEV2:
return blkdev_report_zones_ioctl(bdev, cmd, arg);
case BLKRESETZONE:
case BLKOPENZONE:
diff --git a/include/uapi/linux/blkzoned.h b/include/uapi/linux/blkzoned.h
index dab5d9700898..1441d79a6173 100644
--- a/include/uapi/linux/blkzoned.h
+++ b/include/uapi/linux/blkzoned.h
@@ -82,10 +82,20 @@ enum blk_zone_cond {
/**
* enum blk_zone_report_flags - Feature flags of reported zone descriptors.
*
- * @BLK_ZONE_REP_CAPACITY: Zone descriptor has capacity field.
+ * @BLK_ZONE_REP_CAPACITY: Output only. Indicates that zone descriptors in a
+ * zone report have a valid capacity field.
+ * @BLK_ZONE_REP_CACHED: Input only. Indicates that the zone report should be
+ * generated using cached zone information. In this case,
+ * the implicit open, explicit open and closed zone
+ * conditions are all reported with the
+ * BLK_ZONE_COND_ACTIVE condition.
*/
enum blk_zone_report_flags {
+ /* Output flags */
BLK_ZONE_REP_CAPACITY = (1 << 0),
+
+ /* Input flags */
+ BLK_ZONE_REP_CACHED = (1 << 31),
};

/**
@@ -128,6 +138,10 @@ struct blk_zone {
* @sector: starting sector of report
* @nr_zones: IN maximum / OUT actual
* @flags: one or more flags as defined by enum blk_zone_report_flags.
+ * @flags: one or more flags as defined by enum blk_zone_report_flags.
+ * With BLKREPORTZONE, this field is ignored as an input and is valid
+ * only as an output. Using BLKREPORTZONEV2, this field is used as both
+ * input and output.
* @zones: Space to hold @nr_zones @zones entries on reply.
*
* The array of at most @nr_zones must follow this structure in memory.
@@ -154,9 +168,16 @@ struct blk_zone_range {
/**
* Zoned block device ioctl's:
*
- * @BLKREPORTZONE: Get zone information. Takes a zone report as argument.
- * The zone report will start from the zone containing the
- * sector specified in the report request structure.
+ * @BLKREPORTZONE: Get zone information from a zoned device. Takes a zone report
+ * as argument. The zone report will start from the zone
+ * containing the sector specified in struct blk_zone_report.
+ * The flags field of struct blk_zone_report is used as an
+ * output only and ignored as an input.
+ * DEPRECATED, use BLKREPORTZONEV2 instead.
+ * @BLKREPORTZONEV2: Same as @BLKREPORTZONE but uses the flags field of
+ * struct blk_zone_report as an input, allowing to get a zone
+ * report using cached zone information if BLK_ZONE_REP_CACHED
+ * is set.
* @BLKRESETZONE: Reset the write pointer of the zones in the specified
* sector range. The sector range must be zone aligned.
* @BLKGETZONESZ: Get the device zone size in number of 512 B sectors.
@@ -175,5 +196,6 @@ struct blk_zone_range {
#define BLKOPENZONE _IOW(0x12, 134, struct blk_zone_range)
#define BLKCLOSEZONE _IOW(0x12, 135, struct blk_zone_range)
#define BLKFINISHZONE _IOW(0x12, 136, struct blk_zone_range)
+#define BLKREPORTZONEV2 _IOWR(0x12, 142, struct blk_zone_report)

#endif /* _UAPI_BLKZONED_H */
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 957ce3343a4f..66ca526cf786 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -298,7 +298,7 @@ struct file_attr {
#define BLKROTATIONAL _IO(0x12,126)
#define BLKZEROOUT _IO(0x12,127)
#define BLKGETDISKSEQ _IOR(0x12,128,__u64)
-/* 130-136 are used by zoned block device ioctls (uapi/linux/blkzoned.h) */
+/* 130-136 and 142 are used by zoned block device ioctls (uapi/linux/blkzoned.h) */
/* 137-141 are used by blk-crypto ioctls (uapi/linux/blk-crypto.h) */
#define BLKTRACESETUP2 _IOWR(0x12, 142, struct blk_user_trace_setup2)

--
2.51.0