Skip to content

Commit

Permalink
xfs: verify icount in superblock write
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Darrick J. Wong committed Jul 31, 2018
1 parent 8756a5a commit 69775fd
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
3 changes: 2 additions & 1 deletion fs/xfs/libxfs/xfs_sb.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,10 @@ xfs_validate_sb_write(
* Carry out additional sb summary counter sanity checks when we write
* the superblock. We skip this in the read validator because there
* 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 ||
!xfs_verify_icount(mp, sbp->sb_icount) ||
sbp->sb_ifree > sbp->sb_icount) {
xfs_warn(mp, "SB summary counter sanity check failed");
return -EFSCORRUPTED;
Expand Down
34 changes: 34 additions & 0 deletions fs/xfs/libxfs/xfs_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,37 @@ xfs_verify_rtbno(
{
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;
}
1 change: 1 addition & 0 deletions fs/xfs/libxfs/xfs_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_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_icount(struct xfs_mount *mp, unsigned long long icount);

#endif /* __XFS_TYPES_H__ */

0 comments on commit 69775fd

Please sign in to comment.