aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_log_recover.c19
-rw-r--r--fs/xfs/xfs_mount.c48
-rw-r--r--fs/xfs/xfs_sb.h70
3 files changed, 129 insertions, 8 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 5303b3db3c98..35ac5044ddfd 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3959,6 +3959,25 @@ xlog_recover(
3959 return error; 3959 return error;
3960 } 3960 }
3961 3961
3962 /*
3963 * Version 5 superblock log feature mask validation. We know the
3964 * log is dirty so check if there are any unknown log features
3965 * in what we need to recover. If there are unknown features
3966 * (e.g. unsupported transactions, then simply reject the
3967 * attempt at recovery before touching anything.
3968 */
3969 if (XFS_SB_VERSION_NUM(&log->l_mp->m_sb) == XFS_SB_VERSION_5 &&
3970 xfs_sb_has_incompat_log_feature(&log->l_mp->m_sb,
3971 XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)) {
3972 xfs_warn(log->l_mp,
3973"Superblock has unknown incompatible log features (0x%x) enabled.\n"
3974"The log can not be fully and/or safely recovered by this kernel.\n"
3975"Please recover the log on a kernel that supports the unknown features.",
3976 (log->l_mp->m_sb.sb_features_log_incompat &
3977 XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN));
3978 return EINVAL;
3979 }
3980
3962 xfs_notice(log->l_mp, "Starting recovery (logdev: %s)", 3981 xfs_notice(log->l_mp, "Starting recovery (logdev: %s)",
3963 log->l_mp->m_logname ? log->l_mp->m_logname 3982 log->l_mp->m_logname ? log->l_mp->m_logname
3964 : "internal"); 3983 : "internal");
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 140136cf2dc0..f6bfbd734669 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -114,7 +114,9 @@ static const struct {
114 { offsetof(xfs_sb_t, sb_features_compat), 0 }, 114 { offsetof(xfs_sb_t, sb_features_compat), 0 },
115 { offsetof(xfs_sb_t, sb_features_ro_compat), 0 }, 115 { offsetof(xfs_sb_t, sb_features_ro_compat), 0 },
116 { offsetof(xfs_sb_t, sb_features_incompat), 0 }, 116 { offsetof(xfs_sb_t, sb_features_incompat), 0 },
117 { offsetof(xfs_sb_t, sb_features_log_incompat), 0 },
117 { offsetof(xfs_sb_t, sb_crc), 0 }, 118 { offsetof(xfs_sb_t, sb_crc), 0 },
119 { offsetof(xfs_sb_t, sb_pad), 0 },
118 { offsetof(xfs_sb_t, sb_pquotino), 0 }, 120 { offsetof(xfs_sb_t, sb_pquotino), 0 },
119 { offsetof(xfs_sb_t, sb_lsn), 0 }, 121 { offsetof(xfs_sb_t, sb_lsn), 0 },
120 { sizeof(xfs_sb_t), 0 } 122 { sizeof(xfs_sb_t), 0 }
@@ -334,14 +336,45 @@ xfs_mount_validate_sb(
334 } 336 }
335 337
336 /* 338 /*
337 * Do not allow Version 5 superblocks to mount right now, even though 339 * Version 5 superblock feature mask validation. Reject combinations the
338 * support is in place. We need to implement the proper feature masks 340 * kernel cannot support up front before checking anything else.
339 * first.
340 */ 341 */
341 if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) { 342 if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) {
342 xfs_alert(mp, 343 xfs_alert(mp,
343 "Version 5 superblock detected. Experimental support not yet enabled!"); 344"Version 5 superblock detected. This kernel has EXPERIMENTAL support enabled!\n"
344 return XFS_ERROR(EINVAL); 345"Use of these features in this kernel is at your own risk!");
346
347 if (xfs_sb_has_compat_feature(sbp,
348 XFS_SB_FEAT_COMPAT_UNKNOWN)) {
349 xfs_warn(mp,
350"Superblock has unknown compatible features (0x%x) enabled.\n"
351"Using a more recent kernel is recommended.",
352 (sbp->sb_features_compat &
353 XFS_SB_FEAT_COMPAT_UNKNOWN));
354 }
355
356 if (xfs_sb_has_ro_compat_feature(sbp,
357 XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
358 xfs_alert(mp,
359"Superblock has unknown read-only compatible features (0x%x) enabled.",
360 (sbp->sb_features_ro_compat &
361 XFS_SB_FEAT_RO_COMPAT_UNKNOWN));
362 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
363 xfs_warn(mp,
364"Attempted to mount read-only compatible filesystem read-write.\n"
365"Filesystem can only be safely mounted read only.");
366 return XFS_ERROR(EINVAL);
367 }
368 }
369 if (xfs_sb_has_incompat_feature(sbp,
370 XFS_SB_FEAT_INCOMPAT_UNKNOWN)) {
371 xfs_warn(mp,
372"Superblock has unknown incompatible features (0x%x) enabled.\n"
373"Filesystem can not be safely mounted by this kernel.",
374 (sbp->sb_features_incompat &
375 XFS_SB_FEAT_INCOMPAT_UNKNOWN));
376 return XFS_ERROR(EINVAL);
377 }
345 } 378 }
346 379
347 if (unlikely( 380 if (unlikely(
@@ -580,6 +613,9 @@ xfs_sb_from_disk(
580 to->sb_features_compat = be32_to_cpu(from->sb_features_compat); 613 to->sb_features_compat = be32_to_cpu(from->sb_features_compat);
581 to->sb_features_ro_compat = be32_to_cpu(from->sb_features_ro_compat); 614 to->sb_features_ro_compat = be32_to_cpu(from->sb_features_ro_compat);
582 to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat); 615 to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat);
616 to->sb_features_log_incompat =
617 be32_to_cpu(from->sb_features_log_incompat);
618 to->sb_pad = 0;
583 to->sb_pquotino = be64_to_cpu(from->sb_pquotino); 619 to->sb_pquotino = be64_to_cpu(from->sb_pquotino);
584 to->sb_lsn = be64_to_cpu(from->sb_lsn); 620 to->sb_lsn = be64_to_cpu(from->sb_lsn);
585} 621}
@@ -786,7 +822,7 @@ reread:
786 if (bp->b_error) { 822 if (bp->b_error) {
787 error = bp->b_error; 823 error = bp->b_error;
788 if (loud) 824 if (loud)
789 xfs_warn(mp, "SB validate failed"); 825 xfs_warn(mp, "SB validate failed with error %d.", error);
790 goto release_buf; 826 goto release_buf;
791 } 827 }
792 828
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 457fefae5683..2de58a85833c 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -168,8 +168,10 @@ typedef struct xfs_sb {
168 __uint32_t sb_features_compat; 168 __uint32_t sb_features_compat;
169 __uint32_t sb_features_ro_compat; 169 __uint32_t sb_features_ro_compat;
170 __uint32_t sb_features_incompat; 170 __uint32_t sb_features_incompat;
171 __uint32_t sb_features_log_incompat;
171 172
172 __uint32_t sb_crc; /* superblock crc */ 173 __uint32_t sb_crc; /* superblock crc */
174 __uint32_t sb_pad;
173 175
174 xfs_ino_t sb_pquotino; /* project quota inode */ 176 xfs_ino_t sb_pquotino; /* project quota inode */
175 xfs_lsn_t sb_lsn; /* last write sequence */ 177 xfs_lsn_t sb_lsn; /* last write sequence */
@@ -250,8 +252,10 @@ typedef struct xfs_dsb {
250 __be32 sb_features_compat; 252 __be32 sb_features_compat;
251 __be32 sb_features_ro_compat; 253 __be32 sb_features_ro_compat;
252 __be32 sb_features_incompat; 254 __be32 sb_features_incompat;
255 __be32 sb_features_log_incompat;
253 256
254 __le32 sb_crc; /* superblock crc */ 257 __le32 sb_crc; /* superblock crc */
258 __be32 sb_pad;
255 259
256 __be64 sb_pquotino; /* project quota inode */ 260 __be64 sb_pquotino; /* project quota inode */
257 __be64 sb_lsn; /* last write sequence */ 261 __be64 sb_lsn; /* last write sequence */
@@ -276,7 +280,8 @@ typedef enum {
276 XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG, 280 XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
277 XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT, 281 XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
278 XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_FEATURES_COMPAT, 282 XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_FEATURES_COMPAT,
279 XFS_SBS_FEATURES_RO_COMPAT, XFS_SBS_FEATURES_INCOMPAT, XFS_SBS_CRC, 283 XFS_SBS_FEATURES_RO_COMPAT, XFS_SBS_FEATURES_INCOMPAT,
284 XFS_SBS_FEATURES_LOG_INCOMPAT, XFS_SBS_CRC, XFS_SBS_PAD,
280 XFS_SBS_PQUOTINO, XFS_SBS_LSN, 285 XFS_SBS_PQUOTINO, XFS_SBS_LSN,
281 XFS_SBS_FIELDCOUNT 286 XFS_SBS_FIELDCOUNT
282} xfs_sb_field_t; 287} xfs_sb_field_t;
@@ -306,6 +311,7 @@ typedef enum {
306#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT) 311#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT)
307#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT) 312#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT)
308#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT) 313#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT)
314#define XFS_SB_FEATURES_LOG_INCOMPAT XFS_SB_MVAL(FEATURES_LOG_INCOMPAT)
309#define XFS_SB_CRC XFS_SB_MVAL(CRC) 315#define XFS_SB_CRC XFS_SB_MVAL(CRC)
310#define XFS_SB_PQUOTINO XFS_SB_MVAL(PQUOTINO) 316#define XFS_SB_PQUOTINO XFS_SB_MVAL(PQUOTINO)
311#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT) 317#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT)
@@ -316,7 +322,8 @@ typedef enum {
316 XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \ 322 XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
317 XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \ 323 XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \
318 XFS_SB_BAD_FEATURES2 | XFS_SB_FEATURES_COMPAT | \ 324 XFS_SB_BAD_FEATURES2 | XFS_SB_FEATURES_COMPAT | \
319 XFS_SB_FEATURES_RO_COMPAT | XFS_SB_FEATURES_INCOMPAT | XFS_SB_PQUOTINO) 325 XFS_SB_FEATURES_RO_COMPAT | XFS_SB_FEATURES_INCOMPAT | \
326 XFS_SB_FEATURES_LOG_INCOMPAT | XFS_SB_PQUOTINO)
320 327
321 328
322/* 329/*
@@ -552,6 +559,65 @@ static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp)
552 return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; 559 return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
553} 560}
554 561
562
563/*
564 * Extended v5 superblock feature masks. These are to be used for new v5
565 * superblock features only.
566 *
567 * Compat features are new features that old kernels will not notice or affect
568 * and so can mount read-write without issues.
569 *
570 * RO-Compat (read only) are features that old kernels can read but will break
571 * if they write. Hence only read-only mounts of such filesystems are allowed on
572 * kernels that don't support the feature bit.
573 *
574 * InCompat features are features which old kernels will not understand and so
575 * must not mount.
576 *
577 * Log-InCompat features are for changes to log formats or new transactions that
578 * can't be replayed on older kernels. The fields are set when the filesystem is
579 * mounted, and a clean unmount clears the fields.
580 */
581#define XFS_SB_FEAT_COMPAT_ALL 0
582#define XFS_SB_FEAT_COMPAT_UNKNOWN ~XFS_SB_FEAT_COMPAT_ALL
583static inline bool
584xfs_sb_has_compat_feature(
585 struct xfs_sb *sbp,
586 __uint32_t feature)
587{
588 return (sbp->sb_features_compat & feature) != 0;
589}
590
591#define XFS_SB_FEAT_RO_COMPAT_ALL 0
592#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL
593static inline bool
594xfs_sb_has_ro_compat_feature(
595 struct xfs_sb *sbp,
596 __uint32_t feature)
597{
598 return (sbp->sb_features_ro_compat & feature) != 0;
599}
600
601#define XFS_SB_FEAT_INCOMPAT_ALL 0
602#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL
603static inline bool
604xfs_sb_has_incompat_feature(
605 struct xfs_sb *sbp,
606 __uint32_t feature)
607{
608 return (sbp->sb_features_incompat & feature) != 0;
609}
610
611#define XFS_SB_FEAT_INCOMPAT_LOG_ALL 0
612#define XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_LOG_ALL
613static inline bool
614xfs_sb_has_incompat_log_feature(
615 struct xfs_sb *sbp,
616 __uint32_t feature)
617{
618 return (sbp->sb_features_log_incompat & feature) != 0;
619}
620
555/* 621/*
556 * end of superblock version macros 622 * end of superblock version macros
557 */ 623 */