From 2b7301269e82e86d9601392d289e38f3f66b1467 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 17 May 2022 22:48:13 -0400 Subject: [PATCH] xfs_repair: detect v5 featureset mismatches in secondary supers Make sure we detect and correct mismatches between the V5 features described in the primary and the secondary superblocks. Signed-off-by: Darrick J. Wong Reviewed-by: Eric Sandeen [sandeen: add comment about XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR] Signed-off-by: Eric Sandeen --- repair/agheader.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/repair/agheader.c b/repair/agheader.c index 2af2410..90adc1f 100644 --- a/repair/agheader.c +++ b/repair/agheader.c @@ -221,6 +221,96 @@ compare_sb(xfs_mount_t *mp, xfs_sb_t *sb) } /* + * If the fs feature bits on a secondary superblock don't match the + * primary, we need to update them. + */ +static inline int +check_v5_feature_mismatch( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct xfs_sb *sb) +{ + bool dirty = false; + + if (!xfs_sb_version_hascrc(&mp->m_sb) || agno == 0) + return 0; + + if (mp->m_sb.sb_features_compat != sb->sb_features_compat) { + if (no_modify) { + do_warn( + _("would fix compat feature mismatch in AG %u super, 0x%x != 0x%x\n"), + agno, mp->m_sb.sb_features_compat, + sb->sb_features_compat); + } else { + do_warn( + _("will fix compat feature mismatch in AG %u super, 0x%x != 0x%x\n"), + agno, mp->m_sb.sb_features_compat, + sb->sb_features_compat); + dirty = true; + } + } + + /* + * Ignore XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR becauses the repair upgrade + * path sets it only on the primary while upgrading. + */ + if ((mp->m_sb.sb_features_incompat ^ sb->sb_features_incompat) & + ~XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR) { + if (no_modify) { + do_warn( + _("would fix incompat feature mismatch in AG %u super, 0x%x != 0x%x\n"), + agno, mp->m_sb.sb_features_incompat, + sb->sb_features_incompat); + } else { + do_warn( + _("will fix incompat feature mismatch in AG %u super, 0x%x != 0x%x\n"), + agno, mp->m_sb.sb_features_incompat, + sb->sb_features_incompat); + dirty = true; + } + } + + if (mp->m_sb.sb_features_ro_compat != sb->sb_features_ro_compat) { + if (no_modify) { + do_warn( + _("would fix ro compat feature mismatch in AG %u super, 0x%x != 0x%x\n"), + agno, mp->m_sb.sb_features_ro_compat, + sb->sb_features_ro_compat); + } else { + do_warn( + _("will fix ro compat feature mismatch in AG %u super, 0x%x != 0x%x\n"), + agno, mp->m_sb.sb_features_ro_compat, + sb->sb_features_ro_compat); + dirty = true; + } + } + + if (mp->m_sb.sb_features_log_incompat != sb->sb_features_log_incompat) { + if (no_modify) { + do_warn( + _("would fix log incompat feature mismatch in AG %u super, 0x%x != 0x%x\n"), + agno, mp->m_sb.sb_features_log_incompat, + sb->sb_features_log_incompat); + } else { + do_warn( + _("will fix log incompat feature mismatch in AG %u super, 0x%x != 0x%x\n"), + agno, mp->m_sb.sb_features_log_incompat, + sb->sb_features_log_incompat); + dirty = true; + } + } + + if (!dirty) + return 0; + + sb->sb_features_compat = mp->m_sb.sb_features_compat; + sb->sb_features_ro_compat = mp->m_sb.sb_features_ro_compat; + sb->sb_features_incompat = mp->m_sb.sb_features_incompat; + sb->sb_features_log_incompat = mp->m_sb.sb_features_log_incompat; + return XR_AG_SB_SEC; +} + +/* * Possible fields that may have been set at mkfs time, * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog. * The quota inode fields in the secondaries should be zero. @@ -452,6 +542,8 @@ secondary_sb_whack( rval |= XR_AG_SB_SEC; } + rval |= check_v5_feature_mismatch(mp, i, sb); + if (xfs_sb_version_needsrepair(sb)) { if (i == 0) { if (!no_modify) -- 1.8.3.1