diff options
author | Eric Sandeen <sandeen@sandeen.net> | 2014-10-01 19:24:11 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2014-10-01 19:24:11 -0400 |
commit | 04dd1a0d4b17a71220eae4fb313218f15a49bcdd (patch) | |
tree | b1947cec8a738c5d711b3c6416399080ec145443 /fs/xfs/libxfs | |
parent | 6ee49a20c13b4b4e79a3bba406df8106cff284a1 (diff) |
xfs: fix crc field handling in xfs_sb_to/from_disk
I discovered this in userspace, but the same change applies
to the kernel.
If we xfs_mdrestore an image from a non-crc filesystem, lo
and behold the restored image has gained a CRC:
# db/xfs_metadump.sh -o /dev/sdc1 - | xfs_mdrestore - test.img
# xfs_db -c "sb 0" -c "p crc" /dev/sdc1
crc = 0 (correct)
# xfs_db -c "sb 0" -c "p crc" test.img
crc = 0xb6f8d6a0 (correct)
This is because xfs_sb_from_disk doesn't fill in sb_crc,
but xfs_sb_to_disk(XFS_SB_ALL_BITS) does write the in-memory
CRC to disk - so we get uninitialized memory on disk.
Fix this by always initializing sb_crc to 0 when we read
the superblock, and masking out the CRC bit from ALL_BITS
when we write it.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_sb.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 8426e5e2682e..5f902fa7913f 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c | |||
@@ -445,6 +445,8 @@ __xfs_sb_from_disk( | |||
445 | to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat); | 445 | to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat); |
446 | to->sb_features_log_incompat = | 446 | to->sb_features_log_incompat = |
447 | be32_to_cpu(from->sb_features_log_incompat); | 447 | be32_to_cpu(from->sb_features_log_incompat); |
448 | /* crc is only used on disk, not in memory; just init to 0 here. */ | ||
449 | to->sb_crc = 0; | ||
448 | to->sb_pad = 0; | 450 | to->sb_pad = 0; |
449 | to->sb_pquotino = be64_to_cpu(from->sb_pquotino); | 451 | to->sb_pquotino = be64_to_cpu(from->sb_pquotino); |
450 | to->sb_lsn = be64_to_cpu(from->sb_lsn); | 452 | to->sb_lsn = be64_to_cpu(from->sb_lsn); |
@@ -550,6 +552,9 @@ xfs_sb_to_disk( | |||
550 | if (!fields) | 552 | if (!fields) |
551 | return; | 553 | return; |
552 | 554 | ||
555 | /* We should never write the crc here, it's updated in the IO path */ | ||
556 | fields &= ~XFS_SB_CRC; | ||
557 | |||
553 | xfs_sb_quota_to_disk(to, from, &fields); | 558 | xfs_sb_quota_to_disk(to, from, &fields); |
554 | while (fields) { | 559 | while (fields) { |
555 | f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields); | 560 | f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields); |