diff options
author | Dave Chinner <dchinner@redhat.com> | 2015-01-21 17:10:33 -0500 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2015-01-21 17:10:33 -0500 |
commit | 074e427ba7f7398427e4f8e2aec071edcc509673 (patch) | |
tree | 8cb840a1a507e0c1c06fee397d533b0274d89939 /fs | |
parent | 61e63ecb577f9b56bfb3182f1215b64e37a12c38 (diff) |
xfs: sanitise sb_bad_features2 handling
We currently have to ensure that every time we update sb_features2
that we update sb_bad_features2. Now that we log and format the
superblock in it's entirety we actually don't have to care because
we can simply update the sb_bad_features2 when we format it into the
buffer. This removes the need for anything but the mount and
superblock formatting code to care about sb_bad_features2, and
hence removes the possibility that we forget to update bad_features2
when necessary in the future.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/libxfs/xfs_format.h | 14 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_sb.c | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 23 |
3 files changed, 25 insertions, 20 deletions
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index fbd6da263571..749c86102794 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h | |||
@@ -151,10 +151,13 @@ typedef struct xfs_sb { | |||
151 | __uint32_t sb_features2; /* additional feature bits */ | 151 | __uint32_t sb_features2; /* additional feature bits */ |
152 | 152 | ||
153 | /* | 153 | /* |
154 | * bad features2 field as a result of failing to pad the sb | 154 | * bad features2 field as a result of failing to pad the sb structure to |
155 | * structure to 64 bits. Some machines will be using this field | 155 | * 64 bits. Some machines will be using this field for features2 bits. |
156 | * for features2 bits. Easiest just to mark it bad and not use | 156 | * Easiest just to mark it bad and not use it for anything else. |
157 | * it for anything else. | 157 | * |
158 | * This is not kept up to date in memory; it is always overwritten by | ||
159 | * the value in sb_features2 when formatting the incore superblock to | ||
160 | * the disk buffer. | ||
158 | */ | 161 | */ |
159 | __uint32_t sb_bad_features2; | 162 | __uint32_t sb_bad_features2; |
160 | 163 | ||
@@ -453,13 +456,11 @@ static inline void xfs_sb_version_addattr2(struct xfs_sb *sbp) | |||
453 | { | 456 | { |
454 | sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; | 457 | sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; |
455 | sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT; | 458 | sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT; |
456 | sbp->sb_bad_features2 |= XFS_SB_VERSION2_ATTR2BIT; | ||
457 | } | 459 | } |
458 | 460 | ||
459 | static inline void xfs_sb_version_removeattr2(struct xfs_sb *sbp) | 461 | static inline void xfs_sb_version_removeattr2(struct xfs_sb *sbp) |
460 | { | 462 | { |
461 | sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT; | 463 | sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT; |
462 | sbp->sb_bad_features2 &= ~XFS_SB_VERSION2_ATTR2BIT; | ||
463 | if (!sbp->sb_features2) | 464 | if (!sbp->sb_features2) |
464 | sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT; | 465 | sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT; |
465 | } | 466 | } |
@@ -475,7 +476,6 @@ static inline void xfs_sb_version_addprojid32bit(struct xfs_sb *sbp) | |||
475 | { | 476 | { |
476 | sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; | 477 | sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; |
477 | sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT; | 478 | sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT; |
478 | sbp->sb_bad_features2 |= XFS_SB_VERSION2_PROJID32BIT; | ||
479 | } | 479 | } |
480 | 480 | ||
481 | /* | 481 | /* |
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 63f814872dfb..b0a5fe95a3e2 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c | |||
@@ -497,7 +497,6 @@ xfs_sb_to_disk( | |||
497 | to->sb_fdblocks = cpu_to_be64(from->sb_fdblocks); | 497 | to->sb_fdblocks = cpu_to_be64(from->sb_fdblocks); |
498 | to->sb_frextents = cpu_to_be64(from->sb_frextents); | 498 | to->sb_frextents = cpu_to_be64(from->sb_frextents); |
499 | 499 | ||
500 | |||
501 | to->sb_flags = from->sb_flags; | 500 | to->sb_flags = from->sb_flags; |
502 | to->sb_shared_vn = from->sb_shared_vn; | 501 | to->sb_shared_vn = from->sb_shared_vn; |
503 | to->sb_inoalignmt = cpu_to_be32(from->sb_inoalignmt); | 502 | to->sb_inoalignmt = cpu_to_be32(from->sb_inoalignmt); |
@@ -507,6 +506,13 @@ xfs_sb_to_disk( | |||
507 | to->sb_logsectlog = from->sb_logsectlog; | 506 | to->sb_logsectlog = from->sb_logsectlog; |
508 | to->sb_logsectsize = cpu_to_be16(from->sb_logsectsize); | 507 | to->sb_logsectsize = cpu_to_be16(from->sb_logsectsize); |
509 | to->sb_logsunit = cpu_to_be32(from->sb_logsunit); | 508 | to->sb_logsunit = cpu_to_be32(from->sb_logsunit); |
509 | |||
510 | /* | ||
511 | * We need to ensure that bad_features2 always matches features2. | ||
512 | * Hence we enforce that here rather than having to remember to do it | ||
513 | * everywhere else that updates features2. | ||
514 | */ | ||
515 | from->sb_bad_features2 = from->sb_features2; | ||
510 | to->sb_features2 = cpu_to_be32(from->sb_features2); | 516 | to->sb_features2 = cpu_to_be32(from->sb_features2); |
511 | to->sb_bad_features2 = cpu_to_be32(from->sb_bad_features2); | 517 | to->sb_bad_features2 = cpu_to_be32(from->sb_bad_features2); |
512 | 518 | ||
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 5ef9aa2bfa19..4fa80e63eea2 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -640,25 +640,24 @@ xfs_mountfs( | |||
640 | xfs_sb_mount_common(mp, sbp); | 640 | xfs_sb_mount_common(mp, sbp); |
641 | 641 | ||
642 | /* | 642 | /* |
643 | * Check for a mismatched features2 values. Older kernels | 643 | * Check for a mismatched features2 values. Older kernels read & wrote |
644 | * read & wrote into the wrong sb offset for sb_features2 | 644 | * into the wrong sb offset for sb_features2 on some platforms due to |
645 | * on some platforms due to xfs_sb_t not being 64bit size aligned | 645 | * xfs_sb_t not being 64bit size aligned when sb_features2 was added, |
646 | * when sb_features2 was added, which made older superblock | 646 | * which made older superblock reading/writing routines swap it as a |
647 | * reading/writing routines swap it as a 64-bit value. | 647 | * 64-bit value. |
648 | * | 648 | * |
649 | * For backwards compatibility, we make both slots equal. | 649 | * For backwards compatibility, we make both slots equal. |
650 | * | 650 | * |
651 | * If we detect a mismatched field, we OR the set bits into the | 651 | * If we detect a mismatched field, we OR the set bits into the existing |
652 | * existing features2 field in case it has already been modified; we | 652 | * features2 field in case it has already been modified; we don't want |
653 | * don't want to lose any features. We then update the bad location | 653 | * to lose any features. We then update the bad location with the ORed |
654 | * with the ORed value so that older kernels will see any features2 | 654 | * value so that older kernels will see any features2 flags. The |
655 | * flags, and mark the two fields as needing updates once the | 655 | * superblock writeback code ensures the new sb_features2 is copied to |
656 | * transaction subsystem is online. | 656 | * sb_bad_features2 before it is logged or written to disk. |
657 | */ | 657 | */ |
658 | if (xfs_sb_has_mismatched_features2(sbp)) { | 658 | if (xfs_sb_has_mismatched_features2(sbp)) { |
659 | xfs_warn(mp, "correcting sb_features alignment problem"); | 659 | xfs_warn(mp, "correcting sb_features alignment problem"); |
660 | sbp->sb_features2 |= sbp->sb_bad_features2; | 660 | sbp->sb_features2 |= sbp->sb_bad_features2; |
661 | sbp->sb_bad_features2 = sbp->sb_features2; | ||
662 | mp->m_update_sb = true; | 661 | mp->m_update_sb = true; |
663 | 662 | ||
664 | /* | 663 | /* |