Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: create a predicate to verify per-AG extents

Create a predicate function to verify that a given agbno/blockcount pair
fit entirely within a single allocation group and don't suffer
mathematical overflows. Refactor the existng open-coded logic; we're
going to add more calls to this function in the next patch.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>

+24 -26
+15
fs/xfs/libxfs/xfs_ag.h
··· 133 133 return true; 134 134 } 135 135 136 + static inline bool 137 + xfs_verify_agbext( 138 + struct xfs_perag *pag, 139 + xfs_agblock_t agbno, 140 + xfs_agblock_t len) 141 + { 142 + if (agbno + len <= agbno) 143 + return false; 144 + 145 + if (!xfs_verify_agbno(pag, agbno)) 146 + return false; 147 + 148 + return xfs_verify_agbno(pag, agbno + len - 1); 149 + } 150 + 136 151 /* 137 152 * Verify that an AG inode number pointer neither points outside the AG 138 153 * nor points at static metadata.
+1 -5
fs/xfs/libxfs/xfs_alloc.c
··· 263 263 goto out_bad_rec; 264 264 265 265 /* check for valid extent range, including overflow */ 266 - if (!xfs_verify_agbno(pag, *bno)) 267 - goto out_bad_rec; 268 - if (*bno > *bno + *len) 269 - goto out_bad_rec; 270 - if (!xfs_verify_agbno(pag, *bno + *len - 1)) 266 + if (!xfs_verify_agbext(pag, *bno, *len)) 271 267 goto out_bad_rec; 272 268 273 269 return 0;
+1 -5
fs/xfs/libxfs/xfs_refcount.c
··· 135 135 } 136 136 137 137 /* check for valid extent range, including overflow */ 138 - if (!xfs_verify_agbno(pag, realstart)) 139 - goto out_bad_rec; 140 - if (realstart > realstart + irec->rc_blockcount) 141 - goto out_bad_rec; 142 - if (!xfs_verify_agbno(pag, realstart + irec->rc_blockcount - 1)) 138 + if (!xfs_verify_agbext(pag, realstart, irec->rc_blockcount)) 143 139 goto out_bad_rec; 144 140 145 141 if (irec->rc_refcount == 0 || irec->rc_refcount > MAXREFCOUNT)
+2 -7
fs/xfs/libxfs/xfs_rmap.c
··· 235 235 goto out_bad_rec; 236 236 } else { 237 237 /* check for valid extent range, including overflow */ 238 - if (!xfs_verify_agbno(pag, irec->rm_startblock)) 239 - goto out_bad_rec; 240 - if (irec->rm_startblock > 241 - irec->rm_startblock + irec->rm_blockcount) 242 - goto out_bad_rec; 243 - if (!xfs_verify_agbno(pag, 244 - irec->rm_startblock + irec->rm_blockcount - 1)) 238 + if (!xfs_verify_agbext(pag, irec->rm_startblock, 239 + irec->rm_blockcount)) 245 240 goto out_bad_rec; 246 241 } 247 242
+1 -3
fs/xfs/scrub/alloc.c
··· 100 100 bno = be32_to_cpu(rec->alloc.ar_startblock); 101 101 len = be32_to_cpu(rec->alloc.ar_blockcount); 102 102 103 - if (bno + len <= bno || 104 - !xfs_verify_agbno(pag, bno) || 105 - !xfs_verify_agbno(pag, bno + len - 1)) 103 + if (!xfs_verify_agbext(pag, bno, len)) 106 104 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 107 105 108 106 xchk_allocbt_xref(bs->sc, bno, len);
+2 -3
fs/xfs/scrub/ialloc.c
··· 108 108 xfs_agblock_t bno; 109 109 110 110 bno = XFS_AGINO_TO_AGBNO(mp, agino); 111 - if (bno + len <= bno || 112 - !xfs_verify_agbno(pag, bno) || 113 - !xfs_verify_agbno(pag, bno + len - 1)) 111 + 112 + if (!xfs_verify_agbext(pag, bno, len)) 114 113 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 115 114 116 115 xchk_iallocbt_chunk_xref(bs->sc, irec, agino, bno, len);
+2 -3
fs/xfs/scrub/refcount.c
··· 354 354 355 355 /* Check the extent. */ 356 356 bno &= ~XFS_REFC_COW_START; 357 - if (bno + len <= bno || 358 - !xfs_verify_agbno(pag, bno) || 359 - !xfs_verify_agbno(pag, bno + len - 1)) 357 + 358 + if (!xfs_verify_agbext(pag, bno, len)) 360 359 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 361 360 362 361 if (refcount == 0)