xfs: add repair helpers for the reverse mapping btree
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 9 May 2018 17:02:02 +0000 (10:02 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 16 May 2018 00:57:05 +0000 (17:57 -0700)
Add a couple of functions to the reverse mapping btree that will be used
to repair 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 f7769ed..c0644f1 100644 (file)
@@ -2032,6 +2032,34 @@ out_error:
        return error;
 }
 
+/* Insert a raw rmap into the rmapbt. */
+int
+xfs_rmap_map_raw(
+       struct xfs_btree_cur    *cur,
+       struct xfs_rmap_irec    *rmap)
+{
+       struct xfs_owner_info   oinfo;
+
+       oinfo.oi_owner = rmap->rm_owner;
+       oinfo.oi_offset = rmap->rm_offset;
+       oinfo.oi_flags = 0;
+       if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
+               oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
+       if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
+               oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
+
+       if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
+               return xfs_rmap_map(cur, rmap->rm_startblock,
+                               rmap->rm_blockcount,
+                               rmap->rm_flags & XFS_RMAP_UNWRITTEN,
+                               &oinfo);
+
+       return xfs_rmap_map_shared(cur, rmap->rm_startblock,
+                       rmap->rm_blockcount,
+                       rmap->rm_flags & XFS_RMAP_UNWRITTEN,
+                       &oinfo);
+}
+
 struct xfs_rmap_query_range_info {
        xfs_rmap_query_range_fn fn;
        void                            *priv;
@@ -2455,3 +2483,56 @@ xfs_rmap_record_exists(
                     irec.rm_startblock + irec.rm_blockcount >= bno + len);
        return 0;
 }
+
+struct xfs_rmap_key_state {
+       uint64_t                        owner;
+       uint64_t                        offset;
+       unsigned int                    flags;
+       bool                            has_rmap;
+};
+
+/* For each rmap given, figure out if it doesn't match the key we want. */
+STATIC int
+xfs_rmap_has_other_keys_helper(
+       struct xfs_btree_cur            *cur,
+       struct xfs_rmap_irec            *rec,
+       void                            *priv)
+{
+       struct xfs_rmap_key_state       *rks = priv;
+
+       if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
+           ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
+               return 0;
+       rks->has_rmap = true;
+       return XFS_BTREE_QUERY_RANGE_ABORT;
+}
+
+/*
+ * Given an extent and some owner info, can we find records overlapping
+ * the extent whose owner info does not match the given owner?
+ */
+int
+xfs_rmap_has_other_keys(
+       struct xfs_btree_cur            *cur,
+       xfs_agblock_t                   bno,
+       xfs_extlen_t                    len,
+       struct xfs_owner_info           *oinfo,
+       bool                            *has_rmap)
+{
+       struct xfs_rmap_irec            low = {0};
+       struct xfs_rmap_irec            high;
+       struct xfs_rmap_key_state       rks;
+       int                             error;
+
+       xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
+       rks.has_rmap = false;
+
+       low.rm_startblock = bno;
+       memset(&high, 0xFF, sizeof(high));
+       high.rm_startblock = bno + len - 1;
+
+       error = xfs_rmap_query_range(cur, &low, &high,
+                       xfs_rmap_has_other_keys_helper, &rks);
+       *has_rmap = rks.has_rmap;
+       return error;
+}
index 380e53b..43e506f 100644 (file)
@@ -238,5 +238,9 @@ int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
 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);
+int xfs_rmap_has_other_keys(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+               xfs_extlen_t len, struct xfs_owner_info *oinfo,
+               bool *has_rmap);
+int xfs_rmap_map_raw(struct xfs_btree_cur *cur, struct xfs_rmap_irec *rmap);
 
 #endif /* __XFS_RMAP_H__ */