summaryrefslogtreecommitdiffstats
path: root/nvme-ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--nvme-ioctl.c314
1 files changed, 253 insertions, 61 deletions
diff --git a/nvme-ioctl.c b/nvme-ioctl.c
index 39685d6..2801075 100644
--- a/nvme-ioctl.c
+++ b/nvme-ioctl.c
@@ -145,30 +145,6 @@ int nvme_io(int fd, __u8 opcode, __u64 slba, __u16 nblocks, __u16 control,
return ioctl(fd, NVME_IOCTL_SUBMIT_IO, &io);
}
-int nvme_read(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt,
- __u32 reftag, __u16 apptag, __u16 appmask, void *data,
- void *metadata)
-{
- return nvme_io(fd, nvme_cmd_read, slba, nblocks, control, dsmgmt,
- reftag, apptag, appmask, data, metadata);
-}
-
-int nvme_write(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt,
- __u32 reftag, __u16 apptag, __u16 appmask, void *data,
- void *metadata)
-{
- return nvme_io(fd, nvme_cmd_write, slba, nblocks, control, dsmgmt,
- reftag, apptag, appmask, data, metadata);
-}
-
-int nvme_compare(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt,
- __u32 reftag, __u16 apptag, __u16 appmask, void *data,
- void *metadata)
-{
- return nvme_io(fd, nvme_cmd_compare, slba, nblocks, control, dsmgmt,
- reftag, apptag, appmask, data, metadata);
-}
-
int nvme_verify(int fd, __u32 nsid, __u64 slba, __u16 nblocks,
__u16 control, __u32 reftag, __u16 apptag, __u16 appmask)
{
@@ -251,8 +227,9 @@ int nvme_dsm(int fd, __u32 nsid, __u32 cdw11, struct nvme_dsm_range *dsm,
return nvme_submit_io_passthru(fd, &cmd);
}
-struct nvme_dsm_range *nvme_setup_dsm_range(__u32 *ctx_attrs, __u32 *llbas,
- __u64 *slbas, __u16 nr_ranges)
+struct nvme_dsm_range *nvme_setup_dsm_range(int *ctx_attrs, int *llbas,
+ unsigned long long *slbas,
+ __u16 nr_ranges)
{
int i;
struct nvme_dsm_range *dsm = malloc(nr_ranges * sizeof(*dsm));
@@ -269,6 +246,52 @@ struct nvme_dsm_range *nvme_setup_dsm_range(__u32 *ctx_attrs, __u32 *llbas,
return dsm;
}
+int nvme_copy(int fd, __u32 nsid, struct nvme_copy_range *copy, __u64 sdlba,
+ __u16 nr, __u8 prinfor, __u8 prinfow, __u8 dtype, __u16 dspec,
+ __u8 format, int lr, int fua, __u32 ilbrt, __u16 lbatm,
+ __u16 lbat)
+{
+ __u32 cdw12 = ((nr - 1) & 0xff) | ((format & 0xf) << 8) |
+ ((prinfor & 0xf) << 12) | ((dtype & 0xf) << 20) |
+ ((prinfow & 0xf) << 26) | ((fua & 0x1) << 30) |
+ ((lr & 0x1) << 31);
+
+ struct nvme_passthru_cmd cmd = {
+ .opcode = nvme_cmd_copy,
+ .nsid = nsid,
+ .addr = (__u64)(uintptr_t)copy,
+ .data_len = nr * sizeof(*copy),
+ .cdw10 = sdlba & 0xffffffff,
+ .cdw11 = sdlba >> 32,
+ .cdw12 = cdw12,
+ .cdw13 = (dspec & 0xffff) << 16,
+ .cdw14 = ilbrt,
+ .cdw15 = (lbatm << 16) | lbat,
+ };
+
+ return nvme_submit_io_passthru(fd, &cmd);
+}
+
+struct nvme_copy_range *nvme_setup_copy_range(int *nlbs, unsigned long long *slbas,
+ int *eilbrts, int *elbatms, int *elbats, __u16 nr)
+{
+ struct nvme_copy_range *copy = malloc(nr * sizeof(*copy));
+ if (!copy) {
+ fprintf(stderr, "malloc: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ for (int i = 0; i < nr; i++) {
+ copy[i].nlb = cpu_to_le16(nlbs[i]);
+ copy[i].slba = cpu_to_le64(slbas[i]);
+ copy[i].eilbrt = cpu_to_le32(eilbrts[i]);
+ copy[i].elbatm = cpu_to_le16(elbatms[i]);
+ copy[i].elbat = cpu_to_le16(elbats[i]);
+ }
+
+ return copy;
+}
+
int nvme_resv_acquire(int fd, __u32 nsid, __u8 rtype, __u8 racqa,
bool iekey, __u64 crkey, __u64 nrkey)
{
@@ -365,11 +388,22 @@ int nvme_identify_ns(int fd, __u32 nsid, bool present, void *data)
return nvme_identify(fd, nsid, cns, data);
}
-int nvme_identify_ns_list(int fd, __u32 nsid, bool all, void *data)
+int nvme_identify_ns_list_csi(int fd, __u32 nsid, __u8 csi, bool all, void *data)
{
- int cns = all ? NVME_ID_CNS_NS_PRESENT_LIST : NVME_ID_CNS_NS_ACTIVE_LIST;
+ int cns;
- return nvme_identify(fd, nsid, cns, data);
+ if (csi) {
+ cns = all ? NVME_ID_CNS_CSI_NS_PRESENT_LIST : NVME_ID_CNS_CSI_NS_ACTIVE_LIST;
+ } else {
+ cns = all ? NVME_ID_CNS_NS_PRESENT_LIST : NVME_ID_CNS_NS_ACTIVE_LIST;
+ }
+
+ return nvme_identify13(fd, nsid, cns, csi << 24, data);
+}
+
+int nvme_identify_ns_list(int fd, __u32 nsid, bool all, void *data)
+{
+ return nvme_identify_ns_list_csi(fd, nsid, 0x0, all, data);
}
int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data)
@@ -379,6 +413,11 @@ int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data)
return nvme_identify(fd, nsid, (cntid << 16) | cns, data);
}
+int nvme_identify_primary_ctrl_caps(int fd, void *data)
+{
+ return nvme_identify(fd, 0, NVME_ID_CNS_PRIMARY_CTRL_CAPS, data);
+}
+
int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data)
{
return nvme_identify(fd, nsid, (cntid << 16) | NVME_ID_CNS_SCNDRY_CTRL_LIST, data);
@@ -405,6 +444,26 @@ int nvme_identify_uuid(int fd, void *data)
return nvme_identify(fd, 0, NVME_ID_CNS_UUID_LIST, data);
}
+int nvme_identify_ctrl_nvm(int fd, void *data)
+{
+ return nvme_identify13(fd, 0, NVME_ID_CNS_CSI_ID_CTRL, 0, data);
+}
+
+int nvme_zns_identify_ns(int fd, __u32 nsid, void *data)
+{
+ return nvme_identify13(fd, nsid, NVME_ID_CNS_CSI_ID_NS, 2 << 24, data);
+}
+
+int nvme_zns_identify_ctrl(int fd, void *data)
+{
+ return nvme_identify13(fd, 0, NVME_ID_CNS_CSI_ID_CTRL, 2 << 24, data);
+}
+
+int nvme_identify_iocs(int fd, __u16 cntid, void *data)
+{
+ return nvme_identify(fd, 0, (cntid << 16) | NVME_ID_CNS_CSI, data);
+}
+
int nvme_get_log14(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo,
__u16 lsi, bool rae, __u8 uuid_ix, __u32 data_len, void *data)
{
@@ -436,7 +495,7 @@ int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp,
}
int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae,
- __u32 data_len, void *data)
+ __u8 lsp, __u32 data_len, void *data)
{
__u32 offset = 0, xfer_len = data_len;
void *ptr = data;
@@ -452,7 +511,7 @@ int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae,
if (xfer_len > 4096)
xfer_len = 4096;
- ret = nvme_get_log13(fd, nsid, log_id, NVME_NO_LOG_LSP,
+ ret = nvme_get_log13(fd, nsid, log_id, lsp,
offset, 0, rae, xfer_len, ptr);
if (ret)
return ret;
@@ -484,20 +543,20 @@ int nvme_get_telemetry_log(int fd, void *lp, int generate_report,
int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log)
{
return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_FW_SLOT, true,
- sizeof(*fw_log), fw_log);
+ NVME_NO_LOG_LSP, sizeof(*fw_log), fw_log);
}
int nvme_changed_ns_list_log(int fd, struct nvme_changed_ns_list_log *changed_ns_list_log)
{
return nvme_get_log(fd, 0, NVME_LOG_CHANGED_NS, true,
- sizeof(changed_ns_list_log->log),
+ NVME_NO_LOG_LSP, sizeof(changed_ns_list_log->log),
changed_ns_list_log->log);
}
int nvme_error_log(int fd, int entries, struct nvme_error_log_page *err_log)
{
return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_ERROR, false,
- entries * sizeof(*err_log), err_log);
+ NVME_NO_LOG_LSP, entries * sizeof(*err_log), err_log);
}
int nvme_endurance_log(int fd, __u16 group_id, struct nvme_endurance_group_log *endurance_log)
@@ -509,7 +568,7 @@ int nvme_endurance_log(int fd, __u16 group_id, struct nvme_endurance_group_log *
int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log)
{
return nvme_get_log(fd, nsid, NVME_LOG_SMART, false,
- sizeof(*smart_log), smart_log);
+ NVME_NO_LOG_LSP, sizeof(*smart_log), smart_log);
}
int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo)
@@ -518,27 +577,72 @@ int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo)
true, ana_log_len, ana_log);
}
-int nvme_self_test_log(int fd, __u32 nsid, struct nvme_self_test_log *self_test_log)
+int nvme_self_test_log(int fd, __u32 size, struct nvme_self_test_log *self_test_log)
{
- return nvme_get_log(fd, nsid, NVME_LOG_DEVICE_SELF_TEST, false,
- sizeof(*self_test_log), self_test_log);
+ return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_DEVICE_SELF_TEST, false,
+ NVME_NO_LOG_LSP, size, self_test_log);
}
int nvme_effects_log(int fd, struct nvme_effects_log_page *effects_log)
{
return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_CMD_EFFECTS, false,
- sizeof(*effects_log), effects_log);
+ NVME_NO_LOG_LSP, sizeof(*effects_log), effects_log);
}
int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size)
{
- return nvme_get_log(fd, 0, NVME_LOG_DISC, false, size, log);
+ return nvme_get_log(fd, 0, NVME_LOG_DISC, false, NVME_NO_LOG_LSP, size, log);
}
-int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log)
+int nvme_sanitize_log(int fd, bool rae, struct nvme_sanitize_log_page *sanitize_log)
{
- return nvme_get_log(fd, 0, NVME_LOG_SANITIZE, false,
- sizeof(*sanitize_log), sanitize_log);
+ return nvme_get_log(fd, 0, NVME_LOG_SANITIZE, rae,
+ NVME_NO_LOG_LSP, sizeof(*sanitize_log), sanitize_log);
+}
+
+int nvme_predictable_latency_per_nvmset_log(int fd,
+ __u16 nvmset_id,
+ struct nvme_predlat_per_nvmset_log_page *plpns_log)
+{
+ return nvme_get_log13(fd, NVME_NSID_ALL,
+ NVME_LOG_PRELAT_PER_NVMSET, 0, 0, nvmset_id,
+ false, sizeof(*plpns_log), plpns_log);
+}
+
+int nvme_predictable_latency_event_agg_log(int fd,
+ void *pea_log, bool rae, __u32 size)
+{
+ return nvme_get_log(fd, NVME_NSID_ALL,
+ NVME_LOG_PRELAT_EVENT_AGG, rae, NVME_NO_LOG_LSP,
+ size, pea_log);
+}
+
+int nvme_persistent_event_log(int fd, __u8 action, __u32 size,
+ void *pevent_log_info)
+{
+ return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_PERSISTENT_EVENT,
+ false, action, size, pevent_log_info);
+}
+
+int nvme_endurance_group_event_agg_log(int fd,
+ void *endurance_log, bool rae, __u32 size)
+{
+ return nvme_get_log(fd, NVME_NSID_ALL,
+ NVME_LOG_ENDURANCE_GROUP_EVENT_AGG, rae, NVME_NO_LOG_LSP,
+ size, endurance_log);
+}
+
+int nvme_lba_status_log(int fd, void *lba_status, bool rae,
+ __u32 size)
+{
+ return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_LBA_STATUS,
+ rae, NVME_NO_LOG_LSP, size, lba_status);
+}
+
+int nvme_resv_notif_log(int fd, struct nvme_resv_notif_log *resv)
+{
+ return nvme_get_log(fd, 0, NVME_LOG_RESERVATION, false,
+ NVME_NO_LOG_LSP, sizeof(*resv), resv);
}
int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11,
@@ -659,8 +763,8 @@ int nvme_format(int fd, __u32 nsid, __u8 lbaf, __u8 ses, __u8 pi,
}
int nvme_ns_create(int fd, __u64 nsze, __u64 ncap, __u8 flbas, __u8 dps,
- __u8 nmic, __u32 anagrpid, __u16 nvmsetid, __u32 timeout,
- __u32 *result)
+ __u8 nmic, __u32 anagrpid, __u16 nvmsetid, __u8 csi,
+ __u32 timeout, __u32 *result)
{
struct nvme_id_ns ns = {
.nsze = cpu_to_le64(nsze),
@@ -676,6 +780,7 @@ int nvme_ns_create(int fd, __u64 nsze, __u64 ncap, __u8 flbas, __u8 dps,
.opcode = nvme_admin_ns_mgmt,
.addr = (__u64)(uintptr_t) ((void *)&ns),
.cdw10 = 0,
+ .cdw11 = csi << 24,
.data_len = 0x1000,
.timeout_ms = timeout,
};
@@ -745,7 +850,7 @@ int nvme_fw_commit(int fd, __u8 slot, __u8 action, __u8 bpid)
}
int nvme_sec_send(int fd, __u32 nsid, __u8 nssf, __u16 spsp,
- __u8 secp, __u32 tl, __u32 data_len, void *data, __u32 *result)
+ __u8 secp, __u32 tl, __u32 data_len, void *data)
{
struct nvme_admin_cmd cmd = {
.opcode = nvme_admin_security_send,
@@ -755,16 +860,12 @@ int nvme_sec_send(int fd, __u32 nsid, __u8 nssf, __u16 spsp,
.cdw10 = secp << 24 | spsp << 8 | nssf,
.cdw11 = tl,
};
- int err;
- err = nvme_submit_admin_passthru(fd, &cmd);
- if (!err && result)
- *result = cmd.result;
- return err;
+ return nvme_submit_admin_passthru(fd, &cmd);
}
int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp,
- __u8 secp, __u32 al, __u32 data_len, void *data, __u32 *result)
+ __u8 secp, __u32 al, __u32 data_len, void *data)
{
struct nvme_admin_cmd cmd = {
.opcode = nvme_admin_security_recv,
@@ -774,24 +875,23 @@ int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp,
.addr = (__u64)(uintptr_t) data,
.data_len = data_len,
};
- int err;
- err = nvme_submit_admin_passthru(fd, &cmd);
- if (!err && result)
- *result = cmd.result;
- return err;
+ return nvme_submit_admin_passthru(fd, &cmd);
}
-int nvme_get_lba_status(int fd, __u64 slba, __u32 mndw, __u8 atype, __u16 rl,
- void *data)
+int nvme_get_lba_status(int fd, __u32 namespace_id, __u64 slba, __u32 mndw,
+ __u8 atype, __u16 rl, void *data, __u32 timeout_ms)
{
struct nvme_admin_cmd cmd = {
.opcode = nvme_admin_get_lba_status,
+ .nsid = namespace_id,
.addr = (__u64)(uintptr_t) data,
+ .data_len = (mndw + 1) * 4,
.cdw10 = slba & 0xffffffff,
.cdw11 = slba >> 32,
.cdw12 = mndw,
.cdw13 = (atype << 24) | rl,
+ .timeout_ms = timeout_ms,
};
return nvme_submit_admin_passthru(fd, &cmd);
@@ -851,12 +951,12 @@ int nvme_sanitize(int fd, __u8 sanact, __u8 ause, __u8 owpass, __u8 oipbp,
return nvme_submit_admin_passthru(fd, &cmd);
}
-int nvme_self_test_start(int fd, __u32 nsid, __u32 cdw10)
+int nvme_self_test_start(int fd, __u32 nsid, __u8 stc)
{
struct nvme_admin_cmd cmd = {
.opcode = nvme_admin_dev_self_test,
.nsid = nsid,
- .cdw10 = cdw10,
+ .cdw10 = stc,
};
return nvme_submit_admin_passthru(fd, &cmd);
@@ -877,3 +977,95 @@ int nvme_virtual_mgmt(int fd, __u32 cdw10, __u32 cdw11, __u32 *result)
return err;
}
+
+int nvme_zns_mgmt_send(int fd, __u32 nsid, __u64 slba, bool select_all,
+ enum nvme_zns_send_action zsa, __u32 data_len,
+ void *data)
+{
+ __u32 cdw10 = slba & 0xffffffff;
+ __u32 cdw11 = slba >> 32;
+ __u32 cdw13 = zsa | (!!select_all) << 8;
+
+ struct nvme_passthru_cmd cmd = {
+ .opcode = nvme_zns_cmd_mgmt_send,
+ .nsid = nsid,
+ .cdw10 = cdw10,
+ .cdw11 = cdw11,
+ .cdw13 = cdw13,
+ .addr = (__u64)(uintptr_t)data,
+ .data_len = data_len,
+ };
+
+ return nvme_submit_io_passthru(fd, &cmd);
+}
+
+int nvme_zns_mgmt_recv(int fd, __u32 nsid, __u64 slba,
+ enum nvme_zns_recv_action zra, __u8 zrasf,
+ bool zras_feat, __u32 data_len, void *data)
+{
+ __u32 cdw10 = slba & 0xffffffff;
+ __u32 cdw11 = slba >> 32;
+ __u32 cdw12 = (data_len >> 2) - 1;
+ __u32 cdw13 = zra | zrasf << 8 | zras_feat << 16;
+
+ struct nvme_passthru_cmd cmd = {
+ .opcode = nvme_zns_cmd_mgmt_recv,
+ .nsid = nsid,
+ .cdw10 = cdw10,
+ .cdw11 = cdw11,
+ .cdw12 = cdw12,
+ .cdw13 = cdw13,
+ .addr = (__u64)(uintptr_t)data,
+ .data_len = data_len,
+ };
+
+ return nvme_submit_io_passthru(fd, &cmd);
+}
+
+int nvme_zns_report_zones(int fd, __u32 nsid, __u64 slba, bool extended,
+ enum nvme_zns_report_options opts, bool partial,
+ __u32 data_len, void *data)
+{
+ enum nvme_zns_recv_action zra;
+
+ if (extended)
+ zra = NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES;
+ else
+ zra = NVME_ZNS_ZRA_REPORT_ZONES;
+
+ return nvme_zns_mgmt_recv(fd, nsid, slba, zra, opts, partial,
+ data_len, data);
+}
+
+int nvme_zns_append(int fd, __u32 nsid, __u64 zslba, __u16 nlb, __u16 control,
+ __u32 ilbrt, __u16 lbat, __u16 lbatm, __u32 data_len,
+ void *data, __u32 metadata_len, void *metadata,
+ __u64 *result)
+{
+ __u32 cdw10 = zslba & 0xffffffff;
+ __u32 cdw11 = zslba >> 32;
+ __u32 cdw12 = nlb | (control << 16);
+ __u32 cdw14 = ilbrt;
+ __u32 cdw15 = lbat | (lbatm << 16);
+
+ struct nvme_passthru_cmd64 cmd = {
+ .opcode = nvme_zns_cmd_append,
+ .nsid = nsid,
+ .cdw10 = cdw10,
+ .cdw11 = cdw11,
+ .cdw12 = cdw12,
+ .cdw14 = cdw14,
+ .cdw15 = cdw15,
+ .metadata = (__u64)(uintptr_t)metadata,
+ .addr = (__u64)(uintptr_t)data,
+ .metadata_len = metadata_len,
+ .data_len = data_len,
+ };
+
+ int err;
+
+ err = ioctl(fd, NVME_IOCTL_IO64_CMD, &cmd);
+ if (!err && result)
+ *result = cmd.result;
+ return err;
+}