Skip to content

Commit

Permalink
io_uring: Add 'writetype' option for optional cmds
Browse files Browse the repository at this point in the history
Add a new option 'writetype' to support additional optional Write
command family such as Write Uncorrectable and Write Zeroes in NVMe.
Since we have io_uring_cmd ioengine where we can define the actual
opcode of the command, this option will be used to test NVMe device with
various combination of Write command types.

'writetype' option can be given either 'normal', 'uncor' or 'zeroes'.
'normal' is for normal Write command which is by default, 'uncor' is for
Write Uncorrectable, and the other one is for Write Zeroes.  This should
be used with DDIR_WRITE ddir.

This patch updates command's opcode in fio_ioring_init() to avoid
branches in the I/O hottest path giving opcode value to the
fio_nvme_uring_cmd_prep() as an argument.

Signed-off-by: Minwoo Im <[email protected]>
  • Loading branch information
minwooim committed May 30, 2024
1 parent c284d9b commit 2e9ae80
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 5 deletions.
13 changes: 13 additions & 0 deletions HOWTO.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2430,6 +2430,19 @@ with the caveat that when used on the command line, they must come after the
Specifies the type of uring passthrough command to be used. Supported
value is nvme. Default is nvme.

.. option:: writetype=str : [io_uring_cmd]

Specifies the type of write operation. Defaults to 'normal'.

**normal**
Use normal Write commands for write operations

**uncor**
Use Write Uncorrectable commands for write opreations

**zeroes**
Use Write Zeroes commands for write operations

.. option:: hipri

[io_uring] [io_uring_cmd] [xnvme]
Expand Down
72 changes: 71 additions & 1 deletion engines/io_uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ enum uring_cmd_type {
FIO_URING_CMD_NVME = 1,
};

enum uring_cmd_writetype {
FIO_URING_CMD_WTYPE_NORMAL = 1,
FIO_URING_CMD_WTYPE_UNCOR,
FIO_URING_CMD_WTYPE_ZEROES,
};

struct io_sq_ring {
unsigned *head;
unsigned *tail;
Expand Down Expand Up @@ -83,13 +89,15 @@ struct ioring_data {

struct nvme_dsm *dsm;
uint32_t cdw12_flags[DDIR_RWDIR_CNT];
uint8_t write_opcode;
};

struct ioring_options {
struct thread_data *td;
unsigned int hipri;
unsigned int readfua;
unsigned int writefua;
unsigned int writetype;
struct cmdprio_options cmdprio_options;
unsigned int fixedbufs;
unsigned int registerfiles;
Expand Down Expand Up @@ -158,6 +166,30 @@ static struct fio_option options[] = {
.category = FIO_OPT_C_ENGINE,
.group = FIO_OPT_G_IOURING,
},
{
.name = "writetype",
.lname = "Additional Write commands support (Write Uncorrectable, Write Zeores)",
.type = FIO_OPT_STR,
.off1 = offsetof(struct ioring_options, writetype),
.help = "Issue Write Uncorrectable or Zeroes command instaed of Write command",
.def = "normal",
.posval = {
{ .ival = "normal",
.oval = FIO_URING_CMD_WTYPE_NORMAL,
.help = "Issue Write commands for write operations"
},
{ .ival = "uncor",
.oval = FIO_URING_CMD_WTYPE_UNCOR,
.help = "Issue Write Uncorrectable commands for write operations"
},
{ .ival = "zeroes",
.oval = FIO_URING_CMD_WTYPE_ZEROES,
.help = "Issue Write Zeroes commands for write operations"
},
},
.category = FIO_OPT_C_ENGINE,
.group = FIO_OPT_G_IOURING,
},
{
.name = "fixedbufs",
.lname = "Fixed (pre-mapped) IO buffers",
Expand Down Expand Up @@ -455,7 +487,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, ld->cdw12_flags[io_u->ddir]);
dsm, ld->write_opcode, ld->cdw12_flags[io_u->ddir]);
}

static struct io_u *fio_ioring_event(struct thread_data *td, int event)
Expand Down Expand Up @@ -1243,6 +1275,20 @@ static int fio_ioring_init(struct thread_data *td)
}

