xfs: fix zero byte checking in the superblock scrubber
BugLink: https://bugs.launchpad.net/bugs/2102266
commit c004a793e0ec34047c3bd423bcd8966f5fac88dc upstream.
The logic to check that the region past the end of the superblock is all
zeroes is wrong -- we don't want to check only the bytes past the end of
the maximally sized ondisk superblock structure as currently defined in
xfs_format.h; we want to check the bytes beyond the end of the ondisk as
defined by the feature bits.
Port the superblock size logic from xfs_repair and then put it to use in
xfs_scrub.
Cc: <stable@vger.kernel.org> # v4.15
Fixes: 21fb4cb198 ("xfs: scrub the secondary superblocks")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
Signed-off-by: Mehmet Basaran <mehmet.basaran@canonical.com>
This commit is contained in:
committed by
Mehmet Basaran
parent
1fa9cc36c3
commit
8d3c7a0aba
+27
-2
@@ -58,6 +58,30 @@ xchk_superblock_xref(
|
||||
/* scrub teardown will take care of sc->sa for us */
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the ondisk superblock size in bytes given the feature set of the
|
||||
* mounted filesystem (aka the primary sb). This is subtlely different from
|
||||
* the logic in xfs_repair, which computes the size of a secondary sb given the
|
||||
* featureset listed in the secondary sb.
|
||||
*/
|
||||
STATIC size_t
|
||||
xchk_superblock_ondisk_size(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
if (xfs_has_metauuid(mp))
|
||||
return offsetofend(struct xfs_dsb, sb_meta_uuid);
|
||||
if (xfs_has_crc(mp))
|
||||
return offsetofend(struct xfs_dsb, sb_lsn);
|
||||
if (xfs_sb_version_hasmorebits(&mp->m_sb))
|
||||
return offsetofend(struct xfs_dsb, sb_bad_features2);
|
||||
if (xfs_has_logv2(mp))
|
||||
return offsetofend(struct xfs_dsb, sb_logsunit);
|
||||
if (xfs_has_sector(mp))
|
||||
return offsetofend(struct xfs_dsb, sb_logsectsize);
|
||||
/* only support dirv2 or more recent */
|
||||
return offsetofend(struct xfs_dsb, sb_dirblklog);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scrub the filesystem superblock.
|
||||
*
|
||||
@@ -74,6 +98,7 @@ xchk_superblock(
|
||||
struct xfs_buf *bp;
|
||||
struct xfs_dsb *sb;
|
||||
struct xfs_perag *pag;
|
||||
size_t sblen;
|
||||
xfs_agnumber_t agno;
|
||||
uint32_t v2_ok;
|
||||
__be32 features_mask;
|
||||
@@ -350,8 +375,8 @@ xchk_superblock(
|
||||
}
|
||||
|
||||
/* Everything else must be zero. */
|
||||
if (memchr_inv(sb + 1, 0,
|
||||
BBTOB(bp->b_length) - sizeof(struct xfs_dsb)))
|
||||
sblen = xchk_superblock_ondisk_size(mp);
|
||||
if (memchr_inv((char *)sb + sblen, 0, BBTOB(bp->b_length) - sblen))
|
||||
xchk_block_set_corrupt(sc, bp);
|
||||
|
||||
xchk_superblock_xref(sc, bp);
|
||||
|
||||
Reference in New Issue
Block a user