fio: replace malloc+memset with calloc
[fio.git] / engines / nvme.c
index 9ffc5303d2e2883f3421aa4b1c5c0f66d9967fc0..fd2161f363bf5ddcda6fe45501bfcc8e79898a7d 100644 (file)
@@ -28,7 +28,8 @@ 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;
+       cmd->cdw12 = nlb | (io_u->dtype << 20);
+       cmd->cdw13 = io_u->dspec << 16;
        if (iov) {
                iov->iov_base = io_u->xfer_buf;
                iov->iov_len = io_u->xfer_buflen;
@@ -42,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)
 {
@@ -77,9 +112,10 @@ int fio_nvme_get_info(struct fio_file *f, __u32 *nsid, __u32 *lba_sz,
 
        namespace_id = ioctl(fd, NVME_IOCTL_ID);
        if (namespace_id < 0) {
+               err = -errno;
                log_err("failed to fetch namespace-id");
                close(fd);
-               return -errno;
+               return err;
        }
 
        /*
@@ -240,7 +276,7 @@ int fio_nvme_report_zones(struct thread_data *td, struct fio_file *f,
                                break;
                        default:
                                log_err("%s: invalid type for zone at offset %llu.\n",
-                                       f->file_name, desc->zslba);
+                                       f->file_name, (unsigned long long) desc->zslba);
                                ret = -EIO;
                                goto out;
                        }
@@ -345,3 +381,41 @@ out:
        close(fd);
        return ret;
 }
+
+static inline int nvme_fdp_reclaim_unit_handle_status(int fd, __u32 nsid,
+                                                     __u32 data_len, void *data)
+{
+       struct nvme_passthru_cmd cmd = {
+               .opcode         = nvme_cmd_io_mgmt_recv,
+               .nsid           = nsid,
+               .addr           = (__u64)(uintptr_t)data,
+               .data_len       = data_len,
+               .cdw10          = 1,
+               .cdw11          = (data_len >> 2) - 1,
+       };
+
+       return ioctl(fd, NVME_IOCTL_IO_CMD, &cmd);
+}
+
+int fio_nvme_iomgmt_ruhs(struct thread_data *td, struct fio_file *f,
+                        struct nvme_fdp_ruh_status *ruhs, __u32 bytes)
+{
+       struct nvme_data *data = FILE_ENG_DATA(f);
+       int fd, ret;
+
+       fd = open(f->file_name, O_RDONLY | O_LARGEFILE);
+       if (fd < 0)
+               return -errno;
+
+       ret = nvme_fdp_reclaim_unit_handle_status(fd, data->nsid, bytes, ruhs);
+       if (ret) {
+               log_err("%s: nvme_fdp_reclaim_unit_handle_status failed, err=%d\n",
+                       f->file_name, ret);
+               errno = ENOTSUP;
+       } else
+               errno = 0;
+
+       ret = -errno;
+       close(fd);
+       return ret;
+}