if (!strcmp(td->io_ops->name, "io_uring_cmd")) {
if (td_write(td)) {
switch (o->writetype) {
case FIO_URING_CMD_WTYPE_UNCOR:
ld->write_opcode = nvme_cmd_write_uncor;
break;
case FIO_URING_CMD_WTYPE_ZEROES:
ld->write_opcode = nvme_cmd_write_zeroes;
break;
default:
ld->write_opcode = nvme_cmd_write;
break;
}
}

if (o->readfua)
ld->cdw12_flags[DDIR_READ] = 1 << 30;
if (o->writefua)
Expand Down Expand Up @@ -1371,6 +1417,30 @@ static int fio_ioring_cmd_open_file(struct thread_data *td, struct fio_file *f)
td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
return 1;
}

if (o->writetype != FIO_URING_CMD_WTYPE_NORMAL &&
!td_write(td)) {
log_err("%s: 'readwrite=|rw=' has no write\n",
f->file_name);
td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
return 1;
}

if (o->writetype == FIO_URING_CMD_WTYPE_UNCOR &&
!(data->oncs & NVME_ONCS_WRITE_UNCOR_SUPP)) {
log_err("%s: Write Uncorrectable command is not supported\n",
f->file_name);
td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
return 1;
}

if (o->writetype == FIO_URING_CMD_WTYPE_ZEROES &&
!(data->oncs & NVME_ONCS_WRITE_ZEROES_SUPP)) {
log_err("%s: Write Zeroes command is not supported\n",
f->file_name);
td_verror(td, EINVAL, "fio_ioring_cmd_open_file");
return 1;
}
}
if (!ld || !o->registerfiles)
return generic_open_file(td, f);
Expand Down
5 changes: 2 additions & 3 deletions engines/nvme.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,6 @@ void fio_nvme_uring_cmd_trim_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u,
uint8_t *buf_point;
int i;

cmd->opcode = nvme_cmd_dsm;
cmd->nsid = data->nsid;
cmd->cdw11 = NVME_ATTRIBUTE_DEALLOCATE;
cmd->addr = (__u64) (uintptr_t) (&dsm->range[0]);
Expand All @@ -363,7 +362,7 @@ 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,
unsigned int cdw12_flags)
uint8_t write_opcode, unsigned int cdw12_flags)
{
struct nvme_data *data = FILE_ENG_DATA(io_u->file);
__u64 slba;
Expand All @@ -376,7 +375,7 @@ int fio_nvme_uring_cmd_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u,
cmd->opcode = nvme_cmd_read;
break;
case DDIR_WRITE:
cmd->opcode = nvme_cmd_write;
cmd->opcode = write_opcode;
break;
case DDIR_TRIM:
fio_nvme_uring_cmd_trim_prep(cmd, io_u, dsm);
Expand Down
4 changes: 3 additions & 1 deletion engines/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ enum nvme_admin_opcode {
enum nvme_io_opcode {
nvme_cmd_write = 0x01,
nvme_cmd_read = 0x02,
nvme_cmd_write_uncor = 0x04,
nvme_cmd_write_zeroes = 0x08,
nvme_cmd_dsm = 0x09,
nvme_cmd_io_mgmt_recv = 0x12,
nvme_zns_cmd_mgmt_send = 0x79,
Expand Down Expand Up @@ -433,7 +435,7 @@ int fio_nvme_get_info(struct fio_file *f, __u64 *nlba, __u32 pi_act,

int fio_nvme_uring_cmd_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u,
struct iovec *iov, struct nvme_dsm *dsm,
unsigned int cdw12_flags);
uint8_t write_opcode, 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);
Expand Down
17 changes: 17 additions & 0 deletions fio.1
Original file line number Diff line number Diff line change
Expand Up @@ -2230,6 +2230,23 @@ should be used for the polling thread.
Specifies the type of uring passthrough command to be used. Supported
value is nvme. Default is nvme.
.TP
.BI (io_uring_cmd)writetype \fR=\fPstr
Specifies the type of write operation. Defaults to 'normal'.
.RS
.RS
.TP
.B normal
Use normal Write commands for write operations
.TP
.B uncor
Use Write Uncorrectable commands for write opreations
.TP
.B zeroes
Use Write Zeroes commands for write operations
.TP
.RE
.RE
.TP
.BI (libaio)userspace_reap
Normally, with the libaio engine in use, fio will use the
\fBio_getevents\fR\|(3) system call to reap newly returned events. With
Expand Down

0 comments on commit 2e9ae80

Please sign in to comment.