#include "../lib/types.h"
#include "../os/linux/io_uring.h"
#include "cmdprio.h"
+#include "zbd.h"
#include "nvme.h"
#include <sys/stat.h>
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) {
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)
{
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;
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)
{
#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,
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,
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);
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;