]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
xfs: add scrub cross-referencing helpers for the rmap btrees
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 17 Jan 2018 02:52:13 +0000 (18:52 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Thu, 18 Jan 2018 05:00:44 +0000 (21:00 -0800)
Add a couple of functions to the rmap btrees that will be used
to cross-reference metadata against the rmapbt.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/libxfs/xfs_rmap.c
fs/xfs/libxfs/xfs_rmap.h

index 50db920ceeebbf077c2b3b13690066173ba7cf4e..79822cf6ebe36d62b8d912b1b44f5204e0ec1438 100644 (file)
@@ -2387,3 +2387,70 @@ xfs_rmap_compare(
        else
                return 0;
 }
+
+/* Is there a record covering a given extent? */
+int
+xfs_rmap_has_record(
+       struct xfs_btree_cur    *cur,
+       xfs_agblock_t           bno,
+       xfs_extlen_t            len,
+       bool                    *exists)
+{
+       union xfs_btree_irec    low;
+       union xfs_btree_irec    high;
+
+       memset(&low, 0, sizeof(low));
+       low.r.rm_startblock = bno;
+       memset(&high, 0xFF, sizeof(high));
+       high.r.rm_startblock = bno + len - 1;
+
+       return xfs_btree_has_record(cur, &low, &high, exists);
+}
+
+/*
+ * Is there a record for this owner completely covering a given physical
+ * extent?  If so, *has_rmap will be set to true.  If there is no record
+ * or the record only covers part of the range, we set *has_rmap to false.
+ * This function doesn't perform range lookups or offset checks, so it is
+ * not suitable for checking data fork blocks.
+ */
+int
+xfs_rmap_record_exists(
+       struct xfs_btree_cur    *cur,
+       xfs_agblock_t           bno,
+       xfs_extlen_t            len,
+       struct xfs_owner_info   *oinfo,
+       bool                    *has_rmap)
+{
+       uint64_t                owner;
+       uint64_t                offset;
+       unsigned int            flags;
+       int                     has_record;
+       struct xfs_rmap_irec    irec;
+       int                     error;
+
+       xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
+       ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
+              (flags & XFS_RMAP_BMBT_BLOCK));
+
+       error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
+                       &has_record);
+       if (error)
+               return error;
+       if (!has_record) {
+               *has_rmap = false;
+               return 0;
+       }
+
+       error = xfs_rmap_get_rec(cur, &irec, &has_record);
+       if (error)
+               return error;
+       if (!has_record) {
+               *has_rmap = false;
+               return 0;
+       }
+
+       *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
+                    irec.rm_startblock + irec.rm_blockcount >= bno + len);
+       return 0;
+}
index 0fcd5b1ba7295379081e0c61d230324447a8ae56..380e53be98d536f78e456892e250113c3f9bc40d 100644 (file)
@@ -233,5 +233,10 @@ int xfs_rmap_compare(const struct xfs_rmap_irec *a,
 union xfs_btree_rec;
 int xfs_rmap_btrec_to_irec(union xfs_btree_rec *rec,
                struct xfs_rmap_irec *irec);
+int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+               xfs_extlen_t len, bool *exists);
+int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+               xfs_extlen_t len, struct xfs_owner_info *oinfo,
+               bool *has_rmap);
 
 #endif /* __XFS_RMAP_H__ */