From: Darrick J. Wong Date: Mon, 6 Apr 2020 19:04:25 +0000 (-0700) Subject: xfs: validate the realtime geometry in xfs_validate_sb_common X-Git-Tag: libxfs-5.7-sync_2020-04-28^0 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=19d32c905bd3b14cc5e5448b01fb71ae1b2d8d41;p=xfsprogs-dev.git xfs: validate the realtime geometry in xfs_validate_sb_common Source kernel commit: f8e566c0f5e1fd8de33ccec6eb1ff815cd4b0dc3 Validate the geometry of the realtime geometry when we mount the filesystem, so that we don't abruptly shut down the filesystem later on. Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Darrick J. Wong --- diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index 97e1e32b..885282c8 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -268,6 +268,18 @@ div64_u64_rem( return dividend / divisor; } +static inline uint64_t +div_u64(uint64_t dividend, uint32_t divisor) +{ + return dividend / divisor; +} + +static inline uint64_t +howmany_64(uint64_t dividend, uint32_t divisor) +{ + return div_u64(dividend + divisor - 1, divisor); +} + #define min_t(type,x,y) \ ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) #define max_t(type,x,y) \ diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index e26b9016..d37d60b3 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -325,6 +325,38 @@ xfs_validate_sb_common( return -EFSCORRUPTED; } + /* Validate the realtime geometry; stolen from xfs_repair */ + if (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE || + sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) { + xfs_notice(mp, + "realtime extent sanity check failed"); + return -EFSCORRUPTED; + } + + if (sbp->sb_rblocks == 0) { + if (sbp->sb_rextents != 0 || sbp->sb_rbmblocks != 0 || + sbp->sb_rextslog != 0 || sbp->sb_frextents != 0) { + xfs_notice(mp, + "realtime zeroed geometry check failed"); + return -EFSCORRUPTED; + } + } else { + uint64_t rexts; + uint64_t rbmblocks; + + rexts = div_u64(sbp->sb_rblocks, sbp->sb_rextsize); + rbmblocks = howmany_64(sbp->sb_rextents, + NBBY * sbp->sb_blocksize); + + if (sbp->sb_rextents != rexts || + sbp->sb_rextslog != xfs_highbit32(sbp->sb_rextents) || + sbp->sb_rbmblocks != rbmblocks) { + xfs_notice(mp, + "realtime geometry sanity check failed"); + return -EFSCORRUPTED; + } + } + if (sbp->sb_unit) { if (!xfs_sb_version_hasdalign(sbp) || sbp->sb_unit > sbp->sb_width ||