]> www.infradead.org Git - users/hch/xfs.git/commitdiff
iomap: add a merge boundary flag
authorChristoph Hellwig <hch@lst.de>
Wed, 7 Aug 2024 23:03:59 +0000 (16:03 -0700)
committerChristoph Hellwig <hch@lst.de>
Sun, 22 Sep 2024 08:01:25 +0000 (10:01 +0200)
File systems might have boundaries over which merges aren't possible.
In fact these are very common, although most of the time some kind of
header at the beginning of this region (e.g. XFS alloation groups, ext4
block groups) automatically create a merge barrier.  But if that is
not present, say for a device purely used for data we need to manually
communicate that to iomap.

Add a IOMAP_F_BOUNDARY flag to never merge I/O into a previous mapping.

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/iomap/buffered-io.c
include/linux/iomap.h

index f420c53d86acc5753a76c34e0c2a05ff9673f36f..685136a57cbf75921c0c44c1fdb9f3bc3f261871 100644 (file)
@@ -1603,6 +1603,8 @@ iomap_ioend_can_merge(struct iomap_ioend *ioend, struct iomap_ioend *next)
 {
        if (ioend->io_bio.bi_status != next->io_bio.bi_status)
                return false;
+       if (next->io_flags & IOMAP_F_BOUNDARY)
+               return false;
        if ((ioend->io_flags & IOMAP_F_SHARED) ^
            (next->io_flags & IOMAP_F_SHARED))
                return false;
@@ -1722,6 +1724,8 @@ static struct iomap_ioend *iomap_alloc_ioend(struct iomap_writepage_ctx *wpc,
        INIT_LIST_HEAD(&ioend->io_list);
        ioend->io_type = wpc->iomap.type;
        ioend->io_flags = wpc->iomap.flags;
+       if (pos > wpc->iomap.offset)
+               wpc->iomap.flags &= ~IOMAP_F_BOUNDARY;
        ioend->io_inode = inode;
        ioend->io_size = 0;
        ioend->io_offset = pos;
@@ -1733,6 +1737,8 @@ static struct iomap_ioend *iomap_alloc_ioend(struct iomap_writepage_ctx *wpc,
 
 static bool iomap_can_add_to_ioend(struct iomap_writepage_ctx *wpc, loff_t pos)
 {
+       if (wpc->iomap.offset == pos && (wpc->iomap.flags & IOMAP_F_BOUNDARY))
+               return false;
        if ((wpc->iomap.flags & IOMAP_F_SHARED) !=
            (wpc->ioend->io_flags & IOMAP_F_SHARED))
                return false;
index 6fc1c858013d1e4dda4ed38fa4083acf25d16d36..ba3c9e512463760038a9bf9dc37dd3ada08b377e 100644 (file)
@@ -53,6 +53,9 @@ struct vm_fault;
  *
  * IOMAP_F_XATTR indicates that the iomap is for an extended attribute extent
  * rather than a file data extent.
+ *
+ * IOMAP_F_BOUNDARY indicates that I/O and I/O completions for this iomap must
+ * never be merged with the mapping before it.
  */
 #define IOMAP_F_NEW            (1U << 0)
 #define IOMAP_F_DIRTY          (1U << 1)
@@ -64,6 +67,7 @@ struct vm_fault;
 #define IOMAP_F_BUFFER_HEAD    0
 #endif /* CONFIG_BUFFER_HEAD */
 #define IOMAP_F_XATTR          (1U << 5)
+#define IOMAP_F_BOUNDARY       (1U << 6)
 
 /*
  * Flags set by the core iomap code during operations: