]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: move cow_replace_mapping to xfs_bmap_util.c
authorDarrick J. Wong <djwong@kernel.org>
Tue, 14 Jul 2026 06:04:39 +0000 (23:04 -0700)
committerCarlos Maiolino <cem@kernel.org>
Tue, 14 Jul 2026 09:01:47 +0000 (11:01 +0200)
Move the actual details of (partially) replacing a COW fork mapping to
xfs_bmap_util.c so that all the code doing hairy operations on subsets
of bmbt_irecs are kept together.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
fs/xfs/scrub/cow_repair.c
fs/xfs/scrub/trace.h
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_bmap_util.h
fs/xfs/xfs_trace.h

index 511a761dca9fe362bebb43ec402cd2abc048cd08..8dd9c0266e21694203c1199689f1293c44464765 100644 (file)
@@ -29,6 +29,7 @@
 #include "xfs_rtalloc.h"
 #include "xfs_rtbitmap.h"
 #include "xfs_rtgroup.h"
+#include "xfs_bmap_util.h"
 #include "scrub/xfs_scrub.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
@@ -537,98 +538,6 @@ bad:
        return -EFSCORRUPTED;
 }
 
-#define REPLACE_LEFT_SIDE      (1U << 0)
-#define REPLACE_RIGHT_SIDE     (1U << 1)
-
-/*
- * Given a CoW fork mapping @got and a replacement mapping @rep, map the space
- * described by @rep into the cow fork, pushing aside @got as necessary.  @icur
- * must point to iext tree leaf containing @got.
- */
-static inline void
-xrep_cow_replace_mapping(
-       struct xfs_inode        *ip,
-       struct xfs_iext_cursor  *icur,
-       struct xfs_bmbt_irec    *got,
-       struct xfs_bmbt_irec    *rep)
-{
-       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK);
-       xfs_fileoff_t           rep_endoff =
-                       rep->br_startoff + rep->br_blockcount;
-       xfs_fileoff_t           got_endoff =
-                       got->br_startoff + got->br_blockcount;
-       uint32_t                state = BMAP_COWFORK;
-
-       ASSERT(rep->br_blockcount > 0);
-       ASSERT(!isnullstartblock(got->br_startblock));
-       ASSERT(got->br_startoff <= rep->br_startoff);
-       ASSERT(got_endoff >= rep_endoff);
-
-       trace_xrep_cow_replace_mapping(ip, got, rep);
-
-       if (got->br_startoff == rep->br_startoff)
-               state |= BMAP_LEFT_FILLING;
-       if (got_endoff == rep_endoff)
-               state |= BMAP_RIGHT_FILLING;
-
-       switch (state & (BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING)) {
-       case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING:
-               /*
-                * Replacement matches the whole mapping, update the record.
-                */
-               xfs_iext_update_extent(ip, state, icur, rep);
-               break;
-       case BMAP_LEFT_FILLING:
-               /*
-                * Replace the first part of the mapping: Update the cursor
-                * position with the new mapping, then add a record with the
-                * tail of the old mapping.
-                */
-               got->br_startoff = rep_endoff;
-               got->br_blockcount -= rep->br_blockcount;
-               got->br_startblock += rep->br_blockcount;
-
-               xfs_iext_update_extent(ip, state, icur, rep);
-               xfs_iext_next(ifp, icur);
-               xfs_iext_insert(ip, icur, got, state);
-               break;
-       case BMAP_RIGHT_FILLING:
-               /*
-                * Replacing the last part of the mapping.  Shorten the current
-                * mapping then add a record with the new mapping.
-                */
-               got->br_blockcount -= rep->br_blockcount;
-
-               xfs_iext_update_extent(ip, state, icur, got);
-               xfs_iext_next(ifp, icur);
-               xfs_iext_insert(ip, icur, rep, state);
-               break;
-       case 0:
-               /*
-                * Replacing the middle of the extent.  Shorten the current
-                * mapping, add a new record with the new mapping, and add a
-                * second new record with the tail of the old mapping.
-                */
-               got->br_blockcount = rep->br_startoff - got->br_startoff;
-
-               struct xfs_bmbt_irec    new = {
-                       .br_startoff    = rep_endoff,
-                       .br_blockcount  = got_endoff - rep_endoff,
-                       .br_state       = got->br_state,
-                       .br_startblock  = got->br_startblock +
-                                               rep->br_blockcount +
-                                               got->br_blockcount,
-               };
-
-               xfs_iext_update_extent(ip, state, icur, got);
-               xfs_iext_next(ifp, icur);
-               xfs_iext_insert(ip, icur, rep, state);
-               xfs_iext_next(ifp, icur);
-               xfs_iext_insert(ip, icur, &new, state);
-               break;
-       }
-}
-
 /*
  * Replace the unwritten CoW staging extent backing the given file range with a
  * new space extent that isn't as problematic.
@@ -671,7 +580,7 @@ xrep_cow_replace_range(
         * Replace the old mapping with the new one, and commit the metadata
         * changes made so far.
         */
