From: Barry Naujok Date: Mon, 14 Apr 2008 04:11:32 +0000 (+0000) Subject: Duplicate sb_features2 into following 4 bytes in superblock due to bug X-Git-Tag: v2.10.0~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=459357370731f1197366b04eb60e1198f49ccaf2;p=thirdparty%2Fxfsprogs-dev.git Duplicate sb_features2 into following 4 bytes in superblock due to bug Merge of master-melb:xfs-cmds:30855a by kenmcd. Detect features2 in wrong location in superblock --- diff --git a/db/check.c b/db/check.c index 94f9cd554..bd6d8a9aa 100644 --- a/db/check.c +++ b/db/check.c @@ -869,6 +869,15 @@ blockget_f( mp->m_sb.sb_frextents, frextents); error++; } + if (mp->m_sb.sb_bad_features2 != 0 && + mp->m_sb.sb_bad_features2 != mp->m_sb.sb_features2) { + if (!sflag) + dbprintf("sb_features2 (0x%x) not same as " + "sb_bad_features2 (0x%x)\n", + mp->m_sb.sb_features2, + mp->m_sb.sb_bad_features2); + error++; + } if ((sbversion & XFS_SB_VERSION_ATTRBIT) && !XFS_SB_VERSION_HASATTR(&mp->m_sb)) { if (!sflag) diff --git a/db/sb.c b/db/sb.c index 64a9520c2..03a639e3d 100644 --- a/db/sb.c +++ b/db/sb.c @@ -108,6 +108,7 @@ const field_t sb_flds[] = { { "logsectsize", FLDT_UINT16D, OI(OFF(logsectsize)), C1, 0, TYP_NONE }, { "logsunit", FLDT_UINT32D, OI(OFF(logsunit)), C1, 0, TYP_NONE }, { "features2", FLDT_UINT32X, OI(OFF(features2)), C1, 0, TYP_NONE }, + { "bad_features2", FLDT_UINT32X, OI(OFF(bad_features2)), C1, 0, TYP_NONE }, { NULL } }; diff --git a/include/xfs_sb.h b/include/xfs_sb.h index fd2765049..309834420 100644 --- a/include/xfs_sb.h +++ b/include/xfs_sb.h @@ -151,6 +151,7 @@ typedef struct xfs_sb __uint16_t sb_logsectsize; /* sector size for the log, bytes */ __uint32_t sb_logsunit; /* stripe unit size for the log */ __uint32_t sb_features2; /* additional feature bits */ + __uint32_t sb_bad_features2; /* unusable space */ } xfs_sb_t; /* @@ -169,7 +170,7 @@ typedef enum { XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN, XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG, XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT, - XFS_SBS_FEATURES2, + XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_FIELDCOUNT } xfs_sb_field_t; diff --git a/libxfs/xfs_mount.c b/libxfs/xfs_mount.c index 8e71aee27..cb07cd4d7 100644 --- a/libxfs/xfs_mount.c +++ b/libxfs/xfs_mount.c @@ -140,6 +140,7 @@ static struct { { offsetof(xfs_sb_t, sb_logsectsize),0 }, { offsetof(xfs_sb_t, sb_logsunit), 0 }, { offsetof(xfs_sb_t, sb_features2), 0 }, + { offsetof(xfs_sb_t, sb_bad_features2), 0 }, { sizeof(xfs_sb_t), 0 } }; diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index f30d67452..5e86295ba 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -2103,6 +2103,13 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), dirversion == 2, logversion == 2, attrversion == 1, (sectorsize != BBSIZE || lsectorsize != BBSIZE), sbp->sb_features2 != 0); + /* + * Due to a structure alignment issue, sb_features2 ended up in one + * of two locations, the second "incorrect" location represented by + * the sb_bad_features2 field. To avoid older kernels mounting + * filesystems they shouldn't, set both field to the same value. + */ + sbp->sb_bad_features2 = sbp->sb_features2; if (force_overwrite) zero_old_xfs_structures(&xi, sbp); diff --git a/repair/phase1.c b/repair/phase1.c index e860deb82..3a25934a1 100644 --- a/repair/phase1.c +++ b/repair/phase1.c @@ -91,6 +91,20 @@ phase1(xfs_mount_t *mp) primary_sb_modified = 1; } + /* + * Check bad_features2 and make sure features2 the same as + * bad_features (ORing the two together). Leave bad_features2 + * set so older kernels can still use it and not mount unsupported + * filesystems when it reads bad_features2. + */ + if (sb->sb_bad_features2 != 0 && + sb->sb_bad_features2 != sb->sb_features2) { + sb->sb_features2 |= sb->sb_bad_features2; + sb->sb_bad_features2 = sb->sb_features2; + primary_sb_modified = 1; + do_warn(_("superblock has a features2 mismatch, correcting\n")); + } + if (primary_sb_modified) { if (!no_modify) { do_warn(_("writing modified primary superblock\n"));