Skip to content

Commit

Permalink
xfs: only skip rmap owner checks for unknown-owner rmap removal
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
  • Loading branch information
djwong committed Dec 21, 2017
1 parent 33df3a9 commit 68c58e9
Showing 1 changed file with 52 additions and 24 deletions.
76 changes: 52 additions & 24 deletions fs/xfs/libxfs/xfs_rmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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, &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 */
Expand Down

0 comments on commit 68c58e9

Please sign in to comment.