diff options
Diffstat (limited to 'nvme-ioctl.c')
-rw-r--r-- | nvme-ioctl.c | 314 |
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; +} |