]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: add a couple of queries to iterate free extents in the rtbitmap
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 11 May 2017 19:01:07 +0000 (14:01 -0500)
committerEric Sandeen <sandeen@redhat.com>
Thu, 11 May 2017 19:01:07 +0000 (14:01 -0500)
Source kernel commit: fb3c3de2f65c007f3ee50538ea131f5c4603c7bc

Add _query_range and _query_all functions to the realtime bitmap
allocator.  These two functions are similar in usage to the btree
functions with the same name and will be used for getfsmap and scrub.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/libxfs_priv.h
libxfs/xfs_rtbitmap.c

index b96fb4659de5ab7c7b095a568b26b59289b56ef9..0b4c4890b71f2307de157d58d78a5374ce19b174 100644 (file)
@@ -480,6 +480,16 @@ void xfs_verifier_error(struct xfs_buf *bp);
 /* xfs_rtalloc.c */
 int libxfs_rtfree_extent(struct xfs_trans *, xfs_rtblock_t, xfs_extlen_t);
 
+struct xfs_rtalloc_rec {
+       xfs_rtblock_t           ar_startblock;
+       xfs_rtblock_t           ar_blockcount;
+};
+
+typedef int (*xfs_rtalloc_query_range_fn)(
+       struct xfs_trans        *tp,
+       struct xfs_rtalloc_rec  *rec,
+       void                    *priv);
+
 int libxfs_zero_extent(struct xfs_inode *ip, xfs_fsblock_t start_fsb,
                         xfs_off_t count_fsb);
 
index 36fe323b0f8b7603226f13fc3bbd3fc69e0e3738..dbd2f8819ac0058ae8a2b03b51333e88ff7d8334 100644 (file)
@@ -1011,3 +1011,73 @@ xfs_rtfree_extent(
        }
        return 0;
 }
+
+/* Find all the free records within a given range. */
+int
+xfs_rtalloc_query_range(
+       struct xfs_trans                *tp,
+       struct xfs_rtalloc_rec          *low_rec,
+       struct xfs_rtalloc_rec          *high_rec,
+       xfs_rtalloc_query_range_fn      fn,
+       void                            *priv)
+{
+       struct xfs_rtalloc_rec          rec;
+       struct xfs_mount                *mp = tp->t_mountp;
+       xfs_rtblock_t                   rtstart;
+       xfs_rtblock_t                   rtend;
+       xfs_rtblock_t                   rem;
+       int                             is_free;
+       int                             error = 0;
+
+       if (low_rec->ar_startblock > high_rec->ar_startblock)
+               return -EINVAL;
+       else if (low_rec->ar_startblock == high_rec->ar_startblock)
+               return 0;
+
+       /* Iterate the bitmap, looking for discrepancies. */
+       rtstart = low_rec->ar_startblock;
+       rem = high_rec->ar_startblock - rtstart;
+       while (rem) {
+               /* Is the first block free? */
+               error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend,
+                               &is_free);
+               if (error)
+                       break;
+
+               /* How long does the extent go for? */
+               error = xfs_rtfind_forw(mp, tp, rtstart,
+                               high_rec->ar_startblock - 1, &rtend);
+               if (error)
+                       break;
+
+               if (is_free) {
+                       rec.ar_startblock = rtstart;
+                       rec.ar_blockcount = rtend - rtstart + 1;
+
+                       error = fn(tp, &rec, priv);
+                       if (error)
+                               break;
+               }
+
+               rem -= rtend - rtstart + 1;
+               rtstart = rtend + 1;
+       }
+
+       return error;
+}
+
+/* Find all the free records. */
+int
+xfs_rtalloc_query_all(
+       struct xfs_trans                *tp,
+       xfs_rtalloc_query_range_fn      fn,
+       void                            *priv)
+{
+       struct xfs_rtalloc_rec          keys[2];
+
+       keys[0].ar_startblock = 0;
+       keys[1].ar_startblock = tp->t_mountp->m_sb.sb_rblocks;
+       keys[0].ar_blockcount = keys[1].ar_blockcount = 0;
+
+       return xfs_rtalloc_query_range(tp, &keys[0], &keys[1], fn, priv);
+}