xfs
[Top] [All Lists]

[PATCH V2] xfs: fix crc field handling in xfs_sb_to/from_disk

To: Eric Sandeen <sandeen@xxxxxxxxxx>, xfs-oss <xfs@xxxxxxxxxxx>
Subject: [PATCH V2] xfs: fix crc field handling in xfs_sb_to/from_disk
From: Eric Sandeen <sandeen@xxxxxxxxxxx>
Date: Mon, 09 Jun 2014 16:30:58 -0500
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <5390F89C.2050305@xxxxxxxxxx>
References: <5390F89C.2050305@xxxxxxxxxx>
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:24.0) Gecko/20100101 Thunderbird/24.5.0
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@xxxxxxxxxx>
---

diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c
index 8baf61a..d2ccb2e 100644
--- a/fs/xfs/xfs_sb.c
+++ b/fs/xfs/xfs_sb.c
@@ -450,6 +450,8 @@ xfs_sb_from_disk(
        to->sb_features_incompat = be32_to_cpu(from->sb_features_incompat);
        to->sb_features_log_incompat =
                                be32_to_cpu(from->sb_features_log_incompat);
+       /* crc is only used on disk, not in memory; just init to 0 here. */
+       to->sb_crc = 0;
        to->sb_pad = 0;
        to->sb_pquotino = be64_to_cpu(from->sb_pquotino);
        to->sb_lsn = be64_to_cpu(from->sb_lsn);
@@ -527,6 +529,9 @@ xfs_sb_to_disk(
        if (!fields)
                return;
 
+       /* We should never write the crc here, it's updated in the IO path */
+       fields &= ~XFS_SB_CRC;
+
        xfs_sb_quota_to_disk(to, from, &fields);
        while (fields) {
                f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);

<Prev in Thread] Current Thread [Next in Thread>