From: Dave Chinner <dchinner@xxxxxxxxxx> The version 5 superblock has extended feature masks for compatible, incompatible and read-only compatible feature sets. Implement the masking and mount-time checking for these feature masks. Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx> --- include/xfs_sb.h | 70 ++++++++++++++++++++++++++++++++++++++++++-- libxfs/xfs_mount.c | 53 ++++++++++++++++++++++++--------- logprint/log_print_trans.c | 18 ++++++++++++ 3 files changed, 125 insertions(+), 16 deletions(-) diff --git a/include/xfs_sb.h b/include/xfs_sb.h index d6709db..51db6f2 100644 --- a/include/xfs_sb.h +++ b/include/xfs_sb.h @@ -168,8 +168,10 @@ typedef struct xfs_sb { __uint32_t sb_features_compat; __uint32_t sb_features_ro_compat; __uint32_t sb_features_incompat; + __uint32_t sb_features_log_incompat; __uint32_t sb_crc; /* superblock crc */ + __uint32_t sb_pad; xfs_ino_t sb_pquotino; /* project quota inode */ xfs_lsn_t sb_lsn; /* last write sequence */ @@ -250,8 +252,10 @@ typedef struct xfs_dsb { __be32 sb_features_compat; __be32 sb_features_ro_compat; __be32 sb_features_incompat; + __be32 sb_features_log_incompat; __le32 sb_crc; /* superblock crc */ + __be32 sb_pad; __be64 sb_pquotino; /* project quota inode */ __be64 sb_lsn; /* last write sequence */ @@ -276,7 +280,8 @@ typedef enum { XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG, XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT, XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_FEATURES_COMPAT, - XFS_SBS_FEATURES_RO_COMPAT, XFS_SBS_FEATURES_INCOMPAT, XFS_SBS_CRC, + XFS_SBS_FEATURES_RO_COMPAT, XFS_SBS_FEATURES_INCOMPAT, + XFS_SBS_FEATURES_LOG_INCOMPAT, XFS_SBS_CRC, XFS_SBS_PAD, XFS_SBS_PQUOTINO, XFS_SBS_LSN, XFS_SBS_FIELDCOUNT } xfs_sb_field_t; @@ -306,6 +311,7 @@ typedef enum { #define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT) #define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT) #define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT) +#define XFS_SB_FEATURES_LOG_INCOMPAT XFS_SB_MVAL(FEATURES_LOG_INCOMPAT) #define XFS_SB_CRC XFS_SB_MVAL(CRC) #define XFS_SB_PQUOTINO XFS_SB_MVAL(PQUOTINO) #define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT) @@ -316,7 +322,8 @@ typedef enum { XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \ XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \ XFS_SB_BAD_FEATURES2 | XFS_SB_FEATURES_COMPAT | \ - XFS_SB_FEATURES_RO_COMPAT | XFS_SB_FEATURES_INCOMPAT | XFS_SB_PQUOTINO) + XFS_SB_FEATURES_RO_COMPAT | XFS_SB_FEATURES_INCOMPAT | \ + XFS_SB_FEATURES_LOG_INCOMPAT | XFS_SB_PQUOTINO) /* @@ -559,6 +566,65 @@ static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp) return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; } + +/* + * Extended v5 superblock feature masks. These are to be used for new v5 + * superblock features only. + * + * Compat features are new features that old kernels will not notice or affect + * and so can mount read-write without issues. + * + * RO-Compat (read only) are features that old kernels can read but will break + * if they write. Hence only read-only mounts of such filesystems are allowed on + * kernels that don't support the feature bit. + * + * InCompat features are features which old kernels will not understand and so + * must not mount. + * + * Log-InCompat features are for changes to log formats or new transactions that + * can't be replayed on older kernels. The fields are set when the filesystem is + * mounted, and a clean unmount clears the fields. + */ +#define XFS_SB_FEAT_COMPAT_ALL 0 +#define XFS_SB_FEAT_COMPAT_UNKNOWN ~XFS_SB_FEAT_COMPAT_ALL +static inline bool +xfs_sb_has_compat_feature( + struct xfs_sb *sbp, + __uint32_t feature) +{ + return (sbp->sb_features_compat & feature) != 0; +} + +#define XFS_SB_FEAT_RO_COMPAT_ALL 0 +#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL +static inline bool +xfs_sb_has_ro_compat_feature( + struct xfs_sb *sbp, + __uint32_t feature) +{ + return (sbp->sb_features_ro_compat & feature) != 0; +} + +#define XFS_SB_FEAT_INCOMPAT_ALL 0 +#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL +static inline bool +xfs_sb_has_incompat_feature( + struct xfs_sb *sbp, + __uint32_t feature) +{ + return (sbp->sb_features_incompat & feature) != 0; +} + +#define XFS_SB_FEAT_INCOMPAT_LOG_ALL 0 +#define XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_LOG_ALL +static inline bool +xfs_sb_has_incompat_log_feature( + struct xfs_sb *sbp, + __uint32_t feature) +{ + return (sbp->sb_features_log_incompat & feature) != 0; +} + /* * end of superblock version macros */ diff --git a/libxfs/xfs_mount.c b/libxfs/xfs_mount.c index 07b892b..f66f63d 100644 --- a/libxfs/xfs_mount.c +++ b/libxfs/xfs_mount.c @@ -73,7 +73,9 @@ static const struct { { offsetof(xfs_sb_t, sb_features_compat), 0 }, { offsetof(xfs_sb_t, sb_features_ro_compat), 0 }, { offsetof(xfs_sb_t, sb_features_incompat), 0 }, + { offsetof(xfs_sb_t, sb_features_log_incompat), 0 }, { offsetof(xfs_sb_t, sb_crc), 0 }, + { offsetof(xfs_sb_t, sb_pad), 0 }, { offsetof(xfs_sb_t, sb_pquotino), 0 }, { offsetof(xfs_sb_t, sb_lsn), 0 }, { sizeof(xfs_sb_t), 0 } @@ -140,18 +142,44 @@ xfs_mount_validate_sb( } /* - * Do not allow Version 5 superblocks to mount right now, even though - * support is in place. We need to implement the proper feature masks - * first. + * Version 5 superblock feature mask validation. Reject combinations the + * kernel cannot support up front before checking anything else. */ - if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) { + if (check_inprogress && XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) { xfs_alert(mp, - "Version 5 superblock detected. Experimental support not yet enabled!"); - return XFS_ERROR(EINVAL); +"Version 5 superblock detected. xfsprogs has EXPERIMENTAL support enabled!\n" +"Use of these features is at your own risk!"); + + if (xfs_sb_has_compat_feature(sbp, + XFS_SB_FEAT_COMPAT_UNKNOWN)) { + xfs_warn(mp, +"Superblock has unknown compatible features (0x%x) enabled.\n" +"Using a more recent xfsprogs is recommended.", + (sbp->sb_features_compat & + XFS_SB_FEAT_COMPAT_UNKNOWN)); + } + + if (xfs_sb_has_ro_compat_feature(sbp, + XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) { + xfs_warn(mp, +"Superblock has unknown read-only compatible features (0x%x) enabled.\n" +"Using a more recent xfsprogs is recommended.", + (sbp->sb_features_ro_compat & + XFS_SB_FEAT_RO_COMPAT_UNKNOWN)); + } + if (xfs_sb_has_incompat_feature(sbp, + XFS_SB_FEAT_INCOMPAT_UNKNOWN)) { + xfs_warn(mp, +"Superblock has unknown incompatible features (0x%x) enabled.\n" +"Filesystem can not be safely operated on by this xfsprogs installation", + (sbp->sb_features_incompat & + XFS_SB_FEAT_INCOMPAT_UNKNOWN)); + return XFS_ERROR(EINVAL); + } } if (unlikely( - sbp->sb_logstart == 0 && mp->m_logdev == mp->m_dev)) { + sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { xfs_warn(mp, "filesystem is marked as having an external log; " "specify logdev on the mount command line."); @@ -159,7 +187,7 @@ xfs_mount_validate_sb( } if (unlikely( - sbp->sb_logstart != 0 && mp->m_logdev != mp->m_dev)) { + sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { xfs_warn(mp, "filesystem is marked as having an internal log; " "do not specify logdev on the mount command line."); @@ -214,12 +242,6 @@ xfs_mount_validate_sb( return XFS_ERROR(ENOSYS); } - - if (check_inprogress && sbp->sb_inprogress) { - xfs_warn(mp, "Offline file system operation in progress!"); - return XFS_ERROR(EFSCORRUPTED); - } - /* * Version 1 directory format has never worked on Linux. */ @@ -285,6 +307,9 @@ xfs_sb_from_disk( to->sb_features_compat = be32_to_cpu(from->sb_features_compat); to->sb_features_ro_compat = be32_to_cpu(from->sb_features_ro_compat); to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat); + to->sb_features_log_incompat = + be32_to_cpu(from->sb_features_log_incompat); + to->sb_pad = 0; to->sb_pquotino = be64_to_cpu(from->sb_pquotino); to->sb_lsn = be64_to_cpu(from->sb_lsn); } diff --git a/logprint/log_print_trans.c b/logprint/log_print_trans.c index 86e1c42..2dd3a10 100644 --- a/logprint/log_print_trans.c +++ b/logprint/log_print_trans.c @@ -68,6 +68,24 @@ xfs_log_print_trans( if (head_blk == tail_blk) return; + + /* + * Version 5 superblock log feature mask validation. We know the + * log is dirty so check if there are any unknown log features + * in what we need to recover. If there are unknown features + * (e.g. unsupported transactions) then warn about it. + */ + if (XFS_SB_VERSION_NUM(&log->l_mp->m_sb) == XFS_SB_VERSION_5 && + xfs_sb_has_incompat_log_feature(&log->l_mp->m_sb, + XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)) { + printf(_( +"Superblock has unknown incompatible log features (0x%x) enabled.\n" +"Output may be incomplete or inaccurate. It is recommended that you\n" +"upgrade your xfsprogs installation to match the filesystem features.\n"), + (log->l_mp->m_sb.sb_features_log_incompat & + XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)); + } + if ((error = xlog_do_recovery_pass(log, head_blk, tail_blk, XLOG_RECOVER_PASS1))) { fprintf(stderr, _("%s: failed in xfs_do_recovery_pass, error: %d\n"), progname, error); -- 1.7.10.4 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs