]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: refactor xfs_reflink_find_shared
authorChristoph Hellwig <hch@lst.de>
Sat, 10 Aug 2024 08:32:36 +0000 (10:32 +0200)
committerChristoph Hellwig <hch@lst.de>
Mon, 12 Aug 2024 11:53:06 +0000 (13:53 +0200)
Move lookup of the perag structure from the callers into the helpers,
and return the offset into the extent of the shared region instead of
the block number that needs post-processing.  This prepares the
callsites for the creation of an rt-specific variant in the next patch.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
[djwong: port to the middle of the rtreflink series for cleanliness]
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/xfs_reflink.c
fs/xfs/xfs_reflink.h

index 22b7bf5a0782365735147dd026363a71b7aee5d6..ce5bb92d28c740e4550da1f0a43f6d53a24c4f60 100644 (file)
  */
 
 /*
- * Given an AG extent, find the lowest-numbered run of shared blocks
- * within that range and return the range in fbno/flen.  If
- * find_end_of_shared is true, return the longest contiguous extent of
- * shared blocks.  If there are no shared extents, fbno and flen will
- * be set to NULLAGBLOCK and 0, respectively.
+ * Given a file mapping for the data device, find the lowest-numbered run of
+ * shared blocks within that mapping and return it in shared_offset/shared_len.
+ * The offset is relative to the start of irec.
+ *
+ * If find_end_of_shared is true, return the longest contiguous extent of shared
+ * blocks.  If there are no shared extents, shared_offset and shared_len will be
+ * set to 0;
  */
 static int
 xfs_reflink_find_shared(
-       struct xfs_perag        *pag,
+       struct xfs_mount        *mp,
        struct xfs_trans        *tp,
-       xfs_agblock_t           agbno,
-       xfs_extlen_t            aglen,
-       xfs_agblock_t           *fbno,
-       xfs_extlen_t            *flen,
+       const struct xfs_bmbt_irec *irec,
+       xfs_extlen_t            *shared_offset,
+       xfs_extlen_t            *shared_len,
        bool                    find_end_of_shared)
 {
        struct xfs_buf          *agbp;
+       struct xfs_perag        *pag;
        struct xfs_btree_cur    *cur;
        int                     error;
+       xfs_agblock_t           orig_bno, found_bno;
+
+       pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, irec->br_startblock));
+       orig_bno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
 
        error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
        if (error)
                return error;
 
        cur = xfs_refcountbt_init_cursor(pag->pag_mount, tp, agbp, pag);
-
-       error = xfs_refcount_find_shared(cur, agbno, aglen, fbno, flen,
-                       find_end_of_shared);
-
+       error = xfs_refcount_find_shared(cur, orig_bno, irec->br_blockcount,
+                       &found_bno, shared_len, find_end_of_shared);
        xfs_btree_del_cursor(cur, error);
-
        xfs_trans_brelse(tp, agbp);
+       xfs_perag_put(pag);
+
+       if (!error && *shared_len)
+               *shared_offset = found_bno - orig_bno;
        return error;
 }
 
@@ -172,11 +179,7 @@ xfs_reflink_trim_around_shared(
        bool                    *shared)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_perag        *pag;
-       xfs_agblock_t           agbno;
-       xfs_extlen_t            aglen;
-       xfs_agblock_t           fbno;
-       xfs_extlen_t            flen;
+       xfs_extlen_t            shared_offset, shared_len;
        int                     error = 0;
 
        /* Holes, unwritten, and delalloc extents cannot be shared */
@@ -187,41 +190,33 @@ xfs_reflink_trim_around_shared(
 
        trace_xfs_reflink_trim_around_shared(ip, irec);
 
-       pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, irec->br_startblock));
-       agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
-       aglen = irec->br_blockcount;
-
-       error = xfs_reflink_find_shared(pag, NULL, agbno, aglen, &fbno, &flen,
-                       true);
-       xfs_perag_put(pag);
+       error = xfs_reflink_find_shared(mp, NULL, irec, &shared_offset,
+                       &shared_len, true);
        if (error)
                return error;
 
-       *shared = false;
-       if (fbno == NULLAGBLOCK) {
+       if (!shared_len) {
                /* No shared blocks at all. */
-               return 0;
-       }
-
-       if (fbno == agbno) {
+               *shared = false;
+       } else if (!shared_offset) {
                /*
-                * The start of this extent is shared.  Truncate the
-                * mapping at the end of the shared region so that a
-                * subsequent iteration starts at the start of the
-                * unshared region.
+                * The start of this mapping points to shared space.  Truncate
+                * the mapping at the end of the shared region so that a
+                * subsequent iteration starts at the start of the unshared
+                * region.
                 */
-               irec->br_blockcount = flen;
+               irec->br_blockcount = shared_len;
                *shared = true;
-               return 0;
+       } else {
+               /*
+                * There's a shared region that doesn't start at the beginning
+                * of the mapping.  Truncate the mapping at the start of the
+                * shared extent so that a subsequent iteration starts at the
+                * start of the shared region.
+                */
+               irec->br_blockcount = shared_offset;
+               *shared = false;
        }
-
-       /*
-        * There's a shared extent midway through this extent.
-        * Truncate the mapping at the start of the shared
-        * extent so that a subsequent iteration starts at the
-        * start of the shared region.
-        */
-       irec->br_blockcount = fbno - agbno;
        return 0;
 }
 
@@ -1553,27 +1548,19 @@ xfs_reflink_inode_has_shared_extents(
        *has_shared = false;
        found = xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got);
        while (found) {
-               struct xfs_perag        *pag;
-               xfs_agblock_t           agbno;
-               xfs_extlen_t            aglen;
-               xfs_agblock_t           rbno;
-               xfs_extlen_t            rlen;
+               xfs_extlen_t            shared_offset, shared_len;
 
                if (isnullstartblock(got.br_startblock) ||
                    got.br_state != XFS_EXT_NORM)
                        goto next;
 
-               pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, got.br_startblock));
-               agbno = XFS_FSB_TO_AGBNO(mp, got.br_startblock);
-               aglen = got.br_blockcount;
-               error = xfs_reflink_find_shared(pag, tp, agbno, aglen,
-                               &rbno, &rlen, false);
-               xfs_perag_put(pag);
+               error = xfs_reflink_find_shared(mp, tp, &got, &shared_offset,
+                               &shared_len, false);
                if (error)
                        return error;
 
                /* Is there still a shared block here? */
-               if (rbno != NULLAGBLOCK) {
+               if (shared_len) {
                        *has_shared = true;
                        return 0;
                }
index fb55e4ce49fa1019d2c9e6c4224c4bd7ccc55eee..6dd3b0c3b205ea7ec691d826fe4666cc77c74fea 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __XFS_REFLINK_H
 #define __XFS_REFLINK_H 1
 
-extern int xfs_reflink_trim_around_shared(struct xfs_inode *ip,
+int xfs_reflink_trim_around_shared(struct xfs_inode *ip,
                struct xfs_bmbt_irec *irec, bool *shared);
 int xfs_bmap_trim_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *imap,
                bool *shared);