From 16be6037a37a286778bff6e6d27132b776dc8e79 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Date: Tue, 7 Mar 2023 19:51:06 +0530 Subject: [PATCH] io_uring_cmd: suppport for trim operation Add support for trim operation to the io_uring_cmd ioengine. Print ZBD zone reset stats for trim operation. Signed-off-by: Ankit Kumar --- engines/io_uring.c | 31 ++++++++++++++++++++++++++++++- engines/nvme.c | 34 ++++++++++++++++++++++++++++++++++ engines/nvme.h | 12 ++++++++++++ stat.c | 2 +- 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/engines/io_uring.c b/engines/io_uring.c index 54fdf7f3..f10a4593 100644 --- a/engines/io_uring.c +++ b/engines/io_uring.c @@ -24,6 +24,7 @@ #include "../lib/types.h" #include "../os/linux/io_uring.h" #include "cmdprio.h" +#include "zbd.h" #include "nvme.h" #include @@ -409,6 +410,9 @@ static int fio_ioring_cmd_prep(struct thread_data *td, struct io_u *io_u) if (o->cmd_type != FIO_URING_CMD_NVME) return -EINVAL; + if (io_u->ddir == DDIR_TRIM) + return 0; + sqe = &ld->sqes[(io_u->index) << 1]; if (o->registerfiles) { @@ -556,6 +560,27 @@ static inline void fio_ioring_cmdprio_prep(struct thread_data *td, ld->sqes[io_u->index].ioprio = io_u->ioprio; } +static int fio_ioring_cmd_io_u_trim(const struct thread_data *td, + struct io_u *io_u) +{ + struct fio_file *f = io_u->file; + int ret; + + if (td->o.zone_mode == ZONE_MODE_ZBD) { + ret = zbd_do_io_u_trim(td, io_u); + if (ret == io_u_completed) + return io_u->xfer_buflen; + if (ret) + goto err; + } + + return fio_nvme_trim(td, f, io_u->offset, io_u->xfer_buflen); + +err: + io_u->error = ret; + return 0; +} + static enum fio_q_status fio_ioring_queue(struct thread_data *td, struct io_u *io_u) { @@ -572,7 +597,11 @@ static enum fio_q_status fio_ioring_queue(struct thread_data *td, if (ld->queued) return FIO_Q_BUSY; - do_io_u_trim(td, io_u); + if (!strcmp(td->io_ops->name, "io_uring_cmd")) + fio_ioring_cmd_io_u_trim(td, io_u); + else + do_io_u_trim(td, io_u); + io_u_mark_submit(td, 1); io_u_mark_complete(td, 1); return FIO_Q_COMPLETED; diff --git a/engines/nvme.c b/engines/nvme.c index 3f6b64a8..ac908687 100644 --- a/engines/nvme.c +++ b/engines/nvme.c @@ -43,6 +43,40 @@ int fio_nvme_uring_cmd_prep(struct nvme_uring_cmd *cmd, struct io_u *io_u, return 0; } +static int nvme_trim(int fd, __u32 nsid, __u32 nr_range, __u32 data_len, + void *data) +{ + struct nvme_passthru_cmd cmd = { + .opcode = nvme_cmd_dsm, + .nsid = nsid, + .addr = (__u64)(uintptr_t)data, + .data_len = data_len, + .cdw10 = nr_range - 1, + .cdw11 = NVME_ATTRIBUTE_DEALLOCATE, + }; + + return ioctl(fd, NVME_IOCTL_IO_CMD, &cmd); +} + +int fio_nvme_trim(const struct thread_data *td, struct fio_file *f, + unsigned long long offset, unsigned long long len) +{ + struct nvme_data *data = FILE_ENG_DATA(f); + struct nvme_dsm_range dsm; + int ret; + + dsm.nlb = (len >> data->lba_shift); + dsm.slba = (offset >> data->lba_shift); + + ret = nvme_trim(f->fd, data->nsid, 1, sizeof(struct nvme_dsm_range), + &dsm); + if (ret) + log_err("%s: nvme_trim failed for offset %llu and len %llu, err=%d\n", + f->file_name, offset, len, ret); + + return ret; +} + static int nvme_identify(int fd, __u32 nsid, enum nvme_identify_cns cns, enum nvme_csi csi, void *data) { diff --git a/engines/nvme.h b/engines/nvme.h index 1c0e526b..408594d5 100644 --- a/engines/nvme.h +++ b/engines/nvme.h @@ -48,6 +48,8 @@ struct nvme_uring_cmd { #define NVME_ZNS_ZSA_RESET 0x4 #define NVME_ZONE_TYPE_SEQWRITE_REQ 0x2 +#define NVME_ATTRIBUTE_DEALLOCATE (1 << 2) + enum nvme_identify_cns { NVME_IDENTIFY_CNS_NS = 0x00, NVME_IDENTIFY_CNS_CSI_NS = 0x05, @@ -67,6 +69,7 @@ enum nvme_admin_opcode { enum nvme_io_opcode { nvme_cmd_write = 0x01, nvme_cmd_read = 0x02, + nvme_cmd_dsm = 0x09, nvme_cmd_io_mgmt_recv = 0x12, nvme_zns_cmd_mgmt_send = 0x79, nvme_zns_cmd_mgmt_recv = 0x7a, @@ -207,6 +210,15 @@ struct nvme_fdp_ruh_status { struct nvme_fdp_ruh_status_desc ruhss[]; }; +struct nvme_dsm_range { + __le32 cattr; + __le32 nlb; + __le64 slba; +}; + +int fio_nvme_trim(const struct thread_data *td, struct fio_file *f, + unsigned long long offset, unsigned long long len); + int fio_nvme_iomgmt_ruhs(struct thread_data *td, struct fio_file *f, struct nvme_fdp_ruh_status *ruhs, __u32 bytes); diff --git a/stat.c b/stat.c index d779a90f..015b8e28 100644 --- a/stat.c +++ b/stat.c @@ -555,7 +555,7 @@ static void show_ddir_status(struct group_run_stats *rs, struct thread_stat *ts, iops = (1000 * (uint64_t)ts->total_io_u[ddir]) / runt; iops_p = num2str(iops, ts->sig_figs, 1, 0, N2S_NONE); - if (ddir == DDIR_WRITE) + if (ddir == DDIR_WRITE || ddir == DDIR_TRIM) post_st = zbd_write_status(ts); else if (ddir == DDIR_READ && ts->cachehit && ts->cachemiss) { uint64_t total; -- 2.25.1