iomap: make buffered writes work with RWF_UNCACHED buffered-uncached.3
authorJens Axboe <axboe@kernel.dk>
Tue, 5 Nov 2024 21:56:16 +0000 (14:56 -0700)
committerJens Axboe <axboe@kernel.dk>
Fri, 8 Nov 2024 03:51:49 +0000 (20:51 -0700)
Add iomap buffered write support for RWF_UNCACHED. If RWF_UNCACHED is
set for a write, mark the folios being written with drop_writeback. Then
writeback completion will drop the pages. The write_iter handler simply
kicks off writeback for the pages, and writeback completion will take
care of the rest.

See the similar patch for the generic filemap handling for performance
results, those were in fact done on XFS using this patch.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/iomap/buffered-io.c
include/linux/iomap.h

index ef0b68bccbb6126e136bffd3d6558a78bc8fc1e4..a81004b66e56f33582c61170e1993cf9f663a859 100644 (file)
@@ -959,6 +959,9 @@ retry:
                }
                if (iter->iomap.flags & IOMAP_F_STALE)
                        break;
+               if (iter->flags & IOMAP_UNCACHED &&
+                   !(iter->iomap.flags & IOMAP_F_BUFFER_HEAD))
+                       folio_set_uncached(folio);
 
                offset = offset_in_folio(folio, pos);
                if (bytes > folio_size(folio) - offset)
@@ -1023,8 +1026,9 @@ ssize_t
 iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *i,
                const struct iomap_ops *ops, void *private)
 {
+       struct address_space *mapping = iocb->ki_filp->f_mapping;
        struct iomap_iter iter = {
-               .inode          = iocb->ki_filp->f_mapping->host,
+               .inode          = mapping->host,
                .pos            = iocb->ki_pos,
                .len            = iov_iter_count(i),
                .flags          = IOMAP_WRITE,
@@ -1034,12 +1038,19 @@ iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *i,
 
        if (iocb->ki_flags & IOCB_NOWAIT)
                iter.flags |= IOMAP_NOWAIT;
+       if (iocb->ki_flags & IOCB_UNCACHED)
+               iter.flags |= IOMAP_UNCACHED;
 
        while ((ret = iomap_iter(&iter, ops)) > 0)
                iter.processed = iomap_write_iter(&iter, i);
 
        if (unlikely(iter.pos == iocb->ki_pos))
                return ret;
+       if (iocb->ki_flags & IOCB_UNCACHED) {
+               /* kick off uncached writeback, completion will drop it */
+               __filemap_fdatawrite_range(mapping, iocb->ki_pos, iter.pos,
+                                               WB_SYNC_NONE);
+       }
        ret = iter.pos - iocb->ki_pos;
        iocb->ki_pos = iter.pos;
        return ret;
index f61407e3b12192d78932d8c7ac737a5161da0bc9..89b24fbb13994ac521089a164ef02f39a9ffacf1 100644 (file)
@@ -173,8 +173,9 @@ struct iomap_folio_ops {
 #define IOMAP_NOWAIT           (1 << 5) /* do not block */
 #define IOMAP_OVERWRITE_ONLY   (1 << 6) /* only pure overwrites allowed */
 #define IOMAP_UNSHARE          (1 << 7) /* unshare_file_range */
+#define IOMAP_UNCACHED         (1 << 8) /* uncached IO */
 #ifdef CONFIG_FS_DAX
-#define IOMAP_DAX              (1 << 8) /* DAX mapping */
+#define IOMAP_DAX              (1 << 9) /* DAX mapping */
 #else
 #define IOMAP_DAX              0
 #endif /* CONFIG_FS_DAX */