diff options
-rw-r--r-- | fs/xfs/xfs_mount.c | 34 | ||||
-rw-r--r-- | fs/xfs/xfs_sb.h | 37 |
2 files changed, 62 insertions, 9 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, |
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h index d3a59735009a..b1a83f8ec044 100644 --- a/fs/xfs/xfs_sb.h +++ b/fs/xfs/xfs_sb.h | |||
@@ -89,6 +89,7 @@ struct xfs_mount; | |||
89 | 89 | ||
90 | /* | 90 | /* |
91 | * Superblock - in core version. Must match the ondisk version below. | 91 | * Superblock - in core version. Must match the ondisk version below. |
92 | * Must be padded to 64 bit alignment. | ||
92 | */ | 93 | */ |
93 | typedef struct xfs_sb { | 94 | typedef struct xfs_sb { |
94 | __uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ | 95 | __uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ |
@@ -145,10 +146,21 @@ typedef struct xfs_sb { | |||
145 | __uint16_t sb_logsectsize; /* sector size for the log, bytes */ | 146 | __uint16_t sb_logsectsize; /* sector size for the log, bytes */ |
146 | __uint32_t sb_logsunit; /* stripe unit size for the log */ | 147 | __uint32_t sb_logsunit; /* stripe unit size for the log */ |
147 | __uint32_t sb_features2; /* additional feature bits */ | 148 | __uint32_t sb_features2; /* additional feature bits */ |
149 | |||
150 | /* | ||
151 | * bad features2 field as a result of failing to pad the sb | ||
152 | * structure to 64 bits. Some machines will be using this field | ||
153 | * for features2 bits. Easiest just to mark it bad and not use | ||
154 | * it for anything else. | ||
155 | */ | ||
156 | __uint32_t sb_bad_features2; | ||
157 | |||
158 | /* must be padded to 64 bit alignment */ | ||
148 | } xfs_sb_t; | 159 | } xfs_sb_t; |
149 | 160 | ||
150 | /* | 161 | /* |
151 | * Superblock - on disk version. Must match the in core version below. | 162 | * Superblock - on disk version. Must match the in core version above. |
163 | * Must be padded to 64 bit alignment. | ||
152 | */ | 164 | */ |
153 | typedef struct xfs_dsb { | 165 | typedef struct xfs_dsb { |
154 | __be32 sb_magicnum; /* magic number == XFS_SB_MAGIC */ | 166 | __be32 sb_magicnum; /* magic number == XFS_SB_MAGIC */ |
@@ -205,6 +217,15 @@ typedef struct xfs_dsb { | |||
205 | __be16 sb_logsectsize; /* sector size for the log, bytes */ | 217 | __be16 sb_logsectsize; /* sector size for the log, bytes */ |
206 | __be32 sb_logsunit; /* stripe unit size for the log */ | 218 | __be32 sb_logsunit; /* stripe unit size for the log */ |
207 | __be32 sb_features2; /* additional feature bits */ | 219 | __be32 sb_features2; /* additional feature bits */ |
220 | /* | ||
221 | * bad features2 field as a result of failing to pad the sb | ||
222 | * structure to 64 bits. Some machines will be using this field | ||
223 | * for features2 bits. Easiest just to mark it bad and not use | ||
224 | * it for anything else. | ||
225 | */ | ||
226 | __be32 sb_bad_features2; | ||
227 | |||
228 | /* must be padded to 64 bit alignment */ | ||
208 | } xfs_dsb_t; | 229 | } xfs_dsb_t; |
209 | 230 | ||
210 | /* | 231 | /* |
@@ -223,7 +244,7 @@ typedef enum { | |||
223 | XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN, | 244 | XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN, |
224 | XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG, | 245 | XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG, |
225 | XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT, | 246 | XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT, |
226 | XFS_SBS_FEATURES2, | 247 | XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, |
227 | XFS_SBS_FIELDCOUNT | 248 | XFS_SBS_FIELDCOUNT |
228 | } xfs_sb_field_t; | 249 | } xfs_sb_field_t; |
229 | 250 | ||
@@ -248,13 +269,15 @@ typedef enum { | |||
248 | #define XFS_SB_IFREE XFS_SB_MVAL(IFREE) | 269 | #define XFS_SB_IFREE XFS_SB_MVAL(IFREE) |
249 | #define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS) | 270 | #define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS) |
250 | #define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2) | 271 | #define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2) |
272 | #define XFS_SB_BAD_FEATURES2 XFS_SB_MVAL(BAD_FEATURES2) | ||
251 | #define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT) | 273 | #define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT) |
252 | #define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1) | 274 | #define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1) |
253 | #define XFS_SB_MOD_BITS \ | 275 | #define XFS_SB_MOD_BITS \ |
254 | (XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \ | 276 | (XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \ |
255 | XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \ | 277 | XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \ |
256 | XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \ | 278 | XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \ |
257 | XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2) | 279 | XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \ |
280 | XFS_SB_BAD_FEATURES2) | ||
258 | 281 | ||
259 | 282 | ||
260 | /* | 283 | /* |
@@ -296,6 +319,14 @@ static inline int xfs_sb_good_version(xfs_sb_t *sbp) | |||
296 | } | 319 | } |
297 | #endif /* __KERNEL__ */ | 320 | #endif /* __KERNEL__ */ |
298 | 321 | ||
322 | /* | ||
323 | * Detect a bad features2 field | ||
324 | */ | ||
325 | static inline int xfs_sb_has_bad_features2(xfs_sb_t *sbp) | ||
326 | { | ||
327 | return (sbp->sb_bad_features2 != 0); | ||
328 | } | ||
329 | |||
299 | static inline unsigned xfs_sb_version_tonew(unsigned v) | 330 | static inline unsigned xfs_sb_version_tonew(unsigned v) |
300 | { | 331 | { |
301 | return ((((v) == XFS_SB_VERSION_1) ? \ | 332 | return ((((v) == XFS_SB_VERSION_1) ? \ |