aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_mount.c
diff options
context:
space:
mode:
authorDavid Chinner <dgc@sgi.com>2008-03-05 21:45:50 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-04-10 02:25:15 -0400
commitee1c090825bf2f1cb9712489c234eabf69a9a78f (patch)
treec261cbeeda46937e6c65994b4348227505665f66 /fs/xfs/xfs_mount.c
parent6211870992502efdccf9cd6bae155c83277835fa (diff)
[XFS] Fix superblock features2 field alignment problem
Due to the xfs_dsb_t structure not being 64 bit aligned, the last field of the on-disk superblock can vary in location This causes problems when the filesystem gets moved to a different platform, or there is a 32 bit userspace and 64 bit kernel. This patch detects the defect at mount time, logs a warning such as: XFS: correcting sb_features alignment problem in dmesg and corrects the problem so that everything is OK. it also blacklists the bad field in the superblock so it does not get used for something else later on. SGI-PV: 977636 SGI-Modid: xfs-linux-melb:xfs-kern:30539a Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r--fs/xfs/xfs_mount.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 99bab1e372b1..4e93c02faf24 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -44,7 +44,7 @@
44#include "xfs_quota.h" 44#include "xfs_quota.h"
45#include "xfs_fsops.h" 45#include "xfs_fsops.h"
46 46
47STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t); 47STATIC void xfs_mount_log_sb(xfs_mount_t *, __int64_t);
48STATIC int xfs_uuid_mount(xfs_mount_t *); 48STATIC int xfs_uuid_mount(xfs_mount_t *);
49STATIC void xfs_uuid_unmount(xfs_mount_t *mp); 49STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
50STATIC void xfs_unmountfs_wait(xfs_mount_t *); 50STATIC void xfs_unmountfs_wait(xfs_mount_t *);
@@ -119,6 +119,7 @@ static const struct {
119 { offsetof(xfs_sb_t, sb_logsectsize),0 }, 119 { offsetof(xfs_sb_t, sb_logsectsize),0 },
120 { offsetof(xfs_sb_t, sb_logsunit), 0 }, 120 { offsetof(xfs_sb_t, sb_logsunit), 0 },
121 { offsetof(xfs_sb_t, sb_features2), 0 }, 121 { offsetof(xfs_sb_t, sb_features2), 0 },
122 { offsetof(xfs_sb_t, sb_bad_features2), 0 },
122 { sizeof(xfs_sb_t), 0 } 123 { sizeof(xfs_sb_t), 0 }
123}; 124};
124 125
@@ -449,6 +450,7 @@ xfs_sb_from_disk(
449 to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize); 450 to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize);
450 to->sb_logsunit = be32_to_cpu(from->sb_logsunit); 451 to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
451 to->sb_features2 = be32_to_cpu(from->sb_features2); 452 to->sb_features2 = be32_to_cpu(from->sb_features2);
453 to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2);
452} 454}
453 455
454/* 456/*
@@ -970,6 +972,26 @@ xfs_mountfs(
970 xfs_mount_common(mp, sbp); 972 xfs_mount_common(mp, sbp);
971 973
972 /* 974 /*
975 * Check for a bad features2 field alignment. This happened on
976 * some platforms due to xfs_sb_t not being 64bit size aligned
977 * when sb_features was added and hence the compiler put it in
978 * the wrong place.
979 *
980 * If we detect a bad field, we or the set bits into the existing
981 * features2 field in case it has already been modified and we
982 * don't want to lose any features. Zero the bad one and mark
983 * the two fields as needing updates once the transaction subsystem
984 * is online.
985 */
986 if (xfs_sb_has_bad_features2(sbp)) {
987 cmn_err(CE_WARN,
988 "XFS: correcting sb_features alignment problem");
989 sbp->sb_features2 |= sbp->sb_bad_features2;
990 sbp->sb_bad_features2 = 0;
991 update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;
992 }
993
994 /*
973 * Check if sb_agblocks is aligned at stripe boundary 995 * Check if sb_agblocks is aligned at stripe boundary
974 * If sb_agblocks is NOT aligned turn off m_dalign since 996 * If sb_agblocks is NOT aligned turn off m_dalign since
975 * allocator alignment is within an ag, therefore ag has 997 * allocator alignment is within an ag, therefore ag has
@@ -1159,11 +1181,10 @@ xfs_mountfs(
1159 } 1181 }
1160 1182
1161 /* 1183 /*
1162 * If fs is not mounted readonly, then update the superblock 1184 * If fs is not mounted readonly, then update the superblock changes.
1163 * unit and width changes.
1164 */ 1185 */
1165 if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) 1186 if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY))
1166 xfs_mount_log_sbunit(mp, update_flags); 1187 xfs_mount_log_sb(mp, update_flags);
1167 1188
1168 /* 1189 /*
1169 * Initialise the XFS quota management subsystem for this mount 1190 * Initialise the XFS quota management subsystem for this mount
@@ -1878,13 +1899,14 @@ xfs_uuid_unmount(
1878 * be altered by the mount options. Only the first superblock is updated. 1899 * be altered by the mount options. Only the first superblock is updated.
1879 */ 1900 */
1880STATIC void 1901STATIC void
1881xfs_mount_log_sbunit( 1902xfs_mount_log_sb(
1882 xfs_mount_t *mp, 1903 xfs_mount_t *mp,
1883 __int64_t fields) 1904 __int64_t fields)
1884{ 1905{
1885 xfs_trans_t *tp; 1906 xfs_trans_t *tp;
1886 1907
1887 ASSERT(fields & (XFS_SB_UNIT|XFS_SB_WIDTH|XFS_SB_UUID)); 1908 ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
1909 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2));
1888 1910
1889 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT); 1911 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
1890 if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, 1912 if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,