xfs: use a single inode fork format for metadata btree inodes
authorChristoph Hellwig <hch@lst.de>
Tue, 12 Nov 2024 09:06:25 +0000 (10:06 +0100)
committerChristoph Hellwig <hch@lst.de>
Tue, 12 Nov 2024 09:06:25 +0000 (10:06 +0100)
Source kernel commit: b6e4506f219333c1012b8e4a69cc8cc2e3c59783

And instead switch based on the metatype for the detailed btree format.

This could probably be done even nicer by sharing the same btree root
structure.

Signed-off-by: Christoph Hellwig <hch@lst.de>
libxfs/xfs_format.h
libxfs/xfs_inode_buf.c
libxfs/xfs_inode_fork.c
libxfs/xfs_rtgroup.c
libxfs/xfs_rtrefcount_btree.c
libxfs/xfs_rtrmap_btree.c

index 707d961130372bae5a5253b9a826382978d09d39..b1007fb661ba73822ea39b801937eb9823f1cf40 100644 (file)
@@ -1002,8 +1002,7 @@ enum xfs_dinode_fmt {
        XFS_DINODE_FMT_EXTENTS,         /* struct xfs_bmbt_rec */
        XFS_DINODE_FMT_BTREE,           /* struct xfs_bmdr_block */
        XFS_DINODE_FMT_UUID,            /* added long ago, but never used */
-       XFS_DINODE_FMT_RMAP,            /* reverse mapping btree */
-       XFS_DINODE_FMT_REFCOUNT,        /* reference count btree */
+       XFS_DINODE_FMT_META_BTREE,      /* metadata btree */
 };
 
 #define XFS_INODE_FORMAT_STR \
@@ -1012,8 +1011,7 @@ enum xfs_dinode_fmt {
        { XFS_DINODE_FMT_EXTENTS,       "extent" }, \
        { XFS_DINODE_FMT_BTREE,         "btree" }, \
        { XFS_DINODE_FMT_UUID,          "uuid" }, \
-       { XFS_DINODE_FMT_RMAP,          "rmap" }, \
-       { XFS_DINODE_FMT_REFCOUNT,      "refcount" }
+       { XFS_DINODE_FMT_META_BTREE,    "meta_btree" }
 
 /*
  * Max values for extnum and aextnum.
index b5b28dbf4e82280f8d553462a7c29270a0f708d6..969888cecc6773ce0f836be4b6f29690711ee1e6 100644 (file)
@@ -438,20 +438,11 @@ xfs_dinode_verify_fork(
                if (di_nextents > max_extents)
                        return __this_address;
                break;
-       case XFS_DINODE_FMT_RMAP:
+       case XFS_DINODE_FMT_META_BTREE:
                /*
-                * growfs must create the rtrmap inodes before adding a
-                * realtime volume to the filesystem, so we cannot use the
-                * rtrmapbt predicate here.
+                * XXX: do we need a finer grained check here?
                 */
-               if (!xfs_has_rmapbt(mp))
-                       return __this_address;
-               if (!(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADATA)))
-                       return __this_address;
-               break;
-       case XFS_DINODE_FMT_REFCOUNT:
-               /* same comment about growfs and rmap inodes applies here */
-               if (!xfs_has_reflink(mp))
+               if (!xfs_has_metadir(mp))
                        return __this_address;
                if (!(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADATA)))
                        return __this_address;
@@ -475,9 +466,8 @@ xfs_dinode_verify_forkoff(
                if (dip->di_forkoff != (roundup(sizeof(xfs_dev_t), 8) >> 3))
                        return __this_address;
                break;
-       case XFS_DINODE_FMT_RMAP:
-       case XFS_DINODE_FMT_REFCOUNT:
-               if (!(xfs_has_metadir(mp) && xfs_has_parent(mp)))
+       case XFS_DINODE_FMT_META_BTREE:
+               if (!xfs_has_metadir(mp) || !xfs_has_parent(mp))
                        return __this_address;
                fallthrough;
        case XFS_DINODE_FMT_LOCAL:      /* fall through ... */
@@ -762,18 +752,10 @@ xfs_dinode_verify(
        }
 
        /* metadata inodes containing btrees always have zero extent count */
-       if (flags2 & XFS_DIFLAG2_METADATA) {
-               switch (XFS_DFORK_FORMAT(dip, XFS_DATA_FORK)) {
-               case XFS_DINODE_FMT_RMAP:
-               case XFS_DINODE_FMT_REFCOUNT:
-                       break;
-               default:
-                       if (nextents + naextents == 0 && nblocks != 0)
-                               return __this_address;
-                       break;
-               }
-       } else if (nextents + naextents == 0 && nblocks != 0)
-               return __this_address;
+       if (XFS_DFORK_FORMAT(dip, XFS_DATA_FORK) != XFS_DINODE_FMT_META_BTREE) {
+               if (nextents + naextents == 0 && nblocks != 0)
+                       return __this_address;
+       }
 
        return NULL;
 }
index 6fa49ab145a93c079fc69419ab6a48522c634810..d71f39c5fe736e0deb17978180c8c2115926d449 100644 (file)
@@ -268,24 +268,16 @@ xfs_iformat_data_fork(
                        return xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
                case XFS_DINODE_FMT_BTREE:
                        return xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
-               case XFS_DINODE_FMT_RMAP:
-                       /*
-                        * growfs must create the rtrmap inodes before adding a
-                        * realtime volume to the filesystem, so we cannot use
-                        * the rtrmapbt predicate here.
-                        */
-                       if (!xfs_has_rmapbt(ip->i_mount)) {
-                               xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
-                               return -EFSCORRUPTED;
-                       }
-                       return xfs_iformat_rtrmap(ip, dip);
-               case XFS_DINODE_FMT_REFCOUNT:
-                       /* same comment about growfs and rmap inodes applies */
-                       if (!xfs_has_reflink(ip->i_mount)) {
-                               xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
-                               return -EFSCORRUPTED;
+               case XFS_DINODE_FMT_META_BTREE:
+                       switch (ip->i_metatype) {
+                       case XFS_METAFILE_RTRMAP:
+                               return xfs_iformat_rtrmap(ip, dip);
+                       case XFS_METAFILE_RTREFCOUNT:
+                               return xfs_iformat_rtrefcount(ip, dip);
+                       default:
+                               break;
                        }
-                       return xfs_iformat_rtrefcount(ip, dip);
+                       fallthrough;
                default:
                        xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
                                        dip, sizeof(*dip), __this_address);
@@ -605,16 +597,22 @@ xfs_iflush_fork(
                }
                break;
 
-       case XFS_DINODE_FMT_RMAP:
+       case XFS_DINODE_FMT_META_BTREE:
                ASSERT(whichfork == XFS_DATA_FORK);
-               if (iip->ili_fields & brootflag[whichfork])
-                       xfs_iflush_rtrmap(ip, dip);
-               break;
 
-       case XFS_DINODE_FMT_REFCOUNT:
-               ASSERT(whichfork == XFS_DATA_FORK);
-               if (iip->ili_fields & brootflag[whichfork])
+               if (!(iip->ili_fields & brootflag[whichfork]))
+                       break;
+
+               switch (ip->i_metatype) {
+               case XFS_METAFILE_RTRMAP:
+                       xfs_iflush_rtrmap(ip, dip);
+                       break;
+               case XFS_METAFILE_RTREFCOUNT:
                        xfs_iflush_rtrefcount(ip, dip);
+                       break;
+               default:
+                       ASSERT(0);
+               }
                break;
 
        default:
index d5e035f673f456cb03570c95aa31905d9f87c217..59081e3bb14774f8f6f093d138d99511159458b3 100644 (file)
@@ -308,17 +308,8 @@ xfs_rtginode_ilock_print_fn(
        const struct xfs_inode *ip =
                container_of(m, struct xfs_inode, i_lock.dep_map);
 
-       switch (ip->i_df.if_format) {
-       case XFS_DINODE_FMT_RMAP:
-               printk(KERN_CONT " rgno=%u rmapbt", ip->i_projid);
-               break;
-       case XFS_DINODE_FMT_REFCOUNT:
-               printk(KERN_CONT " rgno=%u refcountbt", ip->i_projid);
-               break;
-       default:
-               printk(KERN_CONT " rgno=%u", ip->i_projid);
-               break;
-       }
+       /* XXX: pretty print metatype */
+       printk(KERN_CONT " rgno=%u metatype %u", ip->i_projid, ip->i_metatype);
 }
 
 /*
@@ -383,7 +374,7 @@ static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTGI_MAX] = {
                .name           = "rmap",
                .metafile_type  = XFS_METAFILE_RTRMAP,
                .sick           = XFS_SICK_RG_RMAPBT,
-               .fmt_mask       = 1U << XFS_DINODE_FMT_RMAP,
+               .fmt_mask       = 1U << XFS_DINODE_FMT_META_BTREE,
                /*
                 * growfs must create the rtrmap inodes before adding a
                 * realtime volume to the filesystem, so we cannot use the
@@ -396,7 +387,7 @@ static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTGI_MAX] = {
                .name           = "refcount",
                .metafile_type  = XFS_METAFILE_RTREFCOUNT,
                .sick           = XFS_SICK_RG_REFCNTBT,
-               .fmt_mask       = 1U << XFS_DINODE_FMT_REFCOUNT,
+               .fmt_mask       = 1U << XFS_DINODE_FMT_META_BTREE,
                /* same comment about growfs and rmap inodes applies here */
                .enabled        = xfs_has_reflink,
                .create         = xfs_rtrefcountbt_create,
index 69fdb78d52b60104168ab2ae772f47b596c4f5ce..edffd0e3d88327a5d507cc286664e2df506698ff 100644 (file)
@@ -436,7 +436,7 @@ xfs_rtrefcountbt_commit_staged_btree(
        int                     flags = XFS_ILOG_CORE | XFS_ILOG_DBROOT;
 
        ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
-       ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_REFCOUNT);
+       ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_META_BTREE);
 
        /*
         * Free any resources hanging off the real fork, then shallow-copy the
@@ -638,6 +638,11 @@ xfs_iformat_rtrefcount(
        unsigned int            level;
        int                     dsize;
 
+       if (!xfs_has_reflink(mp)) {
+               xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
+               return -EFSCORRUPTED;
+       }
+
        dsize = XFS_DFORK_SIZE(dip, mp, XFS_DATA_FORK);
        numrecs = be16_to_cpu(dfp->bb_numrecs);
        level = be16_to_cpu(dfp->bb_level);
@@ -733,7 +738,7 @@ xfs_rtrefcountbt_create(
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_btree_block  *broot;
 
-       ifp->if_format = XFS_DINODE_FMT_REFCOUNT;
+       ifp->if_format = XFS_DINODE_FMT_META_BTREE;
        ASSERT(ifp->if_broot_bytes == 0);
        ASSERT(ifp->if_bytes == 0);
 
index 87f3b1a0cfda5371e9f681898f6c2180f0600d40..86d4c0dc2d7cfde83b4b67a6a1c68e2cf49a167a 100644 (file)
@@ -675,7 +675,7 @@ xfs_rtrmapbt_commit_staged_btree(
        int                     flags = XFS_ILOG_CORE | XFS_ILOG_DBROOT;
 
        ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
-       ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_RMAP);
+       ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_META_BTREE);
 
        /*
         * Free any resources hanging off the real fork, then shallow-copy the
@@ -896,6 +896,11 @@ xfs_iformat_rtrmap(
        unsigned int            level;
        int                     dsize;
 
+       if (!xfs_has_rmapbt(mp)) {
+               xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
+               return -EFSCORRUPTED;
+       }
+
        dsize = XFS_DFORK_SIZE(dip, mp, XFS_DATA_FORK);
        numrecs = be16_to_cpu(dfp->bb_numrecs);
        level = be16_to_cpu(dfp->bb_level);
@@ -987,7 +992,7 @@ xfs_rtrmapbt_create(
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_btree_block  *broot;
 
-       ifp->if_format = XFS_DINODE_FMT_RMAP;
+       ifp->if_format = XFS_DINODE_FMT_META_BTREE;
        ASSERT(ifp->if_broot_bytes == 0);
        ASSERT(ifp->if_bytes == 0);