xfs: verify icount in superblock write

Add a helper predicate to check the inode count for sanity, then use it
in the superblock write verifier to inspect sb_icount.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Bill O'Donnell <billodo@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
This commit is contained in:
Darrick J. Wong 2018-07-26 10:10:42 -07:00
parent 8756a5af18
commit 69775fd15d
3 changed files with 37 additions and 1 deletions

View File

@ -154,9 +154,10 @@ xfs_validate_sb_write(
* Carry out additional sb summary counter sanity checks when we write * Carry out additional sb summary counter sanity checks when we write
* the superblock. We skip this in the read validator because there * the superblock. We skip this in the read validator because there
* could be newer superblocks in the log and if the values are garbage * could be newer superblocks in the log and if the values are garbage
* we'll recalculate them at the end of log mount. * even after replay we'll recalculate them at the end of log mount.
*/ */
if (sbp->sb_fdblocks > sbp->sb_dblocks || if (sbp->sb_fdblocks > sbp->sb_dblocks ||
!xfs_verify_icount(mp, sbp->sb_icount) ||
sbp->sb_ifree > sbp->sb_icount) { sbp->sb_ifree > sbp->sb_icount) {
xfs_warn(mp, "SB summary counter sanity check failed"); xfs_warn(mp, "SB summary counter sanity check failed");
return -EFSCORRUPTED; return -EFSCORRUPTED;

View File

@ -171,3 +171,37 @@ xfs_verify_rtbno(
{ {
return rtbno < mp->m_sb.sb_rblocks; return rtbno < mp->m_sb.sb_rblocks;
} }
/* Calculate the range of valid icount values. */
static void
xfs_icount_range(
struct xfs_mount *mp,
unsigned long long *min,
unsigned long long *max)
{
unsigned long long nr_inos = 0;
xfs_agnumber_t agno;
/* root, rtbitmap, rtsum all live in the first chunk */
*min = XFS_INODES_PER_CHUNK;
for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
xfs_agino_t first, last;
xfs_agino_range(mp, agno, &first, &last);
nr_inos += last - first + 1;
}
*max = nr_inos;
}
/* Sanity-checking of inode counts. */
bool
xfs_verify_icount(
struct xfs_mount *mp,
unsigned long long icount)
{
unsigned long long min, max;
xfs_icount_range(mp, &min, &max);
return icount >= min && icount <= max;
}

View File

@ -165,5 +165,6 @@ bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino);
bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino); bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino); bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino);
bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno); bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
bool xfs_verify_icount(struct xfs_mount *mp, unsigned long long icount);
#endif /* __XFS_TYPES_H__ */ #endif /* __XFS_TYPES_H__ */