From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Coverity points out that xfs_btree_islastblock calls xfs_btree_check_block, but doesn't act on an error return. This predicate has no answer if the btree is corrupt, so tweak the helper to be able to return errors, and then modify the one call site. Coverity-id: 114069 Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_alloc.c | 7 ++++++- fs/xfs/libxfs/xfs_btree.c | 19 ++++++++++++------- fs/xfs/libxfs/xfs_btree.h | 7 ++++--- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 3a724d80783a..65d870189548 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1560,6 +1560,7 @@ xfs_alloc_ag_vextent_near( int i; /* result code, temporary */ xfs_agblock_t bno; xfs_extlen_t len; + bool is_last; /* handle uninitialized agbno range so caller doesn't have to */ if (!args->min_agbno && !args->max_agbno) @@ -1603,7 +1604,11 @@ xfs_alloc_ag_vextent_near( * block, then we just examine all the entries in that block * that are big enough, and pick the best one. */ - if (xfs_btree_islastblock(acur.cnt, 0)) { + error = xfs_btree_islastblock(acur.cnt, 0, &is_last); + if (error) + goto out; + + if (is_last) { bool allocated = false; error = xfs_alloc_ag_vextent_lastblock(args, &acur, &bno, &len, diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 8ad153bc4dea..37b4fa93085c 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -719,20 +719,25 @@ xfs_btree_get_bufs( /* * Check for the cursor referring to the last block at the given level. */ -int /* 1=is last block, 0=not last block */ +int xfs_btree_islastblock( - xfs_btree_cur_t *cur, /* btree cursor */ - int level) /* level to check */ + xfs_btree_cur_t *cur, + int level, + bool *last) { struct xfs_btree_block *block; /* generic btree block pointer */ - xfs_buf_t *bp; /* buffer containing block */ + struct xfs_buf *bp; /* buffer containing block */ + int error; block = xfs_btree_get_block(cur, level, &bp); - xfs_btree_check_block(cur, block, level, bp); + error = xfs_btree_check_block(cur, block, level, bp); + if (error) + return error; if (cur->bc_flags & XFS_BTREE_LONG_PTRS) - return block->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK); + *last = block->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK); else - return block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK); + *last = block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK); + return 0; } /* diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 6670120cd690..c63da9dd05cc 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -320,10 +320,11 @@ xfs_btree_get_bufs( /* * Check for the cursor referring to the last block at the given level. */ -int /* 1=is last block, 0=not last block */ +int xfs_btree_islastblock( - xfs_btree_cur_t *cur, /* btree cursor */ - int level); /* level to check */ + xfs_btree_cur_t *cur, + int level, + bool *last); /* * Compute first and last byte offsets for the fields given.