-       xrep_cow_replace_mapping(sc->ip, &icur, &got, &rep);
+       xfs_bmap_replace_cow_mapping(sc->ip, &icur, &got, &rep);
 
        xfs_inode_set_cowblocks_tag(sc->ip);
        error = xfs_defer_finish(&sc->tp);
index d48a6db5b5f3084819e33ec017a3a9a46cb18e83..d5d39d82749e5ca5daa479f851323eab8c087f32 100644 (file)
@@ -2671,47 +2671,6 @@ TRACE_EVENT(xrep_cow_mark_file_range,
                  __entry->blockcount)
 );
 
-TRACE_EVENT(xrep_cow_replace_mapping,
-       TP_PROTO(struct xfs_inode *ip, const struct xfs_bmbt_irec *got,
-                const struct xfs_bmbt_irec *rep),
-       TP_ARGS(ip, got, rep),
-       TP_STRUCT__entry(
-               __field(dev_t, dev)
-               __field(xfs_ino_t, ino)
-               __field(xfs_fsblock_t, startblock)
-               __field(xfs_fileoff_t, startoff)
-               __field(xfs_filblks_t, blockcount)
-               __field(xfs_exntst_t, state)
-               __field(xfs_fileoff_t, new_startoff)
-               __field(xfs_fsblock_t, new_startblock)
-               __field(xfs_extlen_t, new_blockcount)
-               __field(xfs_exntst_t, new_state)
-       ),
-       TP_fast_assign(
-               __entry->dev = ip->i_mount->m_super->s_dev;
-               __entry->ino = I_INO(ip);
-               __entry->startoff = got->br_startoff;
-               __entry->startblock = got->br_startblock;
-               __entry->blockcount = got->br_blockcount;
-               __entry->state = got->br_state;
-               __entry->new_startoff = rep->br_startoff;
-               __entry->new_startblock = rep->br_startblock;
-               __entry->new_blockcount = rep->br_blockcount;
-               __entry->new_state = rep->br_state;
-       ),
-       TP_printk("dev %d:%d ino 0x%llx startoff 0x%llx startblock 0x%llx fsbcount 0x%llx state 0x%x new_startoff 0x%llx new_startblock 0x%llx new_fsbcount 0x%x new_state 0x%x",
-                 MAJOR(__entry->dev), MINOR(__entry->dev),
-                 __entry->ino,
-                 __entry->startoff,
-                 __entry->startblock,
-                 __entry->blockcount,
-                 __entry->state,
-                 __entry->new_startoff,
-                 __entry->new_startblock,
-                 __entry->new_blockcount,
-                 __entry->new_state)
-);
-
 TRACE_EVENT(xrep_cow_free_staging,
        TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno,
                 xfs_extlen_t blockcount),
index 3b9f262f8e9128c3e9e8ab3a229b066b7c0591bd..c88b9ade7389dd42f44388194cd28e00315bc77e 100644 (file)
@@ -1744,3 +1744,92 @@ out_trans_cancel:
        xfs_trans_cancel(tp);
        goto out_unlock_ilock;
 }
