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 | |
| 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>
| -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 | /* |
