xfs: only skip rmap owner checks for unknown-owner rmap removal

For rmap removal, refactor the rmap owner checks into a separate
function, then skip the checks if we are performing an unknown-owner
removal.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Darrick J. Wong 2017-12-07 19:07:55 -08:00
parent 33df3a9cf9
commit 68c58e9b9a

View file

@ -367,6 +367,51 @@ xfs_rmap_lookup_le_range(
return error;
}
/*
* 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.
*
@ -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);
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);
/* 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, &ltrec, 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 */