engines:io_uring: uring_cmd add support for protection info
[fio.git] / engines / io_uring.c
index 4916e3b052c6dccb89290ab9a8ca5e132c5125ae..376a2a270d12ce2239756dcb87b5cacd96d349b5 100644 (file)
@@ -97,6 +97,11 @@ struct ioring_options {
        unsigned int nowait;
        unsigned int force_async;
        unsigned int md_per_io_size;
+       unsigned int pi_act;
+       unsigned int apptag;
+       unsigned int apptag_mask;
+       unsigned int prchk;
+       char *pi_chk;
        enum uring_cmd_type cmd_type;
 };
 
@@ -229,6 +234,46 @@ static struct fio_option options[] = {
                .category = FIO_OPT_C_ENGINE,
                .group  = FIO_OPT_G_IOURING,
        },
+       {
+               .name   = "pi_act",
+               .lname  = "Protection Information Action",
+               .type   = FIO_OPT_BOOL,
+               .off1   = offsetof(struct ioring_options, pi_act),
+               .def    = "1",
+               .help   = "Protection Information Action bit (pi_act=1 or pi_act=0)",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_IOURING,
+       },
+       {
+               .name   = "pi_chk",
+               .lname  = "Protection Information Check",
+               .type   = FIO_OPT_STR_STORE,
+               .off1   = offsetof(struct ioring_options, pi_chk),
+               .def    = NULL,
+               .help   = "Control of Protection Information Checking (pi_chk=GUARD,REFTAG,APPTAG)",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_IOURING,
+       },
+       {
+               .name   = "apptag",
+               .lname  = "Application Tag used in Protection Information",
+               .type   = FIO_OPT_INT,
+               .off1   = offsetof(struct ioring_options, apptag),
+               .def    = "0x1234",
+               .help   = "Application Tag used in Protection Information field (Default: 0x1234)",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_IOURING,
+       },
+       {
+               .name   = "apptag_mask",
+               .lname  = "Application Tag Mask",
+               .type   = FIO_OPT_INT,
+               .off1   = offsetof(struct ioring_options, apptag_mask),
+               .def    = "0xffff",
+               .help   = "Application Tag Mask used with Application Tag (Default: 0xffff)",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_IOURING,
+       },
        {
                .name   = NULL,
        },
@@ -486,6 +531,33 @@ static int fio_ioring_getevents(struct thread_data *td, unsigned int min,
        return r < 0 ? r : events;
 }
 
+static inline void fio_ioring_cmd_nvme_pi(struct thread_data *td,
+                                         struct io_u *io_u)
+{
+       struct ioring_data *ld = td->io_ops_data;
+       struct ioring_options *o = td->eo;
+       struct nvme_uring_cmd *cmd;
+       struct io_uring_sqe *sqe;
+       struct nvme_cmd_ext_io_opts ext_opts = {0};
+       struct nvme_data *data = FILE_ENG_DATA(io_u->file);
+
+       if (io_u->ddir == DDIR_TRIM)
+               return;
+
+       sqe = &ld->sqes[(io_u->index) << 1];
+       cmd = (struct nvme_uring_cmd *)sqe->cmd;
+
+       if (data->pi_type) {
+               if (o->pi_act)
+                       ext_opts.io_flags |= NVME_IO_PRINFO_PRACT;
+               ext_opts.io_flags |= o->prchk;
+               ext_opts.apptag = o->apptag;
+               ext_opts.apptag_mask = o->apptag_mask;
+       }
+
+       fio_nvme_pi_fill(cmd, io_u, &ext_opts);
+}
+
 static inline void fio_ioring_cmdprio_prep(struct thread_data *td,
                                           struct io_u *io_u)
 {
@@ -500,6 +572,7 @@ static enum fio_q_status fio_ioring_queue(struct thread_data *td,
                                          struct io_u *io_u)
 {
        struct ioring_data *ld = td->io_ops_data;
+       struct ioring_options *o = td->eo;
        struct io_sq_ring *ring = &ld->sq_ring;
        unsigned tail, next_tail;
 
@@ -527,6 +600,10 @@ static enum fio_q_status fio_ioring_queue(struct thread_data *td,
        if (ld->cmdprio.mode != CMDPRIO_MODE_NONE)
                fio_ioring_cmdprio_prep(td, io_u);
 
+       if (!strcmp(td->io_ops->name, "io_uring_cmd") &&
+               o->cmd_type == FIO_URING_CMD_NVME)
+               fio_ioring_cmd_nvme_pi(td, io_u);
+
        ring->array[tail & ld->sq_ring_mask] = io_u->index;
        atomic_store_release(ring->tail, next_tail);
 
@@ -1025,6 +1102,19 @@ static int fio_ioring_cmd_post_init(struct thread_data *td)
        return 0;
 }
 
+static void parse_prchk_flags(struct ioring_options *o)
+{
+       if (!o->pi_chk)
+               return;
+
+       if (strstr(o->pi_chk, "GUARD") != NULL)
+               o->prchk = NVME_IO_PRINFO_PRCHK_GUARD;
+       if (strstr(o->pi_chk, "REFTAG") != NULL)
+               o->prchk |= NVME_IO_PRINFO_PRCHK_REF;
+       if (strstr(o->pi_chk, "APPTAG") != NULL)
+               o->prchk |= NVME_IO_PRINFO_PRCHK_APP;
+}
+
 static int fio_ioring_init(struct thread_data *td)
 {
        struct ioring_options *o = td->eo;
@@ -1071,6 +1161,7 @@ static int fio_ioring_init(struct thread_data *td)
                        return 1;
                }
        }
+       parse_prchk_flags(o);
 
        ld->iovecs = calloc(td->o.iodepth, sizeof(struct iovec));
 
@@ -1139,7 +1230,7 @@ static int fio_ioring_cmd_open_file(struct thread_data *td, struct fio_file *f)
                data = FILE_ENG_DATA(f);
                if (data == NULL) {
                        data = calloc(1, sizeof(struct nvme_data));
-                       ret = fio_nvme_get_info(f, &nlba, data);
+                       ret = fio_nvme_get_info(f, &nlba, o->pi_act, data);
                        if (ret) {
                                free(data);
                                return ret;
@@ -1225,7 +1316,7 @@ static int fio_ioring_cmd_get_file_size(struct thread_data *td,
                int ret;
 
                data = calloc(1, sizeof(struct nvme_data));
-               ret = fio_nvme_get_info(f, &nlba, data);
+               ret = fio_nvme_get_info(f, &nlba, o->pi_act, data);
                if (ret) {
                        free(data);
                        return ret;