xfs: add scrub cross-referencing helpers for the free space btrees
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 17 Jan 2018 02:52:12 +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 free space btrees that will be used
to cross-reference metadata against the bnobt/cntbt, and a generic
btree function that provides the real implementation.

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

index 50ba989..6883a76 100644 (file)
@@ -167,7 +167,7 @@ xfs_alloc_lookup_ge(
  * Lookup the first record less than or equal to [bno, len]
  * in the btree given by cur.
  */
-static int                             /* error */
+int                                    /* error */
 xfs_alloc_lookup_le(
        struct xfs_btree_cur    *cur,   /* btree cursor */
        xfs_agblock_t           bno,    /* starting block of extent */
@@ -2996,3 +2996,22 @@ xfs_verify_fsbno(
                return false;
        return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
 }
+
+/* Is there a record covering a given extent? */
+int
+xfs_alloc_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.a.ar_startblock = bno;
+       memset(&high, 0xFF, sizeof(high));
+       high.a.ar_startblock = bno + len - 1;
+
+       return xfs_btree_has_record(cur, &low, &high, exists);
+}
index 7ba2d12..65a0caf 100644 (file)
@@ -198,6 +198,13 @@ xfs_free_extent(
        enum xfs_ag_resv_type   type);  /* block reservation type */
 
 int                            /* error */
+xfs_alloc_lookup_le(
+       struct xfs_btree_cur    *cur,   /* btree cursor */
+       xfs_agblock_t           bno,    /* starting block of extent */
+       xfs_extlen_t            len,    /* length of extent */
+       int                     *stat); /* success/failure */
+
+int                            /* error */
 xfs_alloc_lookup_ge(
        struct xfs_btree_cur    *cur,   /* btree cursor */
        xfs_agblock_t           bno,    /* starting block of extent */
@@ -237,4 +244,7 @@ bool xfs_verify_agbno(struct xfs_mount *mp, xfs_agnumber_t agno,
                xfs_agblock_t agbno);
 bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
 
+int xfs_alloc_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+               xfs_extlen_t len, bool *exist);
+
 #endif /* __XFS_ALLOC_H__ */
index 2b2be1d..567cff5 100644 (file)
@@ -4998,3 +4998,33 @@ xfs_btree_diff_two_ptrs(
                return (int64_t)be64_to_cpu(a->l) - be64_to_cpu(b->l);
        return (int64_t)be32_to_cpu(a->s) - be32_to_cpu(b->s);
 }
+
+/* If there's an extent, we're done. */
+STATIC int
+xfs_btree_has_record_helper(
+       struct xfs_btree_cur            *cur,
+       union xfs_btree_rec             *rec,
+       void                            *priv)
+{
+       return XFS_BTREE_QUERY_RANGE_ABORT;
+}
+
+/* Is there a record covering a given range of keys? */
+int
+xfs_btree_has_record(
+       struct xfs_btree_cur    *cur,
+       union xfs_btree_irec    *low,
+       union xfs_btree_irec    *high,
+       bool                    *exists)
+{
+       int                     error;
+
+       error = xfs_btree_query_range(cur, low, high,
+                       &xfs_btree_has_record_helper, NULL);
+       if (error == XFS_BTREE_QUERY_RANGE_ABORT) {
+               *exists = true;
+               return 0;
+       }
+       *exists = false;
+       return error;
+}
index 2f13b86..50440b5 100644 (file)
@@ -547,5 +547,7 @@ void xfs_btree_get_keys(struct xfs_btree_cur *cur,
                struct xfs_btree_block *block, union xfs_btree_key *key);
 union xfs_btree_key *xfs_btree_high_key_from_key(struct xfs_btree_cur *cur,
                union xfs_btree_key *key);
+int xfs_btree_has_record(struct xfs_btree_cur *cur, union xfs_btree_irec *low,
+               union xfs_btree_irec *high, bool *exists);
 
 #endif /* __XFS_BTREE_H__ */