|
@@ -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);
|
|
|
-
|
|
|
- /* 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 */
|