os: Reintroduce atomic write support
authorJohn Garry <john.g.garry@oracle.com>
Mon, 16 Sep 2024 16:53:40 +0000 (16:53 +0000)
committerJens Axboe <axboe@kernel.dk>
Mon, 16 Sep 2024 18:15:15 +0000 (12:15 -0600)
Previously O_ATOMIC support was added in commit d01612f3ae25 ("Add support
for O_ATOMIC"). But support was removed in commit a25ba6c64fe1 ("Get rid of
O_ATOMIC"), as support was never added in the Linux kernel.

Linux kernel 6.11 will add support for RWF_ATOMIC, which can be supported
for various ioengines. See latest man pages for details.

The plumbing was left in place for thread option oatomic, so that will be
reused.

Add a flag to say whether an engine supports atomic writes, and reject
when oatomic is set for an engine which does not support atomic writes.

This is a change in behaviour, as since commit a25ba6c64fe1 ("Get rid of
O_ATOMIC"), this oatomic has been ignored. However, it is better to tell
the user that their ioengine of choice does not support atomic writes.

Today RWF_ATOMIC is only supported for direct-IO. In future it may be
supported for buffered IO. As such, do not auto-set odirect=1 when
oatomic==1.

Signed-off-by: John Garry <john.g.garry@oracle.com>
Link: https://lore.kernel.org/r/20240916165347.2226763-3-john.g.garry@oracle.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
init.c
ioengines.h
options.c
os/os-linux.h

diff --git a/init.c b/init.c
index 414535ccd43033aea24c9ab618c91e7b8a4671be..bad8b75b4e25aa849a2bcca16f7453d28d27f59d 100644 (file)
--- a/init.c
+++ b/init.c
@@ -855,6 +855,17 @@ static int fixup_options(struct thread_data *td)
                                                        o->max_bs[DDIR_WRITE]);
        }
 
+       if (td->o.oatomic) {
+               if (!td_ioengine_flagged(td, FIO_ATOMICWRITES)) {
+                       log_err("fio: engine does not support atomic writes\n");
+                       td->o.oatomic = 0;
+                       ret |= 1;
+               }
+
+               if (!td_write(td))
+                       td->o.oatomic = 0;
+       }
+
        if (o->pre_read) {
                if (o->invalidate_cache)
                        o->invalidate_cache = 0;
index b9834fec3ce4ca397c710b4f909c12f7de3a576e..1531cd897739ae61805746b96555b76ff74fc8f7 100644 (file)
@@ -96,6 +96,7 @@ enum {
        __FIO_RO_NEEDS_RW_OPEN,         /* open files in rw mode even if we have a read job; only
                                           affects ioengines using generic_open_file */
        __FIO_MULTI_RANGE_TRIM,         /* ioengine supports trim with more than one range */
+       __FIO_ATOMICWRITES,             /* ioengine supports atomic writes */
        __FIO_IOENGINE_F_LAST,          /* not a real bit; used to count number of bits */
 };
 
@@ -120,6 +121,7 @@ enum fio_ioengine_flags {
        FIO_SKIPPABLE_IOMEM_ALLOC       = 1 << __FIO_SKIPPABLE_IOMEM_ALLOC,
        FIO_RO_NEEDS_RW_OPEN            = 1 << __FIO_RO_NEEDS_RW_OPEN,
        FIO_MULTI_RANGE_TRIM            = 1 << __FIO_MULTI_RANGE_TRIM,
+       FIO_ATOMICWRITES                = 1 << __FIO_ATOMICWRITES,
 };
 
 /*
index 5a6b0a06676501e4c09571347724131fd9f89849..95567de60b113667012971561b468881d6168f95 100644 (file)
--- a/options.c
+++ b/options.c
@@ -2926,6 +2926,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_IO_TYPE,
        },
+#ifdef FIO_HAVE_RWF_ATOMIC
        {
                .name   = "atomic",
                .lname  = "Atomic I/O",
@@ -2936,6 +2937,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_IO_TYPE,
        },
+#endif
        {
                .name   = "buffered",
                .lname  = "Buffered I/O",
index 010a82913eeb62d3b24ea3530a0ff0d523492879..ead8295c4413545324056bdce6f2839e9cb365c1 100644 (file)
@@ -62,6 +62,7 @@
 #define FIO_HAVE_BYTEORDER_FUNCS
 #define FIO_HAVE_PWRITEV2
 #define FIO_HAVE_SHM_ATTACH_REMOVED
+#define FIO_HAVE_RWF_ATOMIC
 
 #ifdef MAP_HUGETLB
 #define FIO_HAVE_MMAP_HUGE