* enable cached zone report v5
@ 2026-01-28 4:32 Christoph Hellwig
2026-01-28 4:32 ` [PATCH 1/5] include blkzoned.h in platform_defs.h Christoph Hellwig
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Christoph Hellwig @ 2026-01-28 4:32 UTC (permalink / raw)
To: Andrey Albershteyn
Cc: Damien Le Moal, Darrick J . Wong, Carlos Maiolino, linux-xfs
Enable cached zone report to speed up mkfs and repair on a zoned block
device (e.g. an SMR disk). Cached zone report support was introduced in
the kernel with version 6.19-rc1.
Note: I've taken this series over from Damien as he's busy and it need
it as a base for further work.
Changes from v4:
- include blkzoned.h from platform_defs.h and add the missing bits
there to avoid problems with newer kernel headers
Changes from v3:
- reorder includes to not need the forward declaration in xfs_zones.h
- use the libfrog/ for #include statements
- fix the include guard in libfrog/zones.h
- fix up i18n string mess
- hide the new ioctl definition in libfrog/zones.c
- don't add userspace includes to libxfs/xfs_zones.h
- reuse the buffer for multiple report zone calls
Changes from v2:
- Complete rework of the series to make the zone reporting code common
in libfrog
- Added patch 1 and 2 as small cleanups/improvements.
Changes from v1:
- Fix erroneous handling of ioctl(BLKREPORTZONEV2) error to correctly
fallback to the regular ioctl(BLKREPORTZONE) if the kernel does not
support BLKREPORTZONEV2.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/5] include blkzoned.h in platform_defs.h
2026-01-28 4:32 enable cached zone report v5 Christoph Hellwig
@ 2026-01-28 4:32 ` Christoph Hellwig
2026-01-28 5:11 ` Darrick J. Wong
2026-01-28 5:58 ` Damien Le Moal
2026-01-28 4:32 ` [PATCH 2/5] xfs: use blkdev_report_zones_cached() Christoph Hellwig
` (3 subsequent siblings)
4 siblings, 2 replies; 10+ messages in thread
From: Christoph Hellwig @ 2026-01-28 4:32 UTC (permalink / raw)
To: Andrey Albershteyn
Cc: Damien Le Moal, Darrick J . Wong, Carlos Maiolino, linux-xfs
We'll need to conditionally add definitions added in later version of
blkzoned.h soon. The right place for that is platform_defs.h, which
means blkzoned.h needs to be included there for cpp trickery to work.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/platform_defs.h | 1 +
libxfs/xfs_zones.c | 1 -
mdrestore/xfs_mdrestore.c | 1 -
mkfs/xfs_mkfs.c | 1 -
repair/zoned.c | 1 -
5 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/include/platform_defs.h b/include/platform_defs.h
index da966490b0f5..1152f0622ccf 100644
--- a/include/platform_defs.h
+++ b/include/platform_defs.h
@@ -24,6 +24,7 @@
#include <stdbool.h>
#include <libgen.h>
#include <urcu.h>
+#include <linux/blkzoned.h>
/* long and pointer must be either 32 bit or 64 bit */
#define BITS_PER_LONG (sizeof(long) * CHAR_BIT)
diff --git a/libxfs/xfs_zones.c b/libxfs/xfs_zones.c
index 7a81d83f5b3e..c1ad7075329c 100644
--- a/libxfs/xfs_zones.c
+++ b/libxfs/xfs_zones.c
@@ -3,7 +3,6 @@
* Copyright (c) 2023-2025 Christoph Hellwig.
* Copyright (c) 2024-2025, Western Digital Corporation or its affiliates.
*/
-#include <linux/blkzoned.h>
#include "libxfs_priv.h"
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/mdrestore/xfs_mdrestore.c b/mdrestore/xfs_mdrestore.c
index b6e8a6196a79..eece58977f97 100644
--- a/mdrestore/xfs_mdrestore.c
+++ b/mdrestore/xfs_mdrestore.c
@@ -8,7 +8,6 @@
#include "xfs_metadump.h"
#include <libfrog/platform.h>
#include "libfrog/div64.h"
-#include <linux/blkzoned.h>
union mdrestore_headers {
__be32 magic;
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index b34407725f76..46f4faf4de5a 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -6,7 +6,6 @@
#include "libfrog/util.h"
#include "libxfs.h"
#include <ctype.h>
-#include <linux/blkzoned.h>
#include "libxfs/xfs_zones.h"
#include "xfs_multidisk.h"
#include "libxcmd.h"
diff --git a/repair/zoned.c b/repair/zoned.c
index 206b0158f95f..49cc43984883 100644
--- a/repair/zoned.c
+++ b/repair/zoned.c
@@ -3,7 +3,6 @@
* Copyright (c) 2024 Christoph Hellwig.
*/
#include <ctype.h>
-#include <linux/blkzoned.h>
#include "libxfs_priv.h"
#include "libxfs.h"
#include "xfs_zones.h"
--
2.47.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/5] xfs: use blkdev_report_zones_cached()
2026-01-28 4:32 enable cached zone report v5 Christoph Hellwig
2026-01-28 4:32 ` [PATCH 1/5] include blkzoned.h in platform_defs.h Christoph Hellwig
@ 2026-01-28 4:32 ` Christoph Hellwig
2026-01-28 4:32 ` [PATCH 3/5] mkfs: remove unnecessary return value affectation Christoph Hellwig
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2026-01-28 4:32 UTC (permalink / raw)
To: Andrey Albershteyn
Cc: Damien Le Moal, Darrick J . Wong, Carlos Maiolino, linux-xfs,
Martin K. Petersen, Jens Axboe
From: Damien Le Moal <dlemoal@kernel.org>
Source kernel commit: e04ccfc28252f181ea8d469d834b48e7dece65b2
Modify xfs_mount_zones() to replace the call to blkdev_report_zones()
with blkdev_report_zones_cached() to speed-up mount operations.
Since this causes xfs_zone_validate_seq() to see zones with the
BLK_ZONE_COND_ACTIVE condition, this function is also modified to acept
this condition as valid.
With this change, mounting a freshly formatted large capacity (30 TB)
SMR HDD completes under 2s compared to over 4.7s before.
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/platform_defs.h | 8 ++++++++
libxfs/xfs_zones.c | 1 +
2 files changed, 9 insertions(+)
diff --git a/include/platform_defs.h b/include/platform_defs.h
index 1152f0622ccf..1a9f401fc11c 100644
--- a/include/platform_defs.h
+++ b/include/platform_defs.h
@@ -308,4 +308,12 @@ struct kvec {
size_t iov_len;
};
+/*
+ * Local definitions for the new cached report zones added in Linux 6.19 in case
+ * the system <linux/blkzoned.h> doesn't provide them yet.
+ */
+#ifndef BLK_ZONE_COND_ACTIVE
+#define BLK_ZONE_COND_ACTIVE 0xff
+#endif
+
#endif /* __XFS_PLATFORM_DEFS_H__ */
diff --git a/libxfs/xfs_zones.c b/libxfs/xfs_zones.c
index c1ad7075329c..90e2ba0908be 100644
--- a/libxfs/xfs_zones.c
+++ b/libxfs/xfs_zones.c
@@ -96,6 +96,7 @@ xfs_zone_validate_seq(
case BLK_ZONE_COND_IMP_OPEN:
case BLK_ZONE_COND_EXP_OPEN:
case BLK_ZONE_COND_CLOSED:
+ case BLK_ZONE_COND_ACTIVE:
return xfs_zone_validate_wp(zone, rtg, write_pointer);
case BLK_ZONE_COND_FULL:
return xfs_zone_validate_full(zone, rtg, write_pointer);
--
2.47.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/5] mkfs: remove unnecessary return value affectation
2026-01-28 4:32 enable cached zone report v5 Christoph Hellwig
2026-01-28 4:32 ` [PATCH 1/5] include blkzoned.h in platform_defs.h Christoph Hellwig
2026-01-28 4:32 ` [PATCH 2/5] xfs: use blkdev_report_zones_cached() Christoph Hellwig
@ 2026-01-28 4:32 ` Christoph Hellwig
2026-01-28 4:32 ` [PATCH 4/5] libfrog: lift common zone reporting code from mkfs and repair Christoph Hellwig
2026-01-28 4:32 ` [PATCH 5/5] libfrog: enable cached report zones Christoph Hellwig
4 siblings, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2026-01-28 4:32 UTC (permalink / raw)
To: Andrey Albershteyn
Cc: Damien Le Moal, Darrick J . Wong, Carlos Maiolino, linux-xfs
From: Damien Le Moal <dlemoal@kernel.org>
The function report_zones() in mkfs/xfs_mkfs.c is a void function. So
there is no need to set the variable ret to -EIO before returning if
fstat() fails.
Fixes: 2e5a737a61d3 ("xfs_mkfs: support creating file system with zoned RT devices")
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
mkfs/xfs_mkfs.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 46f4faf4de5a..b5caa83a799d 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2586,10 +2586,8 @@ report_zones(
exit(1);
}
- if (fstat(fd, &st) < 0) {
- ret = -EIO;
+ if (fstat(fd, &st) < 0)
goto out_close;
- }
if (!S_ISBLK(st.st_mode))
goto out_close;
--
2.47.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/5] libfrog: lift common zone reporting code from mkfs and repair
2026-01-28 4:32 enable cached zone report v5 Christoph Hellwig
` (2 preceding siblings ...)
2026-01-28 4:32 ` [PATCH 3/5] mkfs: remove unnecessary return value affectation Christoph Hellwig
@ 2026-01-28 4:32 ` Christoph Hellwig
2026-01-28 5:09 ` Darrick J. Wong
2026-01-28 4:32 ` [PATCH 5/5] libfrog: enable cached report zones Christoph Hellwig
4 siblings, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2026-01-28 4:32 UTC (permalink / raw)
To: Andrey Albershteyn
Cc: Damien Le Moal, Darrick J . Wong, Carlos Maiolino, linux-xfs
From: Damien Le Moal <dlemoal@kernel.org>
Define the new helper function xfrog_report_zones() to report zones of
a zoned block device. This function is implemented in the new file
libfrog/zones.c and defined in the header file libfrog/zones.h and
use it from mkfs and repair instead of the previous open coded versions.
xfrog_report_zones() allocates and returns a struct blk_zone_report
structure, which can be be reused by subsequent invocations. It is the
responsibility of the caller to free this structure after use.
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
[hch: refactored to allow buffer reuse]
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
libfrog/Makefile | 6 ++++--
libfrog/zones.c | 39 +++++++++++++++++++++++++++++++++++++++
libfrog/zones.h | 16 ++++++++++++++++
mkfs/xfs_mkfs.c | 41 ++++++++++++-----------------------------
repair/zoned.c | 35 +++++++++++------------------------
5 files changed, 82 insertions(+), 55 deletions(-)
create mode 100644 libfrog/zones.c
create mode 100644 libfrog/zones.h
diff --git a/libfrog/Makefile b/libfrog/Makefile
index 268fa26638d7..9f405ffe3475 100644
--- a/libfrog/Makefile
+++ b/libfrog/Makefile
@@ -35,7 +35,8 @@ radix-tree.c \
randbytes.c \
scrub.c \
util.c \
-workqueue.c
+workqueue.c \
+zones.c
HFILES = \
avl64.h \
@@ -65,7 +66,8 @@ radix-tree.h \
randbytes.h \
scrub.h \
statx.h \
-workqueue.h
+workqueue.h \
+zones.h
GETTEXT_PY = \
gettext.py
diff --git a/libfrog/zones.c b/libfrog/zones.c
new file mode 100644
index 000000000000..2276c56bec9c
--- /dev/null
+++ b/libfrog/zones.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025, Western Digital Corporation or its affiliates.
+ */
+#include "platform_defs.h"
+#include "libfrog/zones.h"
+#include <sys/ioctl.h>
+
+/* random size that allows efficient processing */
+#define ZONES_PER_REPORT 16384
+
+struct xfrog_zone_report *
+xfrog_report_zones(
+ int fd,
+ uint64_t sector,
+ struct xfrog_zone_report *rep)
+{
+ if (!rep) {
+ rep = calloc(1, struct_size(rep, zones, ZONES_PER_REPORT));
+ if (!rep) {
+ fprintf(stderr, "%s\n",
+_("Failed to allocate memory for reporting zones."));
+ return NULL;
+ }
+ }
+
+ rep->rep.sector = sector;
+ rep->rep.nr_zones = ZONES_PER_REPORT;
+
+ if (ioctl(fd, BLKREPORTZONE, &rep->rep)) {
+ fprintf(stderr, "%s %s\n",
+_("ioctl(BLKREPORTZONE) failed:\n"),
+ strerror(-errno));
+ free(rep);
+ return NULL;
+ }
+
+ return rep;
+}
diff --git a/libfrog/zones.h b/libfrog/zones.h
new file mode 100644
index 000000000000..3592d48927f1
--- /dev/null
+++ b/libfrog/zones.h
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025, Western Digital Corporation or its affiliates.
+ */
+#ifndef __LIBFROG_ZONES_H__
+#define __LIBFROG_ZONES_H__
+
+struct xfrog_zone_report {
+ struct blk_zone_report rep;
+ struct blk_zone zones[];
+};
+
+struct xfrog_zone_report *
+xfrog_report_zones(int fd, uint64_t sector, struct xfrog_zone_report *rep);
+
+#endif /* __LIBFROG_ZONES_H__ */
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index b5caa83a799d..b99febf2b15f 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -14,6 +14,7 @@
#include "libfrog/crc32cselftest.h"
#include "libfrog/dahashselftest.h"
#include "libfrog/fsproperties.h"
+#include "libfrog/zones.h"
#include "proto.h"
#include <ini.h>
@@ -2541,9 +2542,6 @@ struct zone_topology {
struct zone_info log;
};
-/* random size that allows efficient processing */
-#define ZONES_PER_IOCTL 16384
-
static void
zone_validate_capacity(
struct zone_info *zi,
@@ -2571,12 +2569,11 @@ report_zones(
const char *name,
struct zone_info *zi)
{
- struct blk_zone_report *rep;
+ struct xfrog_zone_report *rep = NULL;
bool found_seq = false;
- int fd, ret = 0;
+ int fd;
uint64_t device_size;
uint64_t sector = 0;
- size_t rep_size;
unsigned int i, n = 0;
struct stat st;
@@ -2603,32 +2600,18 @@ report_zones(
zi->nr_zones = device_size / zi->zone_size;
zi->nr_conv_zones = 0;
- rep_size = sizeof(struct blk_zone_report) +
- sizeof(struct blk_zone) * ZONES_PER_IOCTL;
- rep = malloc(rep_size);
- if (!rep) {
- fprintf(stderr,
-_("Failed to allocate memory for zone reporting.\n"));
- exit(1);
- }
-
while (n < zi->nr_zones) {
- struct blk_zone *zones = (struct blk_zone *)(rep + 1);
+ struct blk_zone *zones;
- memset(rep, 0, rep_size);
- rep->sector = sector;
- rep->nr_zones = ZONES_PER_IOCTL;
-
- ret = ioctl(fd, BLKREPORTZONE, rep);
- if (ret) {
- fprintf(stderr,
-_("ioctl(BLKREPORTZONE) failed: %d!\n"), -errno);
+ rep = xfrog_report_zones(fd, sector, rep);
+ if (!rep)
exit(1);
- }
- if (!rep->nr_zones)
+
+ if (!rep->rep.nr_zones)
break;
- for (i = 0; i < rep->nr_zones; i++) {
+ zones = rep->zones;
+ for (i = 0; i < rep->rep.nr_zones; i++) {
if (n >= zi->nr_zones)
break;
@@ -2675,8 +2658,8 @@ _("Unknown zone type (0x%x) found.\n"), zones[i].type);
n++;
}
- sector = zones[rep->nr_zones - 1].start +
- zones[rep->nr_zones - 1].len;
+ sector = zones[rep->rep.nr_zones - 1].start +
+ zones[rep->rep.nr_zones - 1].len;
}
free(rep);
diff --git a/repair/zoned.c b/repair/zoned.c
index 49cc43984883..07e676ac7fd3 100644
--- a/repair/zoned.c
+++ b/repair/zoned.c
@@ -6,6 +6,7 @@
#include "libxfs_priv.h"
#include "libxfs.h"
#include "xfs_zones.h"
+#include "libfrog/zones.h"
#include "err_protos.h"
#include "zoned.h"
@@ -50,8 +51,7 @@ check_zones(
uint64_t sector = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rtstart);
unsigned int zone_size, zone_capacity;
uint64_t device_size;
- size_t rep_size;
- struct blk_zone_report *rep;
+ struct xfrog_zone_report *rep = NULL;
unsigned int i, n = 0;
if (ioctl(fd, BLKGETSIZE64, &device_size))
@@ -66,31 +66,18 @@ check_zones(
return;
}
- rep_size = sizeof(struct blk_zone_report) +
- sizeof(struct blk_zone) * ZONES_PER_IOCTL;
- rep = malloc(rep_size);
- if (!rep) {
- do_warn(_("malloc failed for zone report\n"));
- return;
- }
-
while (n < mp->m_sb.sb_rgcount) {
- struct blk_zone *zones = (struct blk_zone *)(rep + 1);
- int ret;
+ struct blk_zone *zones;
- memset(rep, 0, rep_size);
- rep->sector = sector;
- rep->nr_zones = ZONES_PER_IOCTL;
+ rep = xfrog_report_zones(fd, sector, rep);
+ if (!rep)
+ return;
- ret = ioctl(fd, BLKREPORTZONE, rep);
- if (ret) {
- do_error(_("ioctl(BLKREPORTZONE) failed: %d!\n"), ret);
- goto out_free;
- }
- if (!rep->nr_zones)
+ if (!rep->rep.nr_zones)
break;
- for (i = 0; i < rep->nr_zones; i++) {
+ zones = rep->zones;
+ for (i = 0; i < rep->rep.nr_zones; i++) {
if (n >= mp->m_sb.sb_rgcount)
break;
@@ -129,8 +116,8 @@ _("Inconsistent zone capacity!\n"));
report_zones_cb(mp, &zones[i]);
n++;
}
- sector = zones[rep->nr_zones - 1].start +
- zones[rep->nr_zones - 1].len;
+ sector = zones[rep->rep.nr_zones - 1].start +
+ zones[rep->rep.nr_zones - 1].len;
}
out_free:
--
2.47.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/5] libfrog: enable cached report zones
2026-01-28 4:32 enable cached zone report v5 Christoph Hellwig
` (3 preceding siblings ...)
2026-01-28 4:32 ` [PATCH 4/5] libfrog: lift common zone reporting code from mkfs and repair Christoph Hellwig
@ 2026-01-28 4:32 ` Christoph Hellwig
2026-01-28 5:10 ` Darrick J. Wong
4 siblings, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2026-01-28 4:32 UTC (permalink / raw)
To: Andrey Albershteyn
Cc: Damien Le Moal, Darrick J . Wong, Carlos Maiolino, linux-xfs
Modify the function xfrog_report_zones() to default to always trying
first a cached report zones using the BLKREPORTZONEV2 ioctl.
If the kernel does not support BLKREPORTZONEV2, fall back to the
(slower) regular report zones BLKREPORTZONE ioctl.
TO enable this feature even if xfsprogs is compiled on a system where
linux/blkzoned.h does not define BLKREPORTZONEV2, this ioctl is defined
in libfrog/zones.h, together with the BLK_ZONE_REP_CACHED flag and the
BLK_ZONE_COND_ACTIVE zone condition.
Since a cached report zone always return the condition
BLK_ZONE_COND_ACTIVE for any zone that is implicitly open, explicitly
open or closed, the function xfs_zone_validate_seq() is modified to
handle this new condition as being equivalent to the implicit open,
explicit open or closed conditions.
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
[hch: don't try cached reporting again if not supported]
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/platform_defs.h | 6 ++++++
libfrog/zones.c | 22 +++++++++++++++++++++-
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/include/platform_defs.h b/include/platform_defs.h
index 1a9f401fc11c..09129e0f22dc 100644
--- a/include/platform_defs.h
+++ b/include/platform_defs.h
@@ -312,6 +312,12 @@ struct kvec {
* Local definitions for the new cached report zones added in Linux 6.19 in case
* the system <linux/blkzoned.h> doesn't provide them yet.
*/
+#ifndef BLKREPORTZONEV2
+#define BLKREPORTZONEV2 _IOWR(0x12, 142, struct blk_zone_report)
+#endif
+#ifndef BLK_ZONE_REP_CACHED
+#define BLK_ZONE_REP_CACHED (1U << 31)
+#endif
#ifndef BLK_ZONE_COND_ACTIVE
#define BLK_ZONE_COND_ACTIVE 0xff
#endif
diff --git a/libfrog/zones.c b/libfrog/zones.c
index 2276c56bec9c..c088d3240545 100644
--- a/libfrog/zones.c
+++ b/libfrog/zones.c
@@ -3,12 +3,15 @@
* Copyright (c) 2025, Western Digital Corporation or its affiliates.
*/
#include "platform_defs.h"
+#include "atomic.h"
#include "libfrog/zones.h"
#include <sys/ioctl.h>
/* random size that allows efficient processing */
#define ZONES_PER_REPORT 16384
+static atomic_t cached_reporting_disabled;
+
struct xfrog_zone_report *
xfrog_report_zones(
int fd,
@@ -24,10 +27,27 @@ _("Failed to allocate memory for reporting zones."));
}
}
+ /*
+ * Try cached report zones first. If this fails, fallback to the regular
+ * (slower) report zones.
+ */
rep->rep.sector = sector;
rep->rep.nr_zones = ZONES_PER_REPORT;
- if (ioctl(fd, BLKREPORTZONE, &rep->rep)) {
+ if (atomic_read(&cached_reporting_disabled))
+ goto uncached;
+
+ rep->rep.flags = BLK_ZONE_REP_CACHED;
+ if (ioctl(fd, BLKREPORTZONEV2, &rep->rep)) {
+ atomic_inc(&cached_reporting_disabled);
+ goto uncached;
+ }
+
+ return rep;
+
+uncached:
+ rep->rep.flags = 0;
+ if (ioctl(fd, BLKREPORTZONE, rep)) {
fprintf(stderr, "%s %s\n",
_("ioctl(BLKREPORTZONE) failed:\n"),
strerror(-errno));
--
2.47.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 4/5] libfrog: lift common zone reporting code from mkfs and repair
2026-01-28 4:32 ` [PATCH 4/5] libfrog: lift common zone reporting code from mkfs and repair Christoph Hellwig
@ 2026-01-28 5:09 ` Darrick J. Wong
0 siblings, 0 replies; 10+ messages in thread
From: Darrick J. Wong @ 2026-01-28 5:09 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Andrey Albershteyn, Damien Le Moal, Carlos Maiolino, linux-xfs
On Wed, Jan 28, 2026 at 05:32:58AM +0100, Christoph Hellwig wrote:
> From: Damien Le Moal <dlemoal@kernel.org>
>
> Define the new helper function xfrog_report_zones() to report zones of
> a zoned block device. This function is implemented in the new file
> libfrog/zones.c and defined in the header file libfrog/zones.h and
> use it from mkfs and repair instead of the previous open coded versions.
>
> xfrog_report_zones() allocates and returns a struct blk_zone_report
> structure, which can be be reused by subsequent invocations. It is the
> responsibility of the caller to free this structure after use.
>
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
> [hch: refactored to allow buffer reuse]
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Still looks good,
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> ---
> libfrog/Makefile | 6 ++++--
> libfrog/zones.c | 39 +++++++++++++++++++++++++++++++++++++++
> libfrog/zones.h | 16 ++++++++++++++++
> mkfs/xfs_mkfs.c | 41 ++++++++++++-----------------------------
> repair/zoned.c | 35 +++++++++++------------------------
> 5 files changed, 82 insertions(+), 55 deletions(-)
> create mode 100644 libfrog/zones.c
> create mode 100644 libfrog/zones.h
>
> diff --git a/libfrog/Makefile b/libfrog/Makefile
> index 268fa26638d7..9f405ffe3475 100644
> --- a/libfrog/Makefile
> +++ b/libfrog/Makefile
> @@ -35,7 +35,8 @@ radix-tree.c \
> randbytes.c \
> scrub.c \
> util.c \
> -workqueue.c
> +workqueue.c \
> +zones.c
>
> HFILES = \
> avl64.h \
> @@ -65,7 +66,8 @@ radix-tree.h \
> randbytes.h \
> scrub.h \
> statx.h \
> -workqueue.h
> +workqueue.h \
> +zones.h
>
> GETTEXT_PY = \
> gettext.py
> diff --git a/libfrog/zones.c b/libfrog/zones.c
> new file mode 100644
> index 000000000000..2276c56bec9c
> --- /dev/null
> +++ b/libfrog/zones.c
> @@ -0,0 +1,39 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025, Western Digital Corporation or its affiliates.
> + */
> +#include "platform_defs.h"
> +#include "libfrog/zones.h"
> +#include <sys/ioctl.h>
> +
> +/* random size that allows efficient processing */
> +#define ZONES_PER_REPORT 16384
> +
> +struct xfrog_zone_report *
> +xfrog_report_zones(
> + int fd,
> + uint64_t sector,
> + struct xfrog_zone_report *rep)
> +{
> + if (!rep) {
> + rep = calloc(1, struct_size(rep, zones, ZONES_PER_REPORT));
> + if (!rep) {
> + fprintf(stderr, "%s\n",
> +_("Failed to allocate memory for reporting zones."));
> + return NULL;
> + }
> + }
> +
> + rep->rep.sector = sector;
> + rep->rep.nr_zones = ZONES_PER_REPORT;
> +
> + if (ioctl(fd, BLKREPORTZONE, &rep->rep)) {
> + fprintf(stderr, "%s %s\n",
> +_("ioctl(BLKREPORTZONE) failed:\n"),
> + strerror(-errno));
> + free(rep);
> + return NULL;
> + }
> +
> + return rep;
> +}
> diff --git a/libfrog/zones.h b/libfrog/zones.h
> new file mode 100644
> index 000000000000..3592d48927f1
> --- /dev/null
> +++ b/libfrog/zones.h
> @@ -0,0 +1,16 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025, Western Digital Corporation or its affiliates.
> + */
> +#ifndef __LIBFROG_ZONES_H__
> +#define __LIBFROG_ZONES_H__
> +
> +struct xfrog_zone_report {
> + struct blk_zone_report rep;
> + struct blk_zone zones[];
> +};
> +
> +struct xfrog_zone_report *
> +xfrog_report_zones(int fd, uint64_t sector, struct xfrog_zone_report *rep);
> +
> +#endif /* __LIBFROG_ZONES_H__ */
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index b5caa83a799d..b99febf2b15f 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -14,6 +14,7 @@
> #include "libfrog/crc32cselftest.h"
> #include "libfrog/dahashselftest.h"
> #include "libfrog/fsproperties.h"
> +#include "libfrog/zones.h"
> #include "proto.h"
> #include <ini.h>
>
> @@ -2541,9 +2542,6 @@ struct zone_topology {
> struct zone_info log;
> };
>
> -/* random size that allows efficient processing */
> -#define ZONES_PER_IOCTL 16384
> -
> static void
> zone_validate_capacity(
> struct zone_info *zi,
> @@ -2571,12 +2569,11 @@ report_zones(
> const char *name,
> struct zone_info *zi)
> {
> - struct blk_zone_report *rep;
> + struct xfrog_zone_report *rep = NULL;
> bool found_seq = false;
> - int fd, ret = 0;
> + int fd;
> uint64_t device_size;
> uint64_t sector = 0;
> - size_t rep_size;
> unsigned int i, n = 0;
> struct stat st;
>
> @@ -2603,32 +2600,18 @@ report_zones(
> zi->nr_zones = device_size / zi->zone_size;
> zi->nr_conv_zones = 0;
>
> - rep_size = sizeof(struct blk_zone_report) +
> - sizeof(struct blk_zone) * ZONES_PER_IOCTL;
> - rep = malloc(rep_size);
> - if (!rep) {
> - fprintf(stderr,
> -_("Failed to allocate memory for zone reporting.\n"));
> - exit(1);
> - }
> -
> while (n < zi->nr_zones) {
> - struct blk_zone *zones = (struct blk_zone *)(rep + 1);
> + struct blk_zone *zones;
>
> - memset(rep, 0, rep_size);
> - rep->sector = sector;
> - rep->nr_zones = ZONES_PER_IOCTL;
> -
> - ret = ioctl(fd, BLKREPORTZONE, rep);
> - if (ret) {
> - fprintf(stderr,
> -_("ioctl(BLKREPORTZONE) failed: %d!\n"), -errno);
> + rep = xfrog_report_zones(fd, sector, rep);
> + if (!rep)
> exit(1);
> - }
> - if (!rep->nr_zones)
> +
> + if (!rep->rep.nr_zones)
> break;
>
> - for (i = 0; i < rep->nr_zones; i++) {
> + zones = rep->zones;
> + for (i = 0; i < rep->rep.nr_zones; i++) {
> if (n >= zi->nr_zones)
> break;
>
> @@ -2675,8 +2658,8 @@ _("Unknown zone type (0x%x) found.\n"), zones[i].type);
>
> n++;
> }
> - sector = zones[rep->nr_zones - 1].start +
> - zones[rep->nr_zones - 1].len;
> + sector = zones[rep->rep.nr_zones - 1].start +
> + zones[rep->rep.nr_zones - 1].len;
> }
>
> free(rep);
> diff --git a/repair/zoned.c b/repair/zoned.c
> index 49cc43984883..07e676ac7fd3 100644
> --- a/repair/zoned.c
> +++ b/repair/zoned.c
> @@ -6,6 +6,7 @@
> #include "libxfs_priv.h"
> #include "libxfs.h"
> #include "xfs_zones.h"
> +#include "libfrog/zones.h"
> #include "err_protos.h"
> #include "zoned.h"
>
> @@ -50,8 +51,7 @@ check_zones(
> uint64_t sector = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rtstart);
> unsigned int zone_size, zone_capacity;
> uint64_t device_size;
> - size_t rep_size;
> - struct blk_zone_report *rep;
> + struct xfrog_zone_report *rep = NULL;
> unsigned int i, n = 0;
>
> if (ioctl(fd, BLKGETSIZE64, &device_size))
> @@ -66,31 +66,18 @@ check_zones(
> return;
> }
>
> - rep_size = sizeof(struct blk_zone_report) +
> - sizeof(struct blk_zone) * ZONES_PER_IOCTL;
> - rep = malloc(rep_size);
> - if (!rep) {
> - do_warn(_("malloc failed for zone report\n"));
> - return;
> - }
> -
> while (n < mp->m_sb.sb_rgcount) {
> - struct blk_zone *zones = (struct blk_zone *)(rep + 1);
> - int ret;
> + struct blk_zone *zones;
>
> - memset(rep, 0, rep_size);
> - rep->sector = sector;
> - rep->nr_zones = ZONES_PER_IOCTL;
> + rep = xfrog_report_zones(fd, sector, rep);
> + if (!rep)
> + return;
>
> - ret = ioctl(fd, BLKREPORTZONE, rep);
> - if (ret) {
> - do_error(_("ioctl(BLKREPORTZONE) failed: %d!\n"), ret);
> - goto out_free;
> - }
> - if (!rep->nr_zones)
> + if (!rep->rep.nr_zones)
> break;
>
> - for (i = 0; i < rep->nr_zones; i++) {
> + zones = rep->zones;
> + for (i = 0; i < rep->rep.nr_zones; i++) {
> if (n >= mp->m_sb.sb_rgcount)
> break;
>
> @@ -129,8 +116,8 @@ _("Inconsistent zone capacity!\n"));
> report_zones_cb(mp, &zones[i]);
> n++;
> }
> - sector = zones[rep->nr_zones - 1].start +
> - zones[rep->nr_zones - 1].len;
> + sector = zones[rep->rep.nr_zones - 1].start +
> + zones[rep->rep.nr_zones - 1].len;
> }
>
> out_free:
> --
> 2.47.3
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 5/5] libfrog: enable cached report zones
2026-01-28 4:32 ` [PATCH 5/5] libfrog: enable cached report zones Christoph Hellwig
@ 2026-01-28 5:10 ` Darrick J. Wong
0 siblings, 0 replies; 10+ messages in thread
From: Darrick J. Wong @ 2026-01-28 5:10 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Andrey Albershteyn, Damien Le Moal, Carlos Maiolino, linux-xfs
On Wed, Jan 28, 2026 at 05:32:59AM +0100, Christoph Hellwig wrote:
> Modify the function xfrog_report_zones() to default to always trying
> first a cached report zones using the BLKREPORTZONEV2 ioctl.
> If the kernel does not support BLKREPORTZONEV2, fall back to the
> (slower) regular report zones BLKREPORTZONE ioctl.
>
> TO enable this feature even if xfsprogs is compiled on a system where
> linux/blkzoned.h does not define BLKREPORTZONEV2, this ioctl is defined
> in libfrog/zones.h, together with the BLK_ZONE_REP_CACHED flag and the
> BLK_ZONE_COND_ACTIVE zone condition.
>
> Since a cached report zone always return the condition
> BLK_ZONE_COND_ACTIVE for any zone that is implicitly open, explicitly
> open or closed, the function xfs_zone_validate_seq() is modified to
> handle this new condition as being equivalent to the implicit open,
> explicit open or closed conditions.
>
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
> [hch: don't try cached reporting again if not supported]
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks fine to me, so
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> ---
> include/platform_defs.h | 6 ++++++
> libfrog/zones.c | 22 +++++++++++++++++++++-
> 2 files changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/include/platform_defs.h b/include/platform_defs.h
> index 1a9f401fc11c..09129e0f22dc 100644
> --- a/include/platform_defs.h
> +++ b/include/platform_defs.h
> @@ -312,6 +312,12 @@ struct kvec {
> * Local definitions for the new cached report zones added in Linux 6.19 in case
> * the system <linux/blkzoned.h> doesn't provide them yet.
> */
> +#ifndef BLKREPORTZONEV2
> +#define BLKREPORTZONEV2 _IOWR(0x12, 142, struct blk_zone_report)
> +#endif
> +#ifndef BLK_ZONE_REP_CACHED
> +#define BLK_ZONE_REP_CACHED (1U << 31)
> +#endif
> #ifndef BLK_ZONE_COND_ACTIVE
> #define BLK_ZONE_COND_ACTIVE 0xff
> #endif
> diff --git a/libfrog/zones.c b/libfrog/zones.c
> index 2276c56bec9c..c088d3240545 100644
> --- a/libfrog/zones.c
> +++ b/libfrog/zones.c
> @@ -3,12 +3,15 @@
> * Copyright (c) 2025, Western Digital Corporation or its affiliates.
> */
> #include "platform_defs.h"
> +#include "atomic.h"
> #include "libfrog/zones.h"
> #include <sys/ioctl.h>
>
> /* random size that allows efficient processing */
> #define ZONES_PER_REPORT 16384
>
> +static atomic_t cached_reporting_disabled;
> +
> struct xfrog_zone_report *
> xfrog_report_zones(
> int fd,
> @@ -24,10 +27,27 @@ _("Failed to allocate memory for reporting zones."));
> }
> }
>
> + /*
> + * Try cached report zones first. If this fails, fallback to the regular
> + * (slower) report zones.
> + */
> rep->rep.sector = sector;
> rep->rep.nr_zones = ZONES_PER_REPORT;
>
> - if (ioctl(fd, BLKREPORTZONE, &rep->rep)) {
> + if (atomic_read(&cached_reporting_disabled))
> + goto uncached;
> +
> + rep->rep.flags = BLK_ZONE_REP_CACHED;
> + if (ioctl(fd, BLKREPORTZONEV2, &rep->rep)) {
> + atomic_inc(&cached_reporting_disabled);
> + goto uncached;
> + }
> +
> + return rep;
> +
> +uncached:
> + rep->rep.flags = 0;
> + if (ioctl(fd, BLKREPORTZONE, rep)) {
> fprintf(stderr, "%s %s\n",
> _("ioctl(BLKREPORTZONE) failed:\n"),
> strerror(-errno));
> --
> 2.47.3
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/5] include blkzoned.h in platform_defs.h
2026-01-28 4:32 ` [PATCH 1/5] include blkzoned.h in platform_defs.h Christoph Hellwig
@ 2026-01-28 5:11 ` Darrick J. Wong
2026-01-28 5:58 ` Damien Le Moal
1 sibling, 0 replies; 10+ messages in thread
From: Darrick J. Wong @ 2026-01-28 5:11 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Andrey Albershteyn, Damien Le Moal, Carlos Maiolino, linux-xfs
On Wed, Jan 28, 2026 at 05:32:55AM +0100, Christoph Hellwig wrote:
> We'll need to conditionally add definitions added in later version of
> blkzoned.h soon. The right place for that is platform_defs.h, which
> means blkzoned.h needs to be included there for cpp trickery to work.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
I was /almost/ about to get cranky about including blkzoned.h
unconditionally but then I noticed that the header has been in
include/uapi/ since October 2016.
So I guess it won't cause any problems with a current distro release.
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
--D
> ---
> include/platform_defs.h | 1 +
> libxfs/xfs_zones.c | 1 -
> mdrestore/xfs_mdrestore.c | 1 -
> mkfs/xfs_mkfs.c | 1 -
> repair/zoned.c | 1 -
> 5 files changed, 1 insertion(+), 4 deletions(-)
>
> diff --git a/include/platform_defs.h b/include/platform_defs.h
> index da966490b0f5..1152f0622ccf 100644
> --- a/include/platform_defs.h
> +++ b/include/platform_defs.h
> @@ -24,6 +24,7 @@
> #include <stdbool.h>
> #include <libgen.h>
> #include <urcu.h>
> +#include <linux/blkzoned.h>
>
> /* long and pointer must be either 32 bit or 64 bit */
> #define BITS_PER_LONG (sizeof(long) * CHAR_BIT)
> diff --git a/libxfs/xfs_zones.c b/libxfs/xfs_zones.c
> index 7a81d83f5b3e..c1ad7075329c 100644
> --- a/libxfs/xfs_zones.c
> +++ b/libxfs/xfs_zones.c
> @@ -3,7 +3,6 @@
> * Copyright (c) 2023-2025 Christoph Hellwig.
> * Copyright (c) 2024-2025, Western Digital Corporation or its affiliates.
> */
> -#include <linux/blkzoned.h>
> #include "libxfs_priv.h"
> #include "xfs.h"
> #include "xfs_fs.h"
> diff --git a/mdrestore/xfs_mdrestore.c b/mdrestore/xfs_mdrestore.c
> index b6e8a6196a79..eece58977f97 100644
> --- a/mdrestore/xfs_mdrestore.c
> +++ b/mdrestore/xfs_mdrestore.c
> @@ -8,7 +8,6 @@
> #include "xfs_metadump.h"
> #include <libfrog/platform.h>
> #include "libfrog/div64.h"
> -#include <linux/blkzoned.h>
>
> union mdrestore_headers {
> __be32 magic;
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index b34407725f76..46f4faf4de5a 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -6,7 +6,6 @@
> #include "libfrog/util.h"
> #include "libxfs.h"
> #include <ctype.h>
> -#include <linux/blkzoned.h>
> #include "libxfs/xfs_zones.h"
> #include "xfs_multidisk.h"
> #include "libxcmd.h"
> diff --git a/repair/zoned.c b/repair/zoned.c
> index 206b0158f95f..49cc43984883 100644
> --- a/repair/zoned.c
> +++ b/repair/zoned.c
> @@ -3,7 +3,6 @@
> * Copyright (c) 2024 Christoph Hellwig.
> */
> #include <ctype.h>
> -#include <linux/blkzoned.h>
> #include "libxfs_priv.h"
> #include "libxfs.h"
> #include "xfs_zones.h"
> --
> 2.47.3
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/5] include blkzoned.h in platform_defs.h
2026-01-28 4:32 ` [PATCH 1/5] include blkzoned.h in platform_defs.h Christoph Hellwig
2026-01-28 5:11 ` Darrick J. Wong
@ 2026-01-28 5:58 ` Damien Le Moal
1 sibling, 0 replies; 10+ messages in thread
From: Damien Le Moal @ 2026-01-28 5:58 UTC (permalink / raw)
To: Christoph Hellwig, Andrey Albershteyn
Cc: Darrick J . Wong, Carlos Maiolino, linux-xfs
On 1/28/26 1:32 PM, Christoph Hellwig wrote:
> We'll need to conditionally add definitions added in later version of
> blkzoned.h soon. The right place for that is platform_defs.h, which
> means blkzoned.h needs to be included there for cpp trickery to work.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Thanks for fixing this.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
--
Damien Le Moal
Western Digital Research
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-01-28 6:03 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-28 4:32 enable cached zone report v5 Christoph Hellwig
2026-01-28 4:32 ` [PATCH 1/5] include blkzoned.h in platform_defs.h Christoph Hellwig
2026-01-28 5:11 ` Darrick J. Wong
2026-01-28 5:58 ` Damien Le Moal
2026-01-28 4:32 ` [PATCH 2/5] xfs: use blkdev_report_zones_cached() Christoph Hellwig
2026-01-28 4:32 ` [PATCH 3/5] mkfs: remove unnecessary return value affectation Christoph Hellwig
2026-01-28 4:32 ` [PATCH 4/5] libfrog: lift common zone reporting code from mkfs and repair Christoph Hellwig
2026-01-28 5:09 ` Darrick J. Wong
2026-01-28 4:32 ` [PATCH 5/5] libfrog: enable cached report zones Christoph Hellwig
2026-01-28 5:10 ` Darrick J. Wong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox