teach iomap_dio_rw() to suppress dsync
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 7 Jun 2022 20:04:03 +0000 (16:04 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 10 Jun 2022 20:03:35 +0000 (16:03 -0400)
New flag, equivalent to removal of IOCB_DSYNC from iocb flags.
This mimics what btrfs is doing (and that's what btrfs will
switch to).  However, I'm not at all sure that we want to
suppress REQ_FUA for those - all btrfs hack really cares about
is suppression of generic_write_sync().  For now let's keep
the existing behaviour, but I really want to hear more detailed
arguments pro or contra.

[folded brain fix from willy]

Suggested-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/iomap/direct-io.c
include/linux/iomap.h

index 370c3241618a091bb5800a75dc638ef024d54a17..c10c69e2de240cf70b74994983e67b51fa99e2eb 100644 (file)
@@ -548,17 +548,19 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                }
 
                /* for data sync or sync, we need sync completion processing */
-               if (iocb->ki_flags & IOCB_DSYNC)
+               if (iocb->ki_flags & IOCB_DSYNC &&
+                   !(dio_flags & IOMAP_DIO_NOSYNC)) {
                        dio->flags |= IOMAP_DIO_NEED_SYNC;
 
-               /*
-                * For datasync only writes, we optimistically try using FUA for
-                * this IO.  Any non-FUA write that occurs will clear this flag,
-                * hence we know before completion whether a cache flush is
-                * necessary.
-                */
-               if ((iocb->ki_flags & (IOCB_DSYNC | IOCB_SYNC)) == IOCB_DSYNC)
-                       dio->flags |= IOMAP_DIO_WRITE_FUA;
+                      /*
+                       * For datasync only writes, we optimistically try
+                       * using FUA for this IO.  Any non-FUA write that
+                       * occurs will clear this flag, hence we know before
+                       * completion whether a cache flush is necessary.
+                       */
+                       if (!(iocb->ki_flags & IOCB_SYNC))
+                               dio->flags |= IOMAP_DIO_WRITE_FUA;
+               }
        }
 
        if (dio_flags & IOMAP_DIO_OVERWRITE_ONLY) {
index e552097c67e0bb3bd659e7ebf9683046131e01ae..c8622d8f064ec4fdced09fcbd67717dedbe65644 100644 (file)
@@ -353,6 +353,12 @@ struct iomap_dio_ops {
  */
 #define IOMAP_DIO_PARTIAL              (1 << 2)
 
+/*
+ * The caller will sync the write if needed; do not sync it within
+ * iomap_dio_rw.  Overrides IOMAP_DIO_FORCE_WAIT.
+ */
+#define IOMAP_DIO_NOSYNC               (1 << 3)
+
 ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
                unsigned int dio_flags, void *private, size_t done_before);