diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_btree.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_btree.c | 97 | 
1 files changed, 57 insertions, 40 deletions
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 71de937f9e64..e2cc98931552 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -105,11 +105,10 @@ xfs_btree_check_lblock(  	xfs_failaddr_t		fa;  	fa = __xfs_btree_check_lblock(cur, block, level, bp); -	if (unlikely(XFS_TEST_ERROR(fa != NULL, mp, -			XFS_ERRTAG_BTREE_CHECK_LBLOCK))) { +	if (XFS_IS_CORRUPT(mp, fa != NULL) || +	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK)) {  		if (bp)  			trace_xfs_btree_corrupt(bp, _RET_IP_); -		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);  		return -EFSCORRUPTED;  	}  	return 0; @@ -169,11 +168,10 @@ xfs_btree_check_sblock(  	xfs_failaddr_t		fa;  	fa = __xfs_btree_check_sblock(cur, block, level, bp); -	if (unlikely(XFS_TEST_ERROR(fa != NULL, mp, -			XFS_ERRTAG_BTREE_CHECK_SBLOCK))) { +	if (XFS_IS_CORRUPT(mp, fa != NULL) || +	    XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BTREE_CHECK_SBLOCK)) {  		if (bp)  			trace_xfs_btree_corrupt(bp, _RET_IP_); -		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);  		return -EFSCORRUPTED;  	}  	return 0; @@ -384,7 +382,7 @@ xfs_btree_del_cursor(  	/*  	 * Free the cursor.  	 */ -	kmem_zone_free(xfs_btree_cur_zone, cur); +	kmem_cache_free(xfs_btree_cur_zone, cur);  }  /* @@ -717,25 +715,6 @@ 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 */ -xfs_btree_islastblock( -	xfs_btree_cur_t		*cur,	/* btree cursor */ -	int			level)	/* level to check */ -{ -	struct xfs_btree_block	*block;	/* generic btree block pointer */ -	xfs_buf_t		*bp;	/* buffer containing block */ - -	block = xfs_btree_get_block(cur, level, &bp); -	xfs_btree_check_block(cur, block, level, bp); -	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) -		return block->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK); -	else -		return block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK); -} - -/*   * Change the cursor to point to the first record at the given level.   * Other levels are unaffected.   */ @@ -1820,6 +1799,7 @@ xfs_btree_lookup_get_block(  out_bad:  	*blkp = NULL; +	xfs_buf_corruption_error(bp);  	xfs_trans_brelse(cur->bc_tp, bp);  	return -EFSCORRUPTED;  } @@ -1867,7 +1847,7 @@ xfs_btree_lookup(  	XFS_BTREE_STATS_INC(cur, lookup);  	/* No such thing as a zero-level tree. */ -	if (cur->bc_nlevels == 0) +	if (XFS_IS_CORRUPT(cur->bc_mp, cur->bc_nlevels == 0))  		return -EFSCORRUPTED;  	block = NULL; @@ -1987,7 +1967,8 @@ xfs_btree_lookup(  			error = xfs_btree_increment(cur, 0, &i);  			if (error)  				goto error0; -			XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); +			if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) +				return -EFSCORRUPTED;  			*stat = 1;  			return 0;  		} @@ -2442,7 +2423,10 @@ xfs_btree_lshift(  		if (error)  			goto error0;  		i = xfs_btree_firstrec(tcur, level); -		XFS_WANT_CORRUPTED_GOTO(tcur->bc_mp, i == 1, error0); +		if (XFS_IS_CORRUPT(tcur->bc_mp, i != 1)) { +			error = -EFSCORRUPTED; +			goto error0; +		}  		error = xfs_btree_decrement(tcur, level, &i);  		if (error) @@ -2609,7 +2593,10 @@ xfs_btree_rshift(  	if (error)  		goto error0;  	i = xfs_btree_lastrec(tcur, level); -	XFS_WANT_CORRUPTED_GOTO(tcur->bc_mp, i == 1, error0); +	if (XFS_IS_CORRUPT(tcur->bc_mp, i != 1)) { +		error = -EFSCORRUPTED; +		goto error0; +	}  	error = xfs_btree_increment(tcur, level, &i);  	if (error) @@ -3463,7 +3450,10 @@ xfs_btree_insert(  			goto error0;  		} -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); +		if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +			error = -EFSCORRUPTED; +			goto error0; +		}  		level++;  		/* @@ -3867,15 +3857,24 @@ xfs_btree_delrec(  		 * Actually any entry but the first would suffice.  		 */  		i = xfs_btree_lastrec(tcur, level); -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); +		if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +			error = -EFSCORRUPTED; +			goto error0; +		}  		error = xfs_btree_increment(tcur, level, &i);  		if (error)  			goto error0; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); +		if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +			error = -EFSCORRUPTED; +			goto error0; +		}  		i = xfs_btree_lastrec(tcur, level); -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); +		if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +			error = -EFSCORRUPTED; +			goto error0; +		}  		/* Grab a pointer to the block. */  		right = xfs_btree_get_block(tcur, level, &rbp); @@ -3919,12 +3918,18 @@ xfs_btree_delrec(  		rrecs = xfs_btree_get_numrecs(right);  		if (!xfs_btree_ptr_is_null(cur, &lptr)) {  			i = xfs_btree_firstrec(tcur, level); -			XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); +			if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +				error = -EFSCORRUPTED; +				goto error0; +			}  			error = xfs_btree_decrement(tcur, level, &i);  			if (error)  				goto error0; -			XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); +			if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +				error = -EFSCORRUPTED; +				goto error0; +			}  		}  	} @@ -3938,13 +3943,19 @@ xfs_btree_delrec(  		 * previous block.  		 */  		i = xfs_btree_firstrec(tcur, level); -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); +		if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +			error = -EFSCORRUPTED; +			goto error0; +		}  		error = xfs_btree_decrement(tcur, level, &i);  		if (error)  			goto error0;  		i = xfs_btree_firstrec(tcur, level); -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); +		if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +			error = -EFSCORRUPTED; +			goto error0; +		}  		/* Grab a pointer to the block. */  		left = xfs_btree_get_block(tcur, level, &lbp); @@ -4286,6 +4297,7 @@ int  xfs_btree_visit_blocks(  	struct xfs_btree_cur		*cur,  	xfs_btree_visit_blocks_fn	fn, +	unsigned int			flags,  	void				*data)  {  	union xfs_btree_ptr		lptr; @@ -4311,6 +4323,11 @@ xfs_btree_visit_blocks(  			/* save for the next iteration of the loop */  			xfs_btree_copy_ptrs(cur, &lptr, ptr, 1); + +			if (!(flags & XFS_BTREE_VISIT_LEAVES)) +				continue; +		} else if (!(flags & XFS_BTREE_VISIT_RECORDS)) { +			continue;  		}  		/* for each buffer in the level */ @@ -4413,7 +4430,7 @@ xfs_btree_change_owner(  	bbcoi.buffer_list = buffer_list;  	return xfs_btree_visit_blocks(cur, xfs_btree_block_change_owner, -			&bbcoi); +			XFS_BTREE_VISIT_ALL, &bbcoi);  }  /* Verify the v5 fields of a long-format btree block. */ @@ -4865,7 +4882,7 @@ xfs_btree_count_blocks(  {  	*blocks = 0;  	return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper, -			blocks); +			XFS_BTREE_VISIT_ALL, blocks);  }  /* Compare two btree pointers. */  |