diff --git a/HOWTO.rst b/HOWTO.rst index 3b262faeae..0b39a89231 100644 --- a/HOWTO.rst +++ b/HOWTO.rst @@ -2847,12 +2847,12 @@ with the caveat that when used on the command line, they must come after the Specify stat system call type to measure lookup/getattr performance. Default is **stat** for :manpage:`stat(2)`. -.. option:: readfua=bool : [sg] +.. option:: readfua=bool : [sg] [io_uring_cmd] With readfua option set to 1, read operations include the force unit access (fua) flag. Default is 0. -.. option:: writefua=bool : [sg] +.. option:: writefua=bool : [sg] [io_uring_cmd] With writefua option set to 1, write operations include the force unit access (fua) flag. Default is 0. diff --git a/engines/io_uring.c b/engines/io_uring.c index 9069fa3e81..3a03ae3524 100644 --- a/engines/io_uring.c +++ b/engines/io_uring.c @@ -82,11 +82,14 @@ struct ioring_data { struct cmdprio cmdprio; struct nvme_dsm *dsm; + uint32_t cdw12_flags[DDIR_RWDIR_CNT]; }; struct ioring_options { struct thread_data *td; unsigned int hipri; + unsigned int readfua; + unsigned int writefua; struct cmdprio_options cmdprio_options; unsigned int fixedbufs; unsigned int registerfiles; @@ -135,6 +138,26 @@ static struct fio_option options[] = { .category = FIO_OPT_C_ENGINE, .group = FIO_OPT_G_IOURING, }, + { + .name = "readfua", + .lname = "Read fua flag support", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct ioring_options, readfua), + .help = "Set FUA flag (force unit access) for all Read operations", + .def = "0", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_IOURING, + }, + { + .name = "writefua", + .lname = "Write fua flag support", + .type = FIO_OPT_BOOL, + .off1 = offsetof(struct ioring_options, writefua), + .help = "Set FUA flag (force unit access) for all Write operations", + .def = "0", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_IOURING, + }, { .name = "fixedbufs", .lname = "Fixed (pre-mapped) IO buffers", @@ -432,7 +455,7 @@ static int fio_ioring_cmd_prep(struct thread_data *td, struct io_u *io_u) return fio_nvme_uring_cmd_prep(cmd, io_u, o->nonvectored ? NULL : &ld->iovecs[io_u->index], - dsm); + dsm, ld->cdw12_flags[io_u->ddir]); } static struct io_u *fio_ioring_event(struct thread_data *td, int event) @@ -1219,6 +1242,13 @@ static int fio_ioring_init(struct thread_data *td) } } + if (!strcmp(td->io_ops->name, "io_uring_cmd")) { + if (o->readfua) + ld->cdw12_flags[DDIR_READ] = 1 << 30; + if (o->writefua) + ld->cdw12_flags[DDIR_WRITE] = 1 << 30; + } + return 0; } diff --git a/engines/nvme.c b/engines/nvme.c index c6629e8644..7b73c806af 100644 --- a/engines/nvme.c +++ b/engines/nvme.c @@ -362,7 +362,8 @@ void fio_nvme_uring_cmd_trim_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u, } int fio_nvme_uring_cmd_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u, - struct iovec *iov, struct nvme_dsm *dsm) + struct iovec *iov, struct nvme_dsm *dsm, + unsigned int cdw12_flags) { struct nvme_data *data = FILE_ENG_DATA(io_u->file); __u64 slba; @@ -391,7 +392,7 @@ int fio_nvme_uring_cmd_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u, cmd->cdw10 = slba & 0xffffffff; cmd->cdw11 = slba >> 32; /* cdw12 represent number of lba's for read/write */ - cmd->cdw12 = nlb | (io_u->dtype << 20); + cmd->cdw12 = nlb | (io_u->dtype << 20) | cdw12_flags; cmd->cdw13 = io_u->dspec << 16; if (iov) { iov->iov_base = io_u->xfer_buf; diff --git a/engines/nvme.h b/engines/nvme.h index 2d5204fc01..2db9eb86dd 100644 --- a/engines/nvme.h +++ b/engines/nvme.h @@ -426,7 +426,8 @@ int fio_nvme_get_info(struct fio_file *f, __u64 *nlba, __u32 pi_act, struct nvme_data *data); int fio_nvme_uring_cmd_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u, - struct iovec *iov, struct nvme_dsm *dsm); + struct iovec *iov, struct nvme_dsm *dsm, + unsigned int cdw12_flags); void fio_nvme_pi_fill(struct nvme_uring_cmd *cmd, struct io_u *io_u, struct nvme_cmd_ext_io_opts *opts); diff --git a/fio.1 b/fio.1 index 1c8e3a5670..9a965cb090 100644 --- a/fio.1 +++ b/fio.1 @@ -2632,11 +2632,11 @@ that "owns" the device also needs to support hipri (also known as iopoll and mq_poll). The MegaRAID driver is an example of a SCSI LLD. Default: clear (0) which does normal (interrupted based) IO. .TP -.BI (sg)readfua \fR=\fPbool +.BI (sg, io_uring_cmd)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 +.BI (sg, io_uring_cmd)writefua \fR=\fPbool With writefua option set to 1, write operations include the force unit access (fua) flag. Default: 0. .TP