diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_refcount.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_refcount.c | 174 | 
1 files changed, 126 insertions, 48 deletions
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 9a7fadb1361c..d7d702ee4d1a 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -200,7 +200,10 @@ xfs_refcount_insert(  	error = xfs_btree_insert(cur, i);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, *i != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  out_error:  	if (error) @@ -227,10 +230,16 @@ xfs_refcount_delete(  	error = xfs_refcount_get_rec(cur, &irec, &found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	trace_xfs_refcount_delete(cur->bc_mp, cur->bc_private.a.agno, &irec);  	error = xfs_btree_delete(cur, i); -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, *i != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	if (error)  		goto out_error;  	error = xfs_refcount_lookup_ge(cur, irec.rc_startblock, &found_rec); @@ -349,7 +358,10 @@ xfs_refcount_split_extent(  	error = xfs_refcount_get_rec(cur, &rcext, &found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	if (rcext.rc_startblock == agbno || xfs_refc_next(&rcext) <= agbno)  		return 0; @@ -371,7 +383,10 @@ xfs_refcount_split_extent(  	error = xfs_refcount_insert(cur, &tmp, &found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	return error;  out_error: @@ -410,19 +425,27 @@ xfs_refcount_merge_center_extents(  			&found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	error = xfs_refcount_delete(cur, &found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	if (center->rc_refcount > 1) {  		error = xfs_refcount_delete(cur, &found_rec);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, -				out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  	}  	/* Enlarge the left extent. */ @@ -430,7 +453,10 @@ xfs_refcount_merge_center_extents(  			&found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	left->rc_blockcount = extlen;  	error = xfs_refcount_update(cur, left); @@ -469,14 +495,18 @@ xfs_refcount_merge_left_extent(  				&found_rec);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, -				out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  		error = xfs_refcount_delete(cur, &found_rec);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, -				out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  	}  	/* Enlarge the left extent. */ @@ -484,7 +514,10 @@ xfs_refcount_merge_left_extent(  			&found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	left->rc_blockcount += cleft->rc_blockcount;  	error = xfs_refcount_update(cur, left); @@ -526,14 +559,18 @@ xfs_refcount_merge_right_extent(  			&found_rec);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, -				out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  		error = xfs_refcount_delete(cur, &found_rec);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, -				out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  	}  	/* Enlarge the right extent. */ @@ -541,7 +578,10 @@ xfs_refcount_merge_right_extent(  			&found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	right->rc_startblock -= cright->rc_blockcount;  	right->rc_blockcount += cright->rc_blockcount; @@ -587,7 +627,10 @@ xfs_refcount_find_left_extents(  	error = xfs_refcount_get_rec(cur, &tmp, &found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	if (xfs_refc_next(&tmp) != agbno)  		return 0; @@ -605,8 +648,10 @@ xfs_refcount_find_left_extents(  		error = xfs_refcount_get_rec(cur, &tmp, &found_rec);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, -				out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  		/* if tmp starts at the end of our range, just use that */  		if (tmp.rc_startblock == agbno) @@ -671,7 +716,10 @@ xfs_refcount_find_right_extents(  	error = xfs_refcount_get_rec(cur, &tmp, &found_rec);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	if (tmp.rc_startblock != agbno + aglen)  		return 0; @@ -689,8 +737,10 @@ xfs_refcount_find_right_extents(  		error = xfs_refcount_get_rec(cur, &tmp, &found_rec);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, -				out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  		/* if tmp ends at the end of our range, just use that */  		if (xfs_refc_next(&tmp) == agbno + aglen) @@ -913,8 +963,11 @@ xfs_refcount_adjust_extents(  						&found_tmp);  				if (error)  					goto out_error; -				XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, -						found_tmp == 1, out_error); +				if (XFS_IS_CORRUPT(cur->bc_mp, +						   found_tmp != 1)) { +					error = -EFSCORRUPTED; +					goto out_error; +				}  				cur->bc_private.a.priv.refc.nr_ops++;  			} else {  				fsbno = XFS_AGB_TO_FSB(cur->bc_mp, @@ -955,8 +1008,10 @@ xfs_refcount_adjust_extents(  			error = xfs_refcount_delete(cur, &found_rec);  			if (error)  				goto out_error; -			XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, -					found_rec == 1, out_error); +			if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +				error = -EFSCORRUPTED; +				goto out_error; +			}  			cur->bc_private.a.priv.refc.nr_ops++;  			goto advloop;  		} else { @@ -1122,7 +1177,7 @@ xfs_refcount_finish_one(  				XFS_ALLOC_FLAG_FREEING, &agbp);  		if (error)  			return error; -		if (!agbp) +		if (XFS_IS_CORRUPT(tp->t_mountp, !agbp))  			return -EFSCORRUPTED;  		rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno); @@ -1272,7 +1327,10 @@ xfs_refcount_find_shared(  	error = xfs_refcount_get_rec(cur, &tmp, &i);  	if (error)  		goto out_error; -	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error); +	if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +		error = -EFSCORRUPTED; +		goto out_error; +	}  	/* If the extent ends before the start, look at the next one */  	if (tmp.rc_startblock + tmp.rc_blockcount <= agbno) { @@ -1284,7 +1342,10 @@ xfs_refcount_find_shared(  		error = xfs_refcount_get_rec(cur, &tmp, &i);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  	}  	/* If the extent starts after the range we want, bail out */ @@ -1312,7 +1373,10 @@ xfs_refcount_find_shared(  		error = xfs_refcount_get_rec(cur, &tmp, &i);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  		if (tmp.rc_startblock >= agbno + aglen ||  		    tmp.rc_startblock != *fbno + *flen)  			break; @@ -1413,8 +1477,11 @@ xfs_refcount_adjust_cow_extents(  	switch (adj) {  	case XFS_REFCOUNT_ADJUST_COW_ALLOC:  		/* Adding a CoW reservation, there should be nothing here. */ -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, -				ext.rc_startblock >= agbno + aglen, out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, +				   agbno + aglen > ext.rc_startblock)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  		tmp.rc_startblock = agbno;  		tmp.rc_blockcount = aglen; @@ -1426,17 +1493,25 @@ xfs_refcount_adjust_cow_extents(  				&found_tmp);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, -				found_tmp == 1, out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, found_tmp != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  		break;  	case XFS_REFCOUNT_ADJUST_COW_FREE:  		/* Removing a CoW reservation, there should be one extent. */ -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, -			ext.rc_startblock == agbno, out_error); -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, -			ext.rc_blockcount == aglen, out_error); -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, -			ext.rc_refcount == 1, out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_startblock != agbno)) { +			error = -EFSCORRUPTED; +			goto out_error; +		} +		if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_blockcount != aglen)) { +			error = -EFSCORRUPTED; +			goto out_error; +		} +		if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_refcount != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  		ext.rc_refcount = 0;  		trace_xfs_refcount_modify_extent(cur->bc_mp, @@ -1444,8 +1519,10 @@ xfs_refcount_adjust_cow_extents(  		error = xfs_refcount_delete(cur, &found_rec);  		if (error)  			goto out_error; -		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, -				found_rec == 1, out_error); +		if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { +			error = -EFSCORRUPTED; +			goto out_error; +		}  		break;  	default:  		ASSERT(0); @@ -1584,14 +1661,15 @@ struct xfs_refcount_recovery {  /* Stuff an extent on the recovery list. */  STATIC int  xfs_refcount_recover_extent( -	struct xfs_btree_cur 		*cur, +	struct xfs_btree_cur		*cur,  	union xfs_btree_rec		*rec,  	void				*priv)  {  	struct list_head		*debris = priv;  	struct xfs_refcount_recovery	*rr; -	if (be32_to_cpu(rec->refc.rc_refcount) != 1) +	if (XFS_IS_CORRUPT(cur->bc_mp, +			   be32_to_cpu(rec->refc.rc_refcount) != 1))  		return -EFSCORRUPTED;  	rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), 0);  |