From: Darrick J. Wong <djwong@xxxxxxxxxx> Create a mask for log incompat feature bits that we don't want to clear at unmount time. This will be used in the next patch to make the LOG_XATTRS feature bit sticky when parent pointers are enabled. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_format.h | 5 +++-- fs/xfs/scrub/agheader.c | 7 ++++++- fs/xfs/scrub/agheader_repair.c | 4 +++- fs/xfs/xfs_mount.c | 10 +++++----- fs/xfs/xfs_mount.h | 3 +++ 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 859062ab6c306..b695403f98632 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -417,9 +417,10 @@ xfs_sb_has_incompat_log_feature( static inline void xfs_sb_remove_incompat_log_features( - struct xfs_sb *sbp) + struct xfs_sb *sbp, + unsigned int features) { - sbp->sb_features_log_incompat &= ~XFS_SB_FEAT_INCOMPAT_LOG_ALL; + sbp->sb_features_log_incompat &= ~features; } static inline void diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c index 1528f14bd9251..6c2581faa73d5 100644 --- a/fs/xfs/scrub/agheader.c +++ b/fs/xfs/scrub/agheader.c @@ -329,8 +329,13 @@ xchk_superblock( * log incompat features protect newer log record types from * older log recovery code. Log recovery doesn't check the * secondary supers, so we can clear these if needed. + * + * Note that mkfs sets the "permanent" bits in the secondary + * supers, so we don't flag the field if those are the only + * bits set. */ - if (sb->sb_features_log_incompat) + if (sb->sb_features_log_incompat != + cpu_to_be32(mp->m_perm_log_incompat)) xchk_block_set_preen(sc, bp); /* Don't care about sb_crc */ diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c index 0dbc484b182f9..7c55338b0cdd7 100644 --- a/fs/xfs/scrub/agheader_repair.c +++ b/fs/xfs/scrub/agheader_repair.c @@ -66,13 +66,15 @@ xrep_superblock( /* * Don't write out a secondary super with NEEDSREPAIR or log incompat * features set, since both are ignored when set on a secondary. + * Always set the permanent log incompat features, just like mkfs. */ if (xfs_has_crc(mp)) { struct xfs_dsb *sb = bp->b_addr; sb->sb_features_incompat &= ~cpu_to_be32(XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR); - sb->sb_features_log_incompat = 0; + sb->sb_features_log_incompat = + cpu_to_be32(mp->m_perm_log_incompat); } /* Write this to disk. */ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 6fd4ceeab0e26..49d6c6de7b33b 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1388,11 +1388,12 @@ bool xfs_clear_incompat_log_features( struct xfs_mount *mp) { + unsigned int to_clear = XFS_SB_FEAT_INCOMPAT_LOG_ALL & + ~mp->m_perm_log_incompat; bool ret = false; if (!xfs_has_crc(mp) || - !xfs_sb_has_incompat_log_feature(&mp->m_sb, - XFS_SB_FEAT_INCOMPAT_LOG_ALL) || + !xfs_sb_has_incompat_log_feature(&mp->m_sb, to_clear) || xfs_is_shutdown(mp) || !xfs_is_done_with_log_incompat(mp)) return false; @@ -1405,9 +1406,8 @@ xfs_clear_incompat_log_features( xfs_buf_lock(mp->m_sb_bp); xfs_buf_hold(mp->m_sb_bp); - if (xfs_sb_has_incompat_log_feature(&mp->m_sb, - XFS_SB_FEAT_INCOMPAT_LOG_ALL)) { - xfs_sb_remove_incompat_log_features(&mp->m_sb); + if (xfs_sb_has_incompat_log_feature(&mp->m_sb, to_clear)) { + xfs_sb_remove_incompat_log_features(&mp->m_sb, to_clear); ret = true; } diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a567a1ac24134..0d9f66ac50af2 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -163,6 +163,9 @@ typedef struct xfs_mount { bool m_finobt_nores; /* no per-AG finobt resv. */ bool m_update_sb; /* sb needs update in mount */ + /* never clear these log incompat feature bits */ + unsigned int m_perm_log_incompat; + /* * Bitsets of per-fs metadata that have been checked and/or are sick. * Callers must hold m_sb_lock to access these two fields.