xfs: don't merge ioends across RTGs
authorDarrick J. Wong <djwong@kernel.org>
Mon, 4 Nov 2024 04:19:28 +0000 (20:19 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 5 Nov 2024 21:38:42 +0000 (13:38 -0800)
Unlike AGs, RTGs don't always have metadata in their first blocks, and
thus we don't get automatic protection from merging I/O completions
across RTG boundaries.  Add code to set the IOMAP_F_BOUNDARY flag for
ioends that start at the first block of a RTG so that they never get
merged into the previous ioend.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/libxfs/xfs_rtgroup.h
fs/xfs/xfs_iomap.c

index 026f34f..2ddfac9 100644 (file)
@@ -188,6 +188,15 @@ xfs_rtb_to_rgbno(
        return __xfs_rtb_to_rgbno(mp, rtbno);
 }
 
+/* Is rtbno the start of a RT group? */
+static inline bool
+xfs_rtbno_is_group_start(
+       struct xfs_mount        *mp,
+       xfs_rtblock_t           rtbno)
+{
+       return (rtbno & mp->m_rgblkmask) == 0;
+}
+
 static inline xfs_daddr_t
 xfs_rtb_to_daddr(
        struct xfs_mount        *mp,
index e810e90..17e5c27 100644 (file)
@@ -24,6 +24,7 @@
 #include "xfs_iomap.h"
 #include "xfs_trace.h"
 #include "xfs_quota.h"
+#include "xfs_rtgroup.h"
 #include "xfs_dquot_item.h"
 #include "xfs_dquot.h"
 #include "xfs_reflink.h"
@@ -115,7 +116,9 @@ xfs_bmbt_to_iomap(
                iomap->addr = IOMAP_NULL_ADDR;
                iomap->type = IOMAP_DELALLOC;
        } else {
-               iomap->addr = BBTOB(xfs_fsb_to_db(ip, imap->br_startblock));
+               xfs_daddr_t     daddr = xfs_fsb_to_db(ip, imap->br_startblock);
+
+               iomap->addr = BBTOB(daddr);
                if (mapping_flags & IOMAP_DAX)
                        iomap->addr += target->bt_dax_part_off;
 
@@ -124,6 +127,14 @@ xfs_bmbt_to_iomap(
                else
                        iomap->type = IOMAP_MAPPED;
 
+               /*
+                * Mark iomaps starting at the first sector of a RTG as merge
+                * boundary so that each I/O completions is contained to a
+                * single RTG.
+                */
+               if (XFS_IS_REALTIME_INODE(ip) && xfs_has_rtgroups(mp) &&
+                   xfs_rtbno_is_group_start(mp, imap->br_startblock))
+                       iomap->flags |= IOMAP_F_BOUNDARY;
        }
        iomap->offset = XFS_FSB_TO_B(mp, imap->br_startoff);
        iomap->length = XFS_FSB_TO_B(mp, imap->br_blockcount);