+
+/*
+ * Given a CoW fork mapping @got and a replacement mapping @rep, map the space
+ * described by @rep into the cow fork, pushing aside @got as necessary.  @icur
+ * must point to iext tree leaf containing @got.
+ */
+void
+xfs_bmap_replace_cow_mapping(
+       struct xfs_inode        *ip,
+       struct xfs_iext_cursor  *icur,
+       struct xfs_bmbt_irec    *got,
+       struct xfs_bmbt_irec    *rep)
+{
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK);
+       xfs_fileoff_t           rep_endoff =
+                       rep->br_startoff + rep->br_blockcount;
+       xfs_fileoff_t           got_endoff =
+                       got->br_startoff + got->br_blockcount;
+       uint32_t                state = BMAP_COWFORK;
+
+       ASSERT(rep->br_blockcount > 0);
+       ASSERT(!isnullstartblock(got->br_startblock));
+       ASSERT(got->br_startoff <= rep->br_startoff);
+       ASSERT(got_endoff >= rep_endoff);
+
+       trace_xfs_bmap_replace_cow_mapping(ip, got, rep);
+
+       if (got->br_startoff == rep->br_startoff)
+               state |= BMAP_LEFT_FILLING;
+       if (got_endoff == rep_endoff)
+               state |= BMAP_RIGHT_FILLING;
+
+       switch (state & (BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING)) {
+       case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING:
+               /*
+                * Replacement matches the whole mapping, update the record.
+                */
+               xfs_iext_update_extent(ip, state, icur, rep);
+               break;
+       case BMAP_LEFT_FILLING:
+               /*
+                * Replace the first part of the mapping: Update the cursor
+                * position with the new mapping, then add a record with the
+                * tail of the old mapping.
+                */
+               got->br_startoff = rep_endoff;
+               got->br_blockcount -= rep->br_blockcount;
+               got->br_startblock += rep->br_blockcount;
+
+               xfs_iext_update_extent(ip, state, icur, rep);
+               xfs_iext_next(ifp, icur);
+               xfs_iext_insert(ip, icur, got, state);
+               break;
+       case BMAP_RIGHT_FILLING:
+               /*
+                * Replacing the last part of the mapping.  Shorten the current
+                * mapping then add a record with the new mapping.
+                */
+               got->br_blockcount -= rep->br_blockcount;
+
+               xfs_iext_update_extent(ip, state, icur, got);
+               xfs_iext_next(ifp, icur);
+               xfs_iext_insert(ip, icur, rep, state);
+               break;
+       case 0:
+               /*
+                * Replacing the middle of the extent.  Shorten the current
+                * mapping, add a new record with the new mapping, and add a
+                * second new record with the tail of the old mapping.
+                */
+               got->br_blockcount = rep->br_startoff - got->br_startoff;
+
+               struct xfs_bmbt_irec    new = {
+                       .br_startoff    = rep_endoff,
+                       .br_blockcount  = got_endoff - rep_endoff,
+                       .br_state       = got->br_state,
+                       .br_startblock  = got->br_startblock +
+                                               rep->br_blockcount +
+                                               got->br_blockcount,
+               };
+
+               xfs_iext_update_extent(ip, state, icur, got);
+               xfs_iext_next(ifp, icur);
+               xfs_iext_insert(ip, icur, rep, state);
+               xfs_iext_next(ifp, icur);
+               xfs_iext_insert(ip, icur, &new, state);
+               break;
+       }
+}
index c477b33616304006b5400403c03ac4c64703baa3..eaaf094154b9f9e882dc3931b91462fa49e1b290 100644 (file)
@@ -81,4 +81,8 @@ int xfs_bmap_count_blocks(struct xfs_trans *tp, struct xfs_inode *ip,
 int    xfs_flush_unmap_range(struct xfs_inode *ip, xfs_off_t offset,
                              xfs_off_t len);
 
+void xfs_bmap_replace_cow_mapping(struct xfs_inode *ip,
+               struct xfs_iext_cursor *icur, struct xfs_bmbt_irec *got,
+               struct xfs_bmbt_irec *rep);
+
 #endif /* __XFS_BMAP_UTIL_H__ */
index d478693674f9526ad4dc3a13674ecc8d18416ad7..aeb89ac53bf190bc2c947465dfe03d505bf46afc 100644 (file)
@@ -6439,6 +6439,47 @@ TRACE_EVENT(xfs_verify_media_error,
                  __entry->error)
 );
 
+TRACE_EVENT(xfs_bmap_replace_cow_mapping,
+       TP_PROTO(struct xfs_inode *ip, const struct xfs_bmbt_irec *got,
+                const struct xfs_bmbt_irec *rep),
+       TP_ARGS(ip, got, rep),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_fsblock_t, startblock)
+               __field(xfs_fileoff_t, startoff)
+               __field(xfs_filblks_t, blockcount)
+               __field(xfs_exntst_t, state)
+               __field(xfs_fileoff_t, new_startoff)
+               __field(xfs_fsblock_t, new_startblock)
+               __field(xfs_extlen_t, new_blockcount)
+               __field(xfs_exntst_t, new_state)
+       ),
+       TP_fast_assign(
+               __entry->dev = ip->i_mount->m_super->s_dev;
+               __entry->ino = I_INO(ip);
+               __entry->startoff = got->br_startoff;
+               __entry->startblock = got->br_startblock;
+               __entry->blockcount = got->br_blockcount;
+               __entry->state = got->br_state;
+               __entry->new_startoff = rep->br_startoff;
+               __entry->new_startblock = rep->br_startblock;
+               __entry->new_blockcount = rep->br_blockcount;
+               __entry->new_state = rep->br_state;
+       ),
+       TP_printk("dev %d:%d ino 0x%llx startoff 0x%llx startblock 0x%llx fsbcount 0x%llx state 0x%x new_startoff 0x%llx new_startblock 0x%llx new_fsbcount 0x%x new_state 0x%x",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->startoff,
+                 __entry->startblock,
+                 __entry->blockcount,
+                 __entry->state,
+                 __entry->new_startoff,
+                 __entry->new_startblock,
+                 __entry->new_blockcount,
+                 __entry->new_state)
+);
+
 #endif /* _TRACE_XFS_H */
 
 #undef TRACE_INCLUDE_PATH