sg: add read/write FUA options
authorKris Davis <Kris.Davis@wdc.com>
Mon, 19 Mar 2018 16:19:44 +0000 (10:19 -0600)
committerJens Axboe <axboe@kernel.dk>
Mon, 19 Mar 2018 16:19:44 +0000 (10:19 -0600)
Enable the user to ask for the FUA bits to be set on read and
write operations.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
HOWTO
engines/sg.c
fio.1
optgroup.h

diff --git a/HOWTO b/HOWTO
index acb9e97fc35bf6ca790d45bb93b7be0260509a8f..dbbbfaa1d839e2d0bd73d91ceb83956c69f8e2c2 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -1747,6 +1747,7 @@ I/O engine
                        :manpage:`read(2)` and :manpage:`write(2)` for asynchronous
                        I/O. Requires :option:`filename` option to specify either block or
                        character devices.
                        :manpage:`read(2)` and :manpage:`write(2)` for asynchronous
                        I/O. Requires :option:`filename` option to specify either block or
                        character devices.
+                       The sg engine includes engine specific options.
 
                **null**
                        Doesn't transfer any data, just pretends to.  This is mainly used to
 
                **null**
                        Doesn't transfer any data, just pretends to.  This is mainly used to
@@ -2068,6 +2069,17 @@ with the caveat that when used on the command line, they must come after the
        multiple paths exist between the client and the server or in certain loopback
        configurations.
 
        multiple paths exist between the client and the server or in certain loopback
        configurations.
 
+.. option:: readfua=bool : [sg]
+
+       With readfua option set to 1, read operations include
+       the force unit access (fua) flag. Default is 0.
+
+.. option:: writefua=bool : [sg]
+
+       With writefua option set to 1, write operations include
+       the force unit access (fua) flag. Default is 0.
+
+
 I/O depth
 ~~~~~~~~~
 
 I/O depth
 ~~~~~~~~~
 
index 4540b57354cd1c1d02e84faa429cd6e069aa376c..f240755595052684864209cdc5b6982a805fcc2d 100644 (file)
 #include <sys/poll.h>
 
 #include "../fio.h"
 #include <sys/poll.h>
 
 #include "../fio.h"
+#include "../optgroup.h"
 
 #ifdef FIO_HAVE_SGIO
 
 
 #ifdef FIO_HAVE_SGIO
 
+
+struct sg_options {
+       void *pad;
+       unsigned int readfua;
+       unsigned int writefua;
+};
+
+static struct fio_option options[] = {
+       {
+               .name   = "readfua",
+               .lname  = "sg engine read fua flag support",
+               .type   = FIO_OPT_BOOL,
+               .off1   = offsetof(struct sg_options, readfua),
+               .help   = "Set FUA flag (force unit access) for all Read operations",
+               .def    = "0",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_SG,
+       },
+       {
+               .name   = "writefua",
+               .lname  = "sg engine write fua flag support",
+               .type   = FIO_OPT_BOOL,
+               .off1   = offsetof(struct sg_options, writefua),
+               .help   = "Set FUA flag (force unit access) for all Write operations",
+               .def    = "0",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_SG,
+       },
+       {
+               .name   = NULL,
+       },
+};
+
 #define MAX_10B_LBA  0xFFFFFFFFULL
 #define SCSI_TIMEOUT_MS 30000   // 30 second timeout; currently no method to override
 #define MAX_SB 64               // sense block maximum return size
 #define MAX_10B_LBA  0xFFFFFFFFULL
 #define SCSI_TIMEOUT_MS 30000   // 30 second timeout; currently no method to override
 #define MAX_SB 64               // sense block maximum return size
@@ -267,6 +301,7 @@ static int fio_sgio_doio(struct thread_data *td, struct io_u *io_u, int do_sync)
 static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u)
 {
        struct sg_io_hdr *hdr = &io_u->hdr;
 static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u)
 {
        struct sg_io_hdr *hdr = &io_u->hdr;
+       struct sg_options *o = td->eo;
        struct sgio_data *sd = td->io_ops_data;
        long long nr_blocks, lba;
 
        struct sgio_data *sd = td->io_ops_data;
        long long nr_blocks, lba;
 
@@ -286,6 +321,10 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u)
                        hdr->cmdp[0] = 0x28; // read(10)
                else
                        hdr->cmdp[0] = 0x88; // read(16)
                        hdr->cmdp[0] = 0x28; // read(10)
                else
                        hdr->cmdp[0] = 0x88; // read(16)
+
+               if (o->readfua)
+                       hdr->cmdp[1] |= 0x08;
+
        } else if (io_u->ddir == DDIR_WRITE) {
                sgio_hdr_init(sd, hdr, io_u, 1);
 
        } else if (io_u->ddir == DDIR_WRITE) {
                sgio_hdr_init(sd, hdr, io_u, 1);
 
@@ -294,6 +333,10 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u)
                        hdr->cmdp[0] = 0x2a; // write(10)
                else
                        hdr->cmdp[0] = 0x8a; // write(16)
                        hdr->cmdp[0] = 0x2a; // write(10)
                else
                        hdr->cmdp[0] = 0x8a; // write(16)
+
+               if (o->writefua)
+                       hdr->cmdp[1] |= 0x08;
+
        } else {
                sgio_hdr_init(sd, hdr, io_u, 0);
                hdr->dxfer_direction = SG_DXFER_NONE;
        } else {
                sgio_hdr_init(sd, hdr, io_u, 0);
                hdr->dxfer_direction = SG_DXFER_NONE;
@@ -822,6 +865,8 @@ static struct ioengine_ops ioengine = {
        .close_file     = generic_close_file,
        .get_file_size  = fio_sgio_get_file_size,
        .flags          = FIO_SYNCIO | FIO_RAWIO,
        .close_file     = generic_close_file,
        .get_file_size  = fio_sgio_get_file_size,
        .flags          = FIO_SYNCIO | FIO_RAWIO,
+       .options        = options,
+       .option_struct_size     = sizeof(struct sg_options)
 };
 
 #else /* FIO_HAVE_SGIO */
 };
 
 #else /* FIO_HAVE_SGIO */
diff --git a/fio.1 b/fio.1
index f955167638d57af97c9ac5e2334a7adb35e80c71..5ca57ce4536787d960e6ee69bbe93d989cec7658 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -1523,7 +1523,7 @@ SCSI generic sg v3 I/O. May either be synchronous using the SG_IO
 ioctl, or if the target is an sg character device we use
 \fBread\fR\|(2) and \fBwrite\fR\|(2) for asynchronous
 I/O. Requires \fBfilename\fR option to specify either block or
 ioctl, or if the target is an sg character device we use
 \fBread\fR\|(2) and \fBwrite\fR\|(2) for asynchronous
 I/O. Requires \fBfilename\fR option to specify either block or
-character devices.
+character devices. The sg engine includes engine specific options.
 .TP
 .B null
 Doesn't transfer any data, just pretends to. This is mainly used to
 .TP
 .B null
 Doesn't transfer any data, just pretends to. This is mainly used to
@@ -1820,6 +1820,14 @@ server side this will be passed into the rdma_bind_addr() function and
 on the client site it will be used in the rdma_resolve_add()
 function. This can be useful when multiple paths exist between the
 client and the server or in certain loopback configurations.
 on the client site it will be used in the rdma_resolve_add()
 function. This can be useful when multiple paths exist between the
 client and the server or in certain loopback configurations.
+.TP
+.BI (sg)readfua \fR=\fPbool
+With readfua option set to 1, read operations include the force
+unit access (fua) flag. Default: 0.
+.TP
+.BI (sg)writefua \fR=\fPbool
+With writefua option set to 1, write operations include the force
+unit access (fua) flag. Default: 0.
 .SS "I/O depth"
 .TP
 .BI iodepth \fR=\fPint
 .SS "I/O depth"
 .TP
 .BI iodepth \fR=\fPint
index 815ac16742cdf526ee959816de3aa9235c93d913..d5e968d4208920dcc8212332066642ecd54ae12b 100644 (file)
@@ -55,10 +55,11 @@ enum opt_category_group {
        __FIO_OPT_G_LIBAIO,
        __FIO_OPT_G_ACT,
        __FIO_OPT_G_LATPROF,
        __FIO_OPT_G_LIBAIO,
        __FIO_OPT_G_ACT,
        __FIO_OPT_G_LATPROF,
-        __FIO_OPT_G_RBD,
-        __FIO_OPT_G_GFAPI,
-        __FIO_OPT_G_MTD,
+       __FIO_OPT_G_RBD,
+       __FIO_OPT_G_GFAPI,
+       __FIO_OPT_G_MTD,
        __FIO_OPT_G_HDFS,
        __FIO_OPT_G_HDFS,
+       __FIO_OPT_G_SG,
        __FIO_OPT_G_NR,
 
        FIO_OPT_G_RATE          = (1ULL << __FIO_OPT_G_RATE),
        __FIO_OPT_G_NR,
 
        FIO_OPT_G_RATE          = (1ULL << __FIO_OPT_G_RATE),
@@ -93,6 +94,7 @@ enum opt_category_group {
        FIO_OPT_G_GFAPI         = (1ULL << __FIO_OPT_G_GFAPI),
        FIO_OPT_G_MTD           = (1ULL << __FIO_OPT_G_MTD),
        FIO_OPT_G_HDFS          = (1ULL << __FIO_OPT_G_HDFS),
        FIO_OPT_G_GFAPI         = (1ULL << __FIO_OPT_G_GFAPI),
        FIO_OPT_G_MTD           = (1ULL << __FIO_OPT_G_MTD),
        FIO_OPT_G_HDFS          = (1ULL << __FIO_OPT_G_HDFS),
+       FIO_OPT_G_SG            = (1ULL << __FIO_OPT_G_SG),
        FIO_OPT_G_INVALID       = (1ULL << __FIO_OPT_G_NR),
 };
 
        FIO_OPT_G_INVALID       = (1ULL << __FIO_OPT_G_NR),
 };