diff options
author | Lachlan McIlroy <lachlan@sgi.com> | 2008-03-27 03:01:14 -0400 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-04-17 21:49:51 -0400 |
commit | 2abdb8c88110bab78bfe17e51346e735560daa02 (patch) | |
tree | 0fad752a8f931991f0a788d52aeaaee508c0c3ea /fs | |
parent | 433550990e6c2e94995239bac6a52b4df454cae0 (diff) |
[XFS] Prevent xfs_bmap_check_leaf_extents() referencing unmapped memory.
While investigating the extent corruption bug I ran into this bug in debug
only code. xfs_bmap_check_leaf_extents() loops through the leaf blocks of
the extent btree checking that every extent is entirely before the next
extent. It also compares the last extent in the previous block to the
first extent in the current block when the previous block has been
released and potentially unmapped. So take a copy of the last extent
instead of a pointer. Also move the last extent check out of the loop
because we only need to do it once.
SGI-PV: 976035
SGI-Modid: xfs-linux-melb:xfs-kern:30718a
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index bce8e3bd8ad1..7d683e0b8ef7 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -6194,7 +6194,7 @@ xfs_bmap_check_leaf_extents( | |||
6194 | xfs_mount_t *mp; /* file system mount structure */ | 6194 | xfs_mount_t *mp; /* file system mount structure */ |
6195 | __be64 *pp; /* pointer to block address */ | 6195 | __be64 *pp; /* pointer to block address */ |
6196 | xfs_bmbt_rec_t *ep; /* pointer to current extent */ | 6196 | xfs_bmbt_rec_t *ep; /* pointer to current extent */ |
6197 | xfs_bmbt_rec_t *lastp; /* pointer to previous extent */ | 6197 | xfs_bmbt_rec_t last = {0, 0}; /* last extent in prev block */ |
6198 | xfs_bmbt_rec_t *nextp; /* pointer to next extent */ | 6198 | xfs_bmbt_rec_t *nextp; /* pointer to next extent */ |
6199 | int bp_release = 0; | 6199 | int bp_release = 0; |
6200 | 6200 | ||
@@ -6264,7 +6264,6 @@ xfs_bmap_check_leaf_extents( | |||
6264 | /* | 6264 | /* |
6265 | * Loop over all leaf nodes checking that all extents are in the right order. | 6265 | * Loop over all leaf nodes checking that all extents are in the right order. |
6266 | */ | 6266 | */ |
6267 | lastp = NULL; | ||
6268 | for (;;) { | 6267 | for (;;) { |
6269 | xfs_fsblock_t nextbno; | 6268 | xfs_fsblock_t nextbno; |
6270 | xfs_extnum_t num_recs; | 6269 | xfs_extnum_t num_recs; |
@@ -6285,18 +6284,16 @@ xfs_bmap_check_leaf_extents( | |||
6285 | */ | 6284 | */ |
6286 | 6285 | ||
6287 | ep = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1); | 6286 | ep = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1); |
6287 | if (i) { | ||
6288 | xfs_btree_check_rec(XFS_BTNUM_BMAP, &last, ep); | ||
6289 | } | ||
6288 | for (j = 1; j < num_recs; j++) { | 6290 | for (j = 1; j < num_recs; j++) { |
6289 | nextp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, j + 1); | 6291 | nextp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, j + 1); |
6290 | if (lastp) { | 6292 | xfs_btree_check_rec(XFS_BTNUM_BMAP, ep, nextp); |
6291 | xfs_btree_check_rec(XFS_BTNUM_BMAP, | ||
6292 | (void *)lastp, (void *)ep); | ||
6293 | } | ||
6294 | xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep, | ||
6295 | (void *)(nextp)); | ||
6296 | lastp = ep; | ||
6297 | ep = nextp; | 6293 | ep = nextp; |
6298 | } | 6294 | } |
6299 | 6295 | ||
6296 | last = *ep; | ||
6300 | i += num_recs; | 6297 | i += num_recs; |
6301 | if (bp_release) { | 6298 | if (bp_release) { |
6302 | bp_release = 0; | 6299 | bp_release = 0; |