aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_mount.c34
-rw-r--r--fs/xfs/xfs_sb.h37
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
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,
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 */
93typedef struct xfs_sb { 94typedef 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 */
153typedef struct xfs_dsb { 165typedef 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 */
325static inline int xfs_sb_has_bad_features2(xfs_sb_t *sbp)
326{
327 return (sbp->sb_bad_features2 != 0);
328}
329
299static inline unsigned xfs_sb_version_tonew(unsigned v) 330static inline unsigned xfs_sb_version_tonew(unsigned v)
300{ 331{
301 return ((((v) == XFS_SB_VERSION_1) ? \ 332 return ((((v) == XFS_SB_VERSION_1) ? \