diff options
| -rw-r--r-- | fs/xfs/libxfs/xfs_rmap.c | 76 | 
1 files changed, 52 insertions, 24 deletions
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 7465cfb39276..50db920ceeeb 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -368,6 +368,51 @@ xfs_rmap_lookup_le_range(  }  /* + * Perform all the relevant owner checks for a removal op.  If we're doing an + * unknown-owner removal then we have no owner information to check. + */ +static int +xfs_rmap_free_check_owner( +	struct xfs_mount	*mp, +	uint64_t		ltoff, +	struct xfs_rmap_irec	*rec, +	xfs_fsblock_t		bno, +	xfs_filblks_t		len, +	uint64_t		owner, +	uint64_t		offset, +	unsigned int		flags) +{ +	int			error = 0; + +	if (owner == XFS_RMAP_OWN_UNKNOWN) +		return 0; + +	/* Make sure the unwritten flag matches. */ +	XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == +			(rec->rm_flags & XFS_RMAP_UNWRITTEN), out); + +	/* Make sure the owner matches what we expect to find in the tree. */ +	XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out); + +	/* Check the offset, if necessary. */ +	if (XFS_RMAP_NON_INODE_OWNER(owner)) +		goto out; + +	if (flags & XFS_RMAP_BMBT_BLOCK) { +		XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK, +				out); +	} else { +		XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out); +		XFS_WANT_CORRUPTED_GOTO(mp, +				ltoff + rec->rm_blockcount >= offset + len, +				out); +	} + +out: +	return error; +} + +/*   * Find the extent in the rmap btree and remove it.   *   * The record we find should always be an exact match for the extent that we're @@ -468,33 +513,16 @@ xfs_rmap_unmap(  			goto out_done;  	} -	/* Make sure the unwritten flag matches. */ -	XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == -			(ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); -  	/* Make sure the extent we found covers the entire freeing range. */  	XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && -		ltrec.rm_startblock + ltrec.rm_blockcount >= -		bno + len, out_error); - -	/* Make sure the owner matches what we expect to find in the tree. */ -	XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner || -				    XFS_RMAP_NON_INODE_OWNER(owner), out_error); +			ltrec.rm_startblock + ltrec.rm_blockcount >= +			bno + len, out_error); -	/* Check the offset, if necessary. */ -	if (!XFS_RMAP_NON_INODE_OWNER(owner)) { -		if (flags & XFS_RMAP_BMBT_BLOCK) { -			XFS_WANT_CORRUPTED_GOTO(mp, -					ltrec.rm_flags & XFS_RMAP_BMBT_BLOCK, -					out_error); -		} else { -			XFS_WANT_CORRUPTED_GOTO(mp, -					ltrec.rm_offset <= offset, out_error); -			XFS_WANT_CORRUPTED_GOTO(mp, -					ltoff + ltrec.rm_blockcount >= offset + len, -					out_error); -		} -	} +	/* Check owner information. */ +	error = xfs_rmap_free_check_owner(mp, ltoff, <rec, bno, len, owner, +			offset, flags); +	if (error) +		goto out_error;  	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {  		/* exact match, simply remove the record from rmap tree */  | 
