xfs: reflect sb features in xfs_mount
authorDave Chinner <dchinner@redhat.com>
Thu, 19 Aug 2021 01:46:26 +0000 (18:46 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 19 Aug 2021 17:07:12 +0000 (10:07 -0700)
Currently on-disk feature checks require decoding the superblock
fileds and so can be non-trivial. We have almost 400 hundred
individual feature checks in the XFS code, so this is a significant
amount of code. To reduce runtime check overhead, pre-process all
the version flags into a features field in the xfs_mount at mount
time so we can convert all the feature checks to a simple flag
check.

There is also a need to convert the dynamic feature flags to update
the m_features field. This is required for attr, attr2 and quota
features. New xfs_mount based wrappers are added for this.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/libxfs/xfs_format.h
fs/xfs/libxfs/xfs_sb.c
fs/xfs/libxfs/xfs_sb.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_rtalloc.c

index ac739e6..fdd3520 100644 (file)
@@ -405,7 +405,7 @@ static inline bool xfs_sb_version_hasprojid32bit(struct xfs_sb *sbp)
                (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT));
 }
 
-static inline void xfs_sb_version_addprojid32bit(struct xfs_sb *sbp)
+static inline void xfs_sb_version_addprojid32(struct xfs_sb *sbp)
 {
        sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
        sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT;
index 4a4586b..f9af5f1 100644 (file)
  * Physical superblock buffer manipulations. Shared with libxfs in userspace.
  */
 
+uint64_t
+xfs_sb_version_to_features(
+       struct xfs_sb   *sbp)
+{
+       uint64_t        features = 0;
+
+       /* optional V4 features */
+       if (sbp->sb_rblocks > 0)
+               features |= XFS_FEAT_REALTIME;
+       if (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT)
+               features |= XFS_FEAT_ATTR;
+       if (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT)
+               features |= XFS_FEAT_QUOTA;
+       if (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT)
+               features |= XFS_FEAT_ALIGN;
+       if (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT)
+               features |= XFS_FEAT_LOGV2;
+       if (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT)
+               features |= XFS_FEAT_DALIGN;
+       if (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT)
+               features |= XFS_FEAT_EXTFLG;
+       if (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT)
+               features |= XFS_FEAT_SECTOR;
+       if (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT)
+               features |= XFS_FEAT_ASCIICI;
+       if (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) {
+               if (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT)
+                       features |= XFS_FEAT_LAZYSBCOUNT;
+               if (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT)
+                       features |= XFS_FEAT_ATTR2;
+               if (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT)
+                       features |= XFS_FEAT_PROJID32;
+               if (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE)
+                       features |= XFS_FEAT_FTYPE;
+       }
+
+       if (XFS_SB_VERSION_NUM(sbp) != XFS_SB_VERSION_5)
+               return features;
+
+       /* Always on V5 features */
+       features |= XFS_FEAT_ALIGN | XFS_FEAT_LOGV2 | XFS_FEAT_EXTFLG |
+                   XFS_FEAT_LAZYSBCOUNT | XFS_FEAT_ATTR2 | XFS_FEAT_PROJID32 |
+                   XFS_FEAT_V3INODES | XFS_FEAT_CRC | XFS_FEAT_PQUOTINO;
+
+       /* Optional V5 features */
+       if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT)
+               features |= XFS_FEAT_FINOBT;
+       if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT)
+               features |= XFS_FEAT_RMAPBT;
+       if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK)
+               features |= XFS_FEAT_REFLINK;
+       if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT)
+               features |= XFS_FEAT_INOBTCNT;
+       if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_FTYPE)
+               features |= XFS_FEAT_FTYPE;
+       if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_SPINODES)
+               features |= XFS_FEAT_SPINODES;
+       if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID)
+               features |= XFS_FEAT_META_UUID;
+       if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_BIGTIME)
+               features |= XFS_FEAT_BIGTIME;
+       if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR)
+               features |= XFS_FEAT_NEEDSREPAIR;
+       return features;
+}
+
 /* Check all the superblock fields we care about when reading one in. */
 STATIC int
 xfs_validate_sb_read(
index 0c1602d..d2dd99c 100644 (file)
@@ -20,6 +20,7 @@ extern void   xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp);
 extern void    xfs_sb_from_disk(struct xfs_sb *to, struct xfs_dsb *from);
 extern void    xfs_sb_to_disk(struct xfs_dsb *to, struct xfs_sb *from);
 extern void    xfs_sb_quota_from_disk(struct xfs_sb *sbp);
+extern uint64_t        xfs_sb_version_to_features(struct xfs_sb *sbp);
 
 extern int     xfs_update_secondary_sbs(struct xfs_mount *mp);
 
index 71dd1bb..bcab5c6 100644 (file)
@@ -3348,6 +3348,7 @@ xlog_do_recover(
        xfs_buf_relse(bp);
 
        /* re-initialise in-core superblock and geometry structures */
+       mp->m_features |= xfs_sb_version_to_features(sbp);
        xfs_reinit_percpu_counters(mp);
        error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
        if (error) {
index 66dbc91..ff53b3f 100644 (file)
@@ -225,6 +225,7 @@ reread:
                goto reread;
        }
 
+       mp->m_features |= xfs_sb_version_to_features(sbp);
        xfs_reinit_percpu_counters(mp);
 
        /* no need to be quiet anymore, so reset the buf ops */
index 57f2ea3..3b5428b 100644 (file)
@@ -147,6 +147,7 @@ typedef struct xfs_mount {
        int                     m_fixedfsid[2]; /* unchanged for life of FS */
        uint                    m_qflags;       /* quota status flags */
        uint64_t                m_flags;        /* global mount flags */
+       uint64_t                m_features;     /* active filesystem features */
        uint64_t                m_low_space[XFS_LOWSP_MAX];
        uint64_t                m_low_rtexts[XFS_LOWSP_MAX];
        struct xfs_ino_geometry m_ino_geo;      /* inode geometry */
@@ -243,6 +244,81 @@ typedef struct xfs_mount {
 
 #define M_IGEO(mp)             (&(mp)->m_ino_geo)
 
+/*
+ * Flags for m_features.
+ *
+ * These are all the active features in the filesystem, regardless of how
+ * they are configured.
+ */
+#define XFS_FEAT_ATTR          (1ULL << 0)     /* xattrs present in fs */
+#define XFS_FEAT_NLINK         (1ULL << 1)     /* 32 bit link counts */
+#define XFS_FEAT_QUOTA         (1ULL << 2)     /* quota active */
+#define XFS_FEAT_ALIGN         (1ULL << 3)     /* inode alignment */
+#define XFS_FEAT_DALIGN                (1ULL << 4)     /* data alignment */
+#define XFS_FEAT_LOGV2         (1ULL << 5)     /* version 2 logs */
+#define XFS_FEAT_SECTOR                (1ULL << 6)     /* sector size > 512 bytes */
+#define XFS_FEAT_EXTFLG                (1ULL << 7)     /* unwritten extents */
+#define XFS_FEAT_ASCIICI       (1ULL << 8)     /* ASCII only case-insens. */
+#define XFS_FEAT_LAZYSBCOUNT   (1ULL << 9)     /* Superblk counters */
+#define XFS_FEAT_ATTR2         (1ULL << 10)    /* dynamic attr fork */
+#define XFS_FEAT_PARENT                (1ULL << 11)    /* parent pointers */
+#define XFS_FEAT_PROJID32      (1ULL << 12)    /* 32 bit project id */
+#define XFS_FEAT_CRC           (1ULL << 13)    /* metadata CRCs */
+#define XFS_FEAT_V3INODES      (1ULL << 14)    /* Version 3 inodes */
+#define XFS_FEAT_PQUOTINO      (1ULL << 15)    /* non-shared proj/grp quotas */
+#define XFS_FEAT_FTYPE         (1ULL << 16)    /* inode type in dir */
+#define XFS_FEAT_FINOBT                (1ULL << 17)    /* free inode btree */
+#define XFS_FEAT_RMAPBT                (1ULL << 18)    /* reverse map btree */
+#define XFS_FEAT_REFLINK       (1ULL << 19)    /* reflinked files */
+#define XFS_FEAT_SPINODES      (1ULL << 20)    /* sparse inode chunks */
+#define XFS_FEAT_META_UUID     (1ULL << 21)    /* metadata UUID */
+#define XFS_FEAT_REALTIME      (1ULL << 22)    /* realtime device present */
+#define XFS_FEAT_INOBTCNT      (1ULL << 23)    /* inobt block counts */
+#define XFS_FEAT_BIGTIME       (1ULL << 24)    /* large timestamps */
+#define XFS_FEAT_NEEDSREPAIR   (1ULL << 25)    /* needs xfs_repair */
+
+#define __XFS_HAS_FEAT(name, NAME) \
+static inline bool xfs_has_ ## name (struct xfs_mount *mp) \
+{ \
+       return mp->m_features & XFS_FEAT_ ## NAME; \
+}
+
+/* Some features can be added dynamically so they need a set wrapper, too. */
+#define __XFS_ADD_FEAT(name, NAME) \
+       __XFS_HAS_FEAT(name, NAME); \
+static inline void xfs_add_ ## name (struct xfs_mount *mp) \
+{ \
+       mp->m_features |= XFS_FEAT_ ## NAME; \
+       xfs_sb_version_add ## name(&mp->m_sb); \
+}
+
+__XFS_ADD_FEAT(attr, ATTR)
+__XFS_HAS_FEAT(nlink, NLINK)
+__XFS_ADD_FEAT(quota, QUOTA)
+__XFS_HAS_FEAT(align, ALIGN)
+__XFS_HAS_FEAT(dalign, DALIGN)
+__XFS_HAS_FEAT(logv2, LOGV2)
+__XFS_HAS_FEAT(sector, SECTOR)
+__XFS_HAS_FEAT(extflg, EXTFLG)
+__XFS_HAS_FEAT(asciici, ASCIICI)
+__XFS_HAS_FEAT(lazysbcount, LAZYSBCOUNT)
+__XFS_ADD_FEAT(attr2, ATTR2)
+__XFS_HAS_FEAT(parent, PARENT)
+__XFS_ADD_FEAT(projid32, PROJID32)
+__XFS_HAS_FEAT(crc, CRC)
+__XFS_HAS_FEAT(v3inodes, V3INODES)
+__XFS_HAS_FEAT(pquotino, PQUOTINO)
+__XFS_HAS_FEAT(ftype, FTYPE)
+__XFS_HAS_FEAT(finobt, FINOBT)
+__XFS_HAS_FEAT(rmapbt, RMAPBT)
+__XFS_HAS_FEAT(reflink, REFLINK)
+__XFS_HAS_FEAT(sparseinodes, SPINODES)
+__XFS_HAS_FEAT(metauuid, META_UUID)
+__XFS_HAS_FEAT(realtime, REALTIME)
+__XFS_HAS_FEAT(inobtcounts, REALTIME)
+__XFS_HAS_FEAT(bigtime, REALTIME)
+__XFS_HAS_FEAT(needsrepair, REALTIME)
+
 /*
  * Flags for m_flags.
  */
index 699066f..f3eb4bf 100644 (file)
@@ -1131,6 +1131,9 @@ error_cancel:
                error = xfs_trans_commit(tp);
                if (error)
                        break;
+
+               /* Ensure the mount RT feature flag is now set. */
+               mp->m_features |= XFS_FEAT_REALTIME;
        }
        if (error)
                goto out_free;