From 52b81b7c3b1c9900bf124b6cd0a2cef4a9a1df76 Mon Sep 17 00:00:00 2001 From: Kris Davis Date: Mon, 19 Mar 2018 10:19:44 -0600 Subject: [PATCH] sg: add read/write FUA options Enable the user to ask for the FUA bits to be set on read and write operations. Signed-off-by: Jens Axboe --- HOWTO | 12 ++++++++++++ engines/sg.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ fio.1 | 10 +++++++++- optgroup.h | 8 +++++--- 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/HOWTO b/HOWTO index acb9e97f..dbbbfaa1 100644 --- 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. + The sg engine includes engine specific options. **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. +.. 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 ~~~~~~~~~ diff --git a/engines/sg.c b/engines/sg.c index 4540b573..f2407555 100644 --- a/engines/sg.c +++ b/engines/sg.c @@ -12,9 +12,43 @@ #include #include "../fio.h" +#include "../optgroup.h" #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 @@ -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; + struct sg_options *o = td->eo; 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) + + if (o->readfua) + hdr->cmdp[1] |= 0x08; + } 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) + + if (o->writefua) + hdr->cmdp[1] |= 0x08; + } 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, + .options = options, + .option_struct_size = sizeof(struct sg_options) }; #else /* FIO_HAVE_SGIO */ diff --git a/fio.1 b/fio.1 index f9551676..5ca57ce4 100644 --- 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 -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 @@ -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. +.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 diff --git a/optgroup.h b/optgroup.h index 815ac167..d5e968d4 100644 --- a/optgroup.h +++ b/optgroup.h @@ -55,10 +55,11 @@ enum opt_category_group { __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_SG, __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_SG = (1ULL << __FIO_OPT_G_SG), FIO_OPT_G_INVALID = (1ULL << __FIO_OPT_G_NR), }; -- 2.25.1