diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 34 |
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 | ||
47 | STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t); | 47 | STATIC void xfs_mount_log_sb(xfs_mount_t *, __int64_t); |
48 | STATIC int xfs_uuid_mount(xfs_mount_t *); | 48 | STATIC int xfs_uuid_mount(xfs_mount_t *); |
49 | STATIC void xfs_uuid_unmount(xfs_mount_t *mp); | 49 | STATIC void xfs_uuid_unmount(xfs_mount_t *mp); |
50 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); | 50 | STATIC 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 | */ |
1880 | STATIC void | 1901 | STATIC void |
1881 | xfs_mount_log_sbunit( | 1902 | xfs_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, |