Skip to content

Commit c004a79

Browse files
author
Darrick J. Wong
committed
xfs: fix zero byte checking in the superblock scrubber
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: <[email protected]> # v4.15 Fixes: 21fb4cb ("xfs: scrub the secondary superblocks") Signed-off-by: "Darrick J. Wong" <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent 06b20ef commit c004a79

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

fs/xfs/scrub/agheader.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,32 @@ xchk_superblock_xref(
5959
/* scrub teardown will take care of sc->sa for us */
6060
}
6161

62+
/*
63+
* Calculate the ondisk superblock size in bytes given the feature set of the
64+
* mounted filesystem (aka the primary sb). This is subtlely different from
65+
* the logic in xfs_repair, which computes the size of a secondary sb given the
66+
* featureset listed in the secondary sb.
67+
*/
68+
STATIC size_t
69+
xchk_superblock_ondisk_size(
70+
struct xfs_mount *mp)
71+
{
72+
if (xfs_has_metadir(mp))
73+
return offsetofend(struct xfs_dsb, sb_pad);
74+
if (xfs_has_metauuid(mp))
75+
return offsetofend(struct xfs_dsb, sb_meta_uuid);
76+
if (xfs_has_crc(mp))
77+
return offsetofend(struct xfs_dsb, sb_lsn);
78+
if (xfs_sb_version_hasmorebits(&mp->m_sb))
79+
return offsetofend(struct xfs_dsb, sb_bad_features2);
80+
if (xfs_has_logv2(mp))
81+
return offsetofend(struct xfs_dsb, sb_logsunit);
82+
if (xfs_has_sector(mp))
83+
return offsetofend(struct xfs_dsb, sb_logsectsize);
84+
/* only support dirv2 or more recent */
85+
return offsetofend(struct xfs_dsb, sb_dirblklog);
86+
}
87+
6288
/*
6389
* Scrub the filesystem superblock.
6490
*
@@ -75,6 +101,7 @@ xchk_superblock(
75101
struct xfs_buf *bp;
76102
struct xfs_dsb *sb;
77103
struct xfs_perag *pag;
104+
size_t sblen;
78105
xfs_agnumber_t agno;
79106
uint32_t v2_ok;
80107
__be32 features_mask;
@@ -388,8 +415,8 @@ xchk_superblock(
388415
}
389416

390417
/* Everything else must be zero. */
391-
if (memchr_inv(sb + 1, 0,
392-
BBTOB(bp->b_length) - sizeof(struct xfs_dsb)))
418+
sblen = xchk_superblock_ondisk_size(mp);
419+
if (memchr_inv((char *)sb + sblen, 0, BBTOB(bp->b_length) - sblen))
393420
xchk_block_set_corrupt(sc, bp);
394421

395422
xchk_superblock_xref(sc, bp);

0 commit comments

Comments
 (0)