]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Duplicate sb_features2 into following 4 bytes in superblock due to bug
authorBarry Naujok <bnaujok@sgi.com>
Mon, 14 Apr 2008 04:11:32 +0000 (04:11 +0000)
committerBarry Naujok <bnaujok@sgi.com>
Mon, 14 Apr 2008 04:11:32 +0000 (04:11 +0000)
Merge of master-melb:xfs-cmds:30855a by kenmcd.

  Detect features2 in wrong location in superblock

db/check.c
db/sb.c
include/xfs_sb.h
libxfs/xfs_mount.c
mkfs/xfs_mkfs.c
repair/phase1.c

index 94f9cd5541ffbd4badfdf7ed0d9d50211ca15a8c..bd6d8a9aacfe3a6f870bb064a3ed16342292dc26 100644 (file)
@@ -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 64a9520c2837ea35f8a9db029542740d0ce33326..03a639e3decb56d8d3f59fc9d1578d88d057781e 100644 (file)
--- 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 }
 };
 
index fd27650499da39136bd91103dbf33e1885454a85..3098344208f11380e8cf95ee3da2aaac8f1c12ec 100644 (file)
@@ -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;
 
index 8e71aee278990a34ec4d7f7e9ae1ced0830a40fd..cb07cd4d730612bbca36be422db59532e2fc6119 100644 (file)
@@ -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 }
 };
 
index f30d67452697e67cace027ae28bca7d659c5fbbe..5e86295baea3f4c9fc79c28c7215fa6f46c8b6b9 100644 (file)
@@ -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);
index e860deb82a2803da5301002044887d0e3f8738eb..3a25934a1e8e5e15c6e6c31a0c2c236df11874c3 100644 (file)
@@ -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"));