]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: support zone gaps
authorChristoph Hellwig <hch@lst.de>
Sat, 21 Dec 2024 09:58:24 +0000 (09:58 +0000)
committerChristoph Hellwig <hch@lst.de>
Mon, 3 Feb 2025 04:49:15 +0000 (05:49 +0100)
Zoned devices can have gaps beyond the usable capacity of a zone and the
end in the LBA/daddr address space.  In other words, the hardware
equivalent to the RT groups already takes care of the power of 2
alignment for us.  In this case the sparse FSB/RTB address space maps 1:1
to the device address space.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
fs/xfs/libxfs/xfs_format.h
fs/xfs/libxfs/xfs_group.h
fs/xfs/libxfs/xfs_rtgroup.h
fs/xfs/libxfs/xfs_sb.c
fs/xfs/libxfs/xfs_zones.c
fs/xfs/xfs_mount.h

index c99f94c481d28ea2b1a8d2f2c08db58c9dcde521..036b7951c069765a1b45311176eab615cd8daaca 100644 (file)
@@ -398,6 +398,7 @@ xfs_sb_has_ro_compat_feature(
 #define XFS_SB_FEAT_INCOMPAT_PARENT    (1 << 7)  /* parent pointers */
 #define XFS_SB_FEAT_INCOMPAT_METADIR   (1 << 8)  /* metadata dir tree */
 #define XFS_SB_FEAT_INCOMPAT_ZONED     (1 << 9)  /* zoned RT allocator */
+#define XFS_SB_FEAT_INCOMPAT_ZONE_GAPS (1 << 10) /* RTGs have LBA gaps */
 
 #define XFS_SB_FEAT_INCOMPAT_ALL \
                (XFS_SB_FEAT_INCOMPAT_FTYPE | \
@@ -409,7 +410,8 @@ xfs_sb_has_ro_compat_feature(
                 XFS_SB_FEAT_INCOMPAT_EXCHRANGE | \
                 XFS_SB_FEAT_INCOMPAT_PARENT | \
                 XFS_SB_FEAT_INCOMPAT_METADIR | \
-                XFS_SB_FEAT_INCOMPAT_ZONED)
+                XFS_SB_FEAT_INCOMPAT_ZONED | \
+                XFS_SB_FEAT_INCOMPAT_ZONE_GAPS)
 
 #define XFS_SB_FEAT_INCOMPAT_UNKNOWN   ~XFS_SB_FEAT_INCOMPAT_ALL
 static inline bool
index cff3f815947bfca1a49cb1116621f1770393018f..4423932a23130010e82f8596247b2a17f47f0d89 100644 (file)
@@ -123,7 +123,11 @@ xfs_gbno_to_daddr(
        struct xfs_groups       *g = &mp->m_groups[xg->xg_type];
        xfs_fsblock_t           fsbno;
 
-       fsbno = (xfs_fsblock_t)xg->xg_gno * g->blocks + gbno;
+       if (g->has_daddr_gaps)
+               fsbno = xfs_gbno_to_fsb(xg, gbno);
+       else
+               fsbno = (xfs_fsblock_t)xg->xg_gno * g->blocks + gbno;
+
        return XFS_FSB_TO_BB(mp, g->start_fsb + fsbno);
 }
 
index b325aff28264d5066517a322ec9e20f33656e3df..d36a6ae0abe57fafc67048fd7546f61e068caf20 100644 (file)
@@ -245,11 +245,14 @@ xfs_rtb_to_daddr(
        xfs_rtblock_t           rtbno)
 {
        struct xfs_groups       *g = &mp->m_groups[XG_TYPE_RTG];
-       xfs_rgnumber_t          rgno = xfs_rtb_to_rgno(mp, rtbno);
-       uint64_t                start_bno = (xfs_rtblock_t)rgno * g->blocks;
 
-       return XFS_FSB_TO_BB(mp,
-               g->start_fsb + start_bno + (rtbno & g->blkmask));
+       if (xfs_has_rtgroups(mp) && !g->has_daddr_gaps) {
+               xfs_rgnumber_t  rgno = xfs_rtb_to_rgno(mp, rtbno);
+
+               rtbno = (xfs_rtblock_t)rgno * g->blocks + (rtbno & g->blkmask);
+       }
+
+       return XFS_FSB_TO_BB(mp, g->start_fsb + rtbno);
 }
 
 static inline xfs_rtblock_t
@@ -261,7 +264,7 @@ xfs_daddr_to_rtb(
        xfs_rfsblock_t          bno;
 
        bno = XFS_BB_TO_FSBT(mp, daddr) - g->start_fsb;
-       if (xfs_has_rtgroups(mp)) {
+       if (xfs_has_rtgroups(mp) && !g->has_daddr_gaps) {
                xfs_rgnumber_t  rgno;
                uint32_t        rgbno;
 
index 64a9e88cb8ec0d20a7b8bb208bb981d8972d5677..e1f90809c17e11bb0f78bb2f1f57b20152739a17 100644 (file)
@@ -1205,6 +1205,9 @@ xfs_sb_mount_rextsize(
                rgs->blklog = mp->m_sb.sb_rgblklog;
                rgs->blkmask = xfs_mask32lo(mp->m_sb.sb_rgblklog);
                rgs->start_fsb = mp->m_sb.sb_rtstart;
+               if (xfs_sb_has_incompat_feature(sbp,
+                               XFS_SB_FEAT_INCOMPAT_ZONE_GAPS))
+                       rgs->has_daddr_gaps = true;
        } else {
                rgs->blocks = 0;
                rgs->blklog = 0;
index b022ed960eacda786f5cf3c15d0b6231c6554414..b0791a71931c9317ab399f787ccadacaa958e314 100644 (file)
@@ -137,6 +137,7 @@ xfs_zone_validate(
 {
        struct xfs_mount        *mp = rtg_mount(rtg);
        struct xfs_groups       *g = &mp->m_groups[XG_TYPE_RTG];
+       uint32_t                expected_size;
 
        /*
         * Check that the zone capacity matches the rtgroup size stored in the
@@ -151,11 +152,25 @@ xfs_zone_validate(
                return false;
        }
 
-       if (XFS_BB_TO_FSB(mp, zone->len) != 1 << g->blklog) {
+       if (g->has_daddr_gaps) {
+               expected_size = 1 << g->blklog;
+       } else {
+               if (zone->len != zone->capacity) {
+                       xfs_warn(mp,
+"zone %u has capacity != size ((0x%llx vs 0x%llx)",
+                               rtg_rgno(rtg),
+                               XFS_BB_TO_FSB(mp, zone->len),
+                               XFS_BB_TO_FSB(mp, zone->capacity));
+                       return false;
+               }
+               expected_size = g->blocks;
+       }
+
+       if (XFS_BB_TO_FSB(mp, zone->len) != expected_size) {
                xfs_warn(mp,
 "zone %u length (0x%llx) does match geometry (0x%x).",
                        rtg_rgno(rtg), XFS_BB_TO_FSB(mp, zone->len),
-                       1 << g->blklog);
+                       expected_size);
        }
 
        switch (zone->type) {
index 2c277f3c367ce1ad04c657b70518fa05cfad0848..6c5757f6e4efcdc8cee366a0b116240cf1359097 100644 (file)
@@ -97,6 +97,15 @@ struct xfs_groups {
         */
        uint8_t                 blklog;
 
+       /*
+        * Zoned devices can have gaps beyond the usable capacity of a zone and
+        * the end in the LBA/daddr address space.  In other words, the hardware
+        * equivalent to the RT groups already takes care of the power of 2
+        * alignment for us.  In this case the sparse FSB/RTB address space maps
+        * 1:1 to the device address space.
+        */
+       bool                    has_daddr_gaps;
+
        /*
         * Mask to extract the group-relative block number from a FSB.
         * For a pre-rtgroups filesystem we pretend to have one very large