]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: use blkdev_get_zone_info to simplify zone reporting
authorChristoph Hellwig <hch@lst.de>
Wed, 14 Jan 2026 06:53:29 +0000 (07:53 +0100)
committerCarlos Maiolino <cem@kernel.org>
Wed, 21 Jan 2026 11:57:17 +0000 (12:57 +0100)
Unwind the callback based programming model by querying the cached
zone information using blkdev_get_zone_info.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
fs/xfs/xfs_zone_alloc.c

index d127f122d6cf25922a0b677c085cde879da86af7..89d3a5c878ee3b5f1640fda22108908f30b6c466 100644 (file)
@@ -976,7 +976,6 @@ xfs_free_open_zones(
 }
 
 struct xfs_init_zones {
-       struct xfs_mount        *mp;
        uint32_t                zone_size;
        uint32_t                zone_capacity;
        uint64_t                available;
@@ -994,19 +993,52 @@ struct xfs_init_zones {
  * the most recently written ones got deleted again before unmount, but this is
  * the best we can do without hardware support.
  */
-static xfs_rgblock_t
-xfs_rmap_estimate_write_pointer(
-       struct xfs_rtgroup      *rtg)
+static int
+xfs_query_write_pointer(
+       struct xfs_init_zones   *iz,
+       struct xfs_rtgroup      *rtg,
+       xfs_rgblock_t           *write_pointer)
 {
+       struct xfs_mount        *mp = rtg_mount(rtg);
+       struct block_device     *bdev = mp->m_rtdev_targp->bt_bdev;
+       sector_t                start = xfs_gbno_to_daddr(&rtg->rtg_group, 0);
        xfs_rgblock_t           highest_rgbno;
+       struct blk_zone         zone = {};
+       int                     error;
+
+       if (bdev_is_zoned(bdev)) {
+               error = blkdev_get_zone_info(bdev, start, &zone);
+               if (error)
+                       return error;
+               if (zone.start != start) {
+                       xfs_warn(mp, "mismatched zone start: 0x%llx/0x%llx.",
+                               zone.start, start);
+                       return -EFSCORRUPTED;
+               }
+
+               if (!xfs_validate_blk_zone(mp, &zone, rtg_rgno(rtg),
+                               iz->zone_size, iz->zone_capacity,
+                               write_pointer))
+                       return -EFSCORRUPTED;
+
+               /*
+                * Use the hardware write pointer returned by
+                * xfs_validate_blk_zone for sequential write required zones,
+                * else fall through to the rmap-based estimation below.
+                */
+               if (zone.cond != BLK_ZONE_COND_NOT_WP)
+                       return 0;
+       }
 
        xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
        highest_rgbno = xfs_rtrmap_highest_rgbno(rtg);
        xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_RMAP);
 
        if (highest_rgbno == NULLRGBLOCK)
-               return 0;
-       return highest_rgbno + 1;
+               *write_pointer = 0;
+       else
+               *write_pointer = highest_rgbno + 1;
+       return 0;
 }
 
 static int
@@ -1084,43 +1116,6 @@ xfs_init_zone(
        return 0;
 }
 
-static int
-xfs_get_zone_info_cb(
-       struct blk_zone         *zone,
-       unsigned int            idx,
-       void                    *data)
-{
-       struct xfs_init_zones   *iz = data;
-       struct xfs_mount        *mp = iz->mp;
-       xfs_fsblock_t           zsbno = xfs_daddr_to_rtb(mp, zone->start);
-       xfs_rgnumber_t          rgno;
-       xfs_rgblock_t           write_pointer;
-       struct xfs_rtgroup      *rtg;
-       int                     error;
-
-       if (xfs_rtb_to_rgbno(mp, zsbno) != 0) {
-               xfs_warn(mp, "mismatched zone start 0x%llx.", zsbno);
-               return -EFSCORRUPTED;
-       }
-
-       rgno = xfs_rtb_to_rgno(mp, zsbno);
-       rtg = xfs_rtgroup_grab(mp, rgno);
-       if (!rtg) {
-               xfs_warn(mp, "realtime group not found for zone %u.", rgno);
-               return -EFSCORRUPTED;
-       }
-       if (!xfs_validate_blk_zone(mp, zone, idx, iz->zone_size,
-                       iz->zone_capacity, &write_pointer)) {
-               xfs_rtgroup_rele(rtg);
-               return -EFSCORRUPTED;
-       }
-       if (zone->cond == BLK_ZONE_COND_NOT_WP)
-               write_pointer = xfs_rmap_estimate_write_pointer(rtg);
-       error = xfs_init_zone(iz, rtg, write_pointer);
-       xfs_rtgroup_rele(rtg);
-       return error;
-}
-
 /*
  * Calculate the max open zone limit based on the of number of backing zones
  * available.
@@ -1255,15 +1250,13 @@ xfs_mount_zones(
        struct xfs_mount        *mp)
 {
        struct xfs_init_zones   iz = {
-               .mp             = mp,
                .zone_capacity  = mp->m_groups[XG_TYPE_RTG].blocks,
                .zone_size      = xfs_rtgroup_raw_size(mp),
        };
-       struct xfs_buftarg      *bt = mp->m_rtdev_targp;
-       xfs_extlen_t            zone_blocks = mp->m_groups[XG_TYPE_RTG].blocks;
+       struct xfs_rtgroup      *rtg = NULL;
        int                     error;
 
-       if (!bt) {
+       if (!mp->m_rtdev_targp) {
                xfs_notice(mp, "RT device missing.");
                return -EINVAL;
        }
@@ -1291,7 +1284,7 @@ xfs_mount_zones(
                return -ENOMEM;
 
        xfs_info(mp, "%u zones of %u blocks (%u max open zones)",
-                mp->m_sb.sb_rgcount, zone_blocks, mp->m_max_open_zones);
+                mp->m_sb.sb_rgcount, iz.zone_capacity, mp->m_max_open_zones);
        trace_xfs_zones_mount(mp);
 
        /*
@@ -1315,25 +1308,18 @@ xfs_mount_zones(
         * or beneficial.
         */
        mp->m_super->s_min_writeback_pages =
-               XFS_FSB_TO_B(mp, min(zone_blocks, XFS_MAX_BMBT_EXTLEN)) >>
+               XFS_FSB_TO_B(mp, min(iz.zone_capacity, XFS_MAX_BMBT_EXTLEN)) >>
                        PAGE_SHIFT;
 
-       if (bdev_is_zoned(bt->bt_bdev)) {
-               error = blkdev_report_zones_cached(bt->bt_bdev,
-                               XFS_FSB_TO_BB(mp, mp->m_sb.sb_rtstart),
-                               mp->m_sb.sb_rgcount, xfs_get_zone_info_cb, &iz);
-               if (error < 0)
+       while ((rtg = xfs_rtgroup_next(mp, rtg))) {
+               xfs_rgblock_t           write_pointer;
+
+               error = xfs_query_write_pointer(&iz, rtg, &write_pointer);
+               if (!error)
+                       error = xfs_init_zone(&iz, rtg, write_pointer);
+               if (error) {
+                       xfs_rtgroup_rele(rtg);
                        goto out_free_zone_info;
-       } else {
-               struct xfs_rtgroup      *rtg = NULL;
-
-               while ((rtg = xfs_rtgroup_next(mp, rtg))) {
-                       error = xfs_init_zone(&iz, rtg,
-                                       xfs_rmap_estimate_write_pointer(rtg));
-                       if (error) {
-                               xfs_rtgroup_rele(rtg);
-                               goto out_free_zone_info;
-                       }
                }
        }