]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
xfs: add a couple of queries to iterate free extents in the rtbitmap
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 28 Mar 2017 21:56:36 +0000 (14:56 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 3 Apr 2017 22:18:17 +0000 (15:18 -0700)
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>
fs/xfs/libxfs/xfs_rtbitmap.c
fs/xfs/xfs_rtalloc.h

index ea45584a9913bbd51908c9a477bb25c90d000fa9..e47b99e59f6035c0bb76a98aa76df998c659348c 100644 (file)
@@ -1016,3 +1016,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);
+}
index 51dd3c7266086d5039e5b77f8ec9ea72c5d95f31..f13133e6f19fa4a25e4359d19d7cadebf5e2b970 100644 (file)
 struct xfs_mount;
 struct xfs_trans;
 
+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);
+
 #ifdef CONFIG_XFS_RT
 /*
  * Function prototypes for exported functions.
@@ -118,13 +128,21 @@ int xfs_rtmodify_summary(struct xfs_mount *mp, struct xfs_trans *tp, int log,
 int xfs_rtfree_range(struct xfs_mount *mp, struct xfs_trans *tp,
                     xfs_rtblock_t start, xfs_extlen_t len,
                     struct xfs_buf **rbpp, xfs_fsblock_t *rsb);
-
-
+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);
+int xfs_rtalloc_query_all(struct xfs_trans *tp,
+                         xfs_rtalloc_query_range_fn fn,
+                         void *priv);
 #else
 # define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb)    (ENOSYS)
 # define xfs_rtfree_extent(t,b,l)                       (ENOSYS)
 # define xfs_rtpick_extent(m,t,l,rb)                    (ENOSYS)
 # define xfs_growfs_rt(mp,in)                           (ENOSYS)
+# define xfs_rtalloc_query_range(t,l,h,f,p)             (ENOSYS)
+# define xfs_rtalloc_query_all(t,f,p)                   (ENOSYS)
 static inline int              /* error */
 xfs_rtmount_init(
        xfs_mount_t     *mp)    /* file system mount structure */