From: Damien Le Moal Date: Wed, 28 Jan 2026 04:32:58 +0000 (+0100) Subject: libfrog: lift common zone reporting code from mkfs and repair X-Git-Tag: v6.19.0~22 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e2a429986eb9c2d19d9d07a027a9fabe7171bb7f;p=xfsprogs-dev.git libfrog: lift common zone reporting code from mkfs and repair 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 [hch: refactored to allow buffer reuse] Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong --- diff --git a/libfrog/Makefile b/libfrog/Makefile index 268fa266..9f405ffe 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 00000000..2276c56b --- /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 + +/* 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 00000000..3592d489 --- /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 2230e82a..a1199402 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 @@ -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 49cc4398..07e676ac 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: