From: Darrick J. Wong <djwong@xxxxxxxxxx> The ondisk format specifies that the start of each realtime group must have a superblock so that rt space mappings never cross an rtgroup boundary. Check that rt block pointers obey this. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_types.c | 46 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c index b1fa715e5f39..34d02b2bfdd1 100644 --- a/fs/xfs/libxfs/xfs_types.c +++ b/fs/xfs/libxfs/xfs_types.c @@ -13,6 +13,8 @@ #include "xfs_mount.h" #include "xfs_ag.h" #include "xfs_imeta.h" +#include "xfs_rtbitmap.h" +#include "xfs_rtgroup.h" /* @@ -133,6 +135,26 @@ xfs_verify_dir_ino( return xfs_verify_ino(mp, ino); } +/* + * Verify that an rtgroup block number pointer neither points outside the + * rtgroup nor points at static metadata. + */ +static inline bool +xfs_verify_rgno_rgbno( + struct xfs_mount *mp, + xfs_rgnumber_t rgno, + xfs_rgblock_t rgbno) +{ + xfs_rgblock_t eorg; + + eorg = xfs_rtgroup_block_count(mp, rgno); + if (rgbno >= eorg) + return false; + if (rgbno < mp->m_sb.sb_rextsize) + return false; + return true; +} + /* * Verify that an realtime block number pointer doesn't point off the * end of the realtime device. @@ -142,7 +164,20 @@ xfs_verify_rtbno( struct xfs_mount *mp, xfs_rtblock_t rtbno) { - return rtbno < mp->m_sb.sb_rblocks; + xfs_rgnumber_t rgno; + xfs_rgblock_t rgbno; + + if (rtbno >= mp->m_sb.sb_rblocks) + return false; + + if (!xfs_has_rtgroups(mp)) + return true; + + rgbno = xfs_rtb_to_rgbno(mp, rtbno, &rgno); + if (rgno >= mp->m_sb.sb_rgcount) + return false; + + return xfs_verify_rgno_rgbno(mp, rgno, rgbno); } /* Verify that a realtime device extent is fully contained inside the volume. */ @@ -158,7 +193,14 @@ xfs_verify_rtbext( if (!xfs_verify_rtbno(mp, rtbno)) return false; - return xfs_verify_rtbno(mp, rtbno + len - 1); + if (!xfs_verify_rtbno(mp, rtbno + len - 1)) + return false; + + if (xfs_has_rtgroups(mp) && + xfs_rtb_to_rgno(mp, rtbno) != xfs_rtb_to_rgno(mp, rtbno + len - 1)) + return false; + + return true; } /* Calculate the range of valid icount values. */