xfs: reflect sb features in xfs_mount

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>
This commit is contained in:
Dave Chinner 2021-08-18 18:46:26 -07:00 committed by Darrick J. Wong
parent e23b55d537
commit a1d86e8dec
7 changed files with 149 additions and 1 deletions

View 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;

View file

@ -30,6 +30,72 @@
* 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(

View 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);

View 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) {

View file

@ -225,6 +225,7 @@ xfs_readsb(
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 */

View 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.
*/

View file

@ -1131,6 +1131,9 @@ xfs_growfs_rt(
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;