1
0
Fork 0

Adding upstream version 1.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-15 08:44:15 +01:00
parent 809e3412a9
commit 336fe81026
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
743 changed files with 51081 additions and 0 deletions

66
test/cpp.cc Normal file
View file

@ -0,0 +1,66 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* This file is part of libnvme.
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
*
* Authors: Keith Busch <keith.busch@wdc.com>
*/
#include <iostream>
#include <libnvme.h>
int main()
{
nvme_root_t r;
nvme_host_t h;
nvme_subsystem_t s;
nvme_ctrl_t c;
nvme_path_t p;
nvme_ns_t n;
r = nvme_scan(NULL);
if (!r)
return -1;
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
std::cout << nvme_subsystem_get_name(s)
<< " - NQN=" << nvme_subsystem_get_nqn(s)
<< "\n";
nvme_subsystem_for_each_ctrl(s, c) {
std::cout << " `- " << nvme_ctrl_get_name(c)
<< " " << nvme_ctrl_get_transport(c)
<< " " << nvme_ctrl_get_address(c)
<< " " << nvme_ctrl_get_state(c)
<< "\n";
nvme_ctrl_for_each_ns(c, n) {
std::cout << " `- "
<< nvme_ns_get_name(n)
<< "lba size:"
<< nvme_ns_get_lba_size(n)
<< " lba max:"
<< nvme_ns_get_lba_count(n)
<< "\n";
}
nvme_ctrl_for_each_path(c, p) {
std::cout << " `- "
<< nvme_path_get_name(p)
<< " "
<< nvme_path_get_ana_state(p)
<< "\n";
}
}
nvme_subsystem_for_each_ns(s, n) {
std::cout << " `- " << nvme_ns_get_name(n)
<< "lba size:"
<< nvme_ns_get_lba_size(n)
<< " lba max:"
<< nvme_ns_get_lba_count(n) << "\n";
}
}
}
std::cout << "\n";
nvme_free_tree(r);
return 0;
}

39
test/meson.build Normal file
View file

@ -0,0 +1,39 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of libnvme.
# Copyright (c) 2021 Dell Inc.
#
# Authors: Martin Belanger <Martin.Belanger@dell.com>
# These tests all require interaction with a real NVMe device, so we don't
# define as meson unit-tests, and therefore get run as part of the 'test'
# target. However, they're available for developer use, when hardware is
# available.
main = executable(
'main-test',
['test.c'],
dependencies: libuuid_dep,
link_with: libnvme,
include_directories: [incdir, internal_incdir]
)
cpp = executable(
'test-cpp',
['cpp.cc'],
link_with: libnvme,
include_directories: [incdir, internal_incdir]
)
register = executable(
'test-register',
['register.c'],
link_with: libnvme,
include_directories: [incdir, internal_incdir]
)
zns = executable(
'test-zns',
['zns.c'],
link_with: libnvme,
include_directories: [incdir, internal_incdir]
)

231
test/register.c Normal file
View file

@ -0,0 +1,231 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* This file is part of libnvme.
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
*
* Authors: Keith Busch <keith.busch@wdc.com>
*/
/**
* Prints the values of the nvme register map. Use the nvme controller resource
* for your pci device found in /sys/class/nvme/nvmeX/device/resource0
*/
#include <fcntl.h>
#include <inttypes.h>
#include <libnvme.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/mman.h>
#include <ccan/endian/endian.h>
static inline uint32_t nvme_mmio_read32(volatile void *addr)
{
uint32_t *p = (__le32 *)addr;
return le32_to_cpu(*p);
}
static inline uint64_t nvme_mmio_read64(volatile void *addr)
{
volatile __u32 *p = (__u32 *)addr;
uint32_t low, high;
low = nvme_mmio_read32(p);
high = nvme_mmio_read32(p + 1);
return low + ((uint64_t)high << 32);
}
void nvme_print_registers(void *regs)
{
__u64 cap = nvme_mmio_read64(regs + NVME_REG_CAP);
__u32 vs = nvme_mmio_read32(regs + NVME_REG_VS);
__u32 intms = nvme_mmio_read32(regs + NVME_REG_INTMS);
__u32 intmc = nvme_mmio_read32(regs + NVME_REG_INTMC);
__u32 cc = nvme_mmio_read32(regs + NVME_REG_CC);
__u32 csts = nvme_mmio_read32(regs + NVME_REG_CSTS);
__u32 nssr = nvme_mmio_read32(regs + NVME_REG_NSSR);
__u32 aqa = nvme_mmio_read32(regs + NVME_REG_AQA);
__u64 asq = nvme_mmio_read64(regs + NVME_REG_ASQ);
__u64 acq = nvme_mmio_read64(regs + NVME_REG_ACQ);
__u32 cmbloc = nvme_mmio_read32(regs + NVME_REG_CMBLOC);
__u32 cmbsz = nvme_mmio_read32(regs + NVME_REG_CMBSZ);
__u32 bpinfo = nvme_mmio_read32(regs + NVME_REG_BPINFO);
__u32 bprsel = nvme_mmio_read32(regs + NVME_REG_BPRSEL);
__u64 bpmbl = nvme_mmio_read64(regs + NVME_REG_BPMBL);
__u64 cmbmsc = nvme_mmio_read64(regs + NVME_REG_CMBMSC);
__u32 cmbsts = nvme_mmio_read32(regs + NVME_REG_CMBSTS);
__u32 pmrcap = nvme_mmio_read32(regs + NVME_REG_PMRCAP);
__u32 pmrctl = nvme_mmio_read32(regs + NVME_REG_PMRCTL);
__u32 pmrsts = nvme_mmio_read32(regs + NVME_REG_PMRSTS);
__u32 pmrebs = nvme_mmio_read32(regs + NVME_REG_PMREBS);
__u32 pmrswtp = nvme_mmio_read32(regs + NVME_REG_PMRSWTP);
__u64 pmrmsc = nvme_mmio_read32(regs + NVME_REG_PMRMSCL) |
(__u64)nvme_mmio_read64(regs + NVME_REG_PMRMSCU) << 32;
printf("%-10s : %llx\n", "CAP", cap);
printf(" %-8s : %llx\n", "MQES", NVME_CAP_MQES(cap));
printf(" %-8s : %llx\n", "CQRS", NVME_CAP_CQR(cap));
printf(" %-8s : %llx\n", "AMS", NVME_CAP_AMS(cap));
printf(" %-8s : %llx\n", "TO", NVME_CAP_TO(cap));
printf(" %-8s : %llx\n", "DSTRD", NVME_CAP_DSTRD(cap));
printf(" %-8s : %llx\n", "NSSRC", NVME_CAP_NSSRC(cap));
printf(" %-8s : %llx\n", "CSS", NVME_CAP_CSS(cap));
printf(" %-8s : %llx\n", "BPS", NVME_CAP_BPS(cap));
printf(" %-8s : %llx\n", "MPSMIN", NVME_CAP_MPSMIN(cap));
printf(" %-8s : %llx\n", "MPSMAX", NVME_CAP_MPSMAX(cap));
printf(" %-8s : %llx\n", "CMBS", NVME_CAP_CMBS(cap));
printf(" %-8s : %llx\n", "PMRS", NVME_CAP_PMRS(cap));
printf("%-10s : %x\n", "VS", vs);
printf(" %-8s : %x\n", "MJR", NVME_VS_TER(vs));
printf(" %-8s : %x\n", "MNR", NVME_VS_MNR(vs));
printf(" %-8s : %x\n", "TER", NVME_VS_MJR(vs));
printf("%-10s : %x\n", "INTMS", intms);
printf("%-10s : %x\n", "INTMC", intmc);
printf("%-10s : %x\n", "CC", cc);
printf(" %-8s : %x\n", "EN", NVME_CC_EN(cc));
printf(" %-8s : %x\n", "CSS", NVME_CC_CSS(cc));
printf(" %-8s : %x\n", "MPS", NVME_CC_MPS(cc));
printf(" %-8s : %x\n", "AMS", NVME_CC_AMS(cc));
printf(" %-8s : %x\n", "SHN", NVME_CC_SHN(cc));
printf(" %-8s : %x\n", "IOSQES", NVME_CC_IOSQES(cc));
printf(" %-8s : %x\n", "IOCQES", NVME_CC_IOCQES(cc));
printf("%-10s : %x\n", "CSTS", csts);
printf(" %-8s : %x\n", "RDY", NVME_CSTS_RDY(csts));
printf(" %-8s : %x\n", "CFS", NVME_CSTS_CFS(csts));
printf(" %-8s : %x\n", "SHST", NVME_CSTS_SHST(csts));
printf(" %-8s : %x\n", "NSSRO", NVME_CSTS_NSSRO(csts));
printf(" %-8s : %x\n", "PP", NVME_CSTS_PP(csts));
printf("%-10s : %x\n", "NSSR", nssr);
printf("%-10s : %x\n", "AQA", aqa);
printf(" %-8s : %x\n", "ASQS", NVME_AQA_ASQS(aqa));
printf(" %-8s : %x\n", "ACQS", NVME_AQA_ACQS(aqa));
printf("%-10s : %llx\n", "ASQ", asq);
printf("%-10s : %llx\n", "ACQ", acq);
printf("%-10s : %x\n", "CMBLOC", cmbloc);
printf(" %-8s : %x\n", "BIR", NVME_CMBLOC_BIR(cmbloc));
printf(" %-8s : %x\n", "CQMMS", NVME_CMBLOC_CQMMS(cmbloc));
printf(" %-8s : %x\n", "CQPDS", NVME_CMBLOC_CQPDS(cmbloc));
printf(" %-8s : %x\n", "CDPLMS", NVME_CMBLOC_CDPLMS(cmbloc));
printf(" %-8s : %x\n", "CDPCILS", NVME_CMBLOC_CDPCILS(cmbloc));
printf(" %-8s : %x\n", "CDMMMS", NVME_CMBLOC_CDMMMS(cmbloc));
printf(" %-8s : %x\n", "CQDA", NVME_CMBLOC_CQDA(cmbloc));
printf(" %-8s : %x\n", "OFST", NVME_CMBLOC_OFST(cmbloc));
printf("%-10s : %x\n", "CMBSZ", cmbsz);
printf(" %-8s : %x\n", "SQS", NVME_CMBSZ_SQS(cmbsz));
printf(" %-8s : %x\n", "CQS", NVME_CMBSZ_CQS(cmbsz));
printf(" %-8s : %x\n", "LISTS", NVME_CMBSZ_LISTS(cmbsz));
printf(" %-8s : %x\n", "RDS", NVME_CMBSZ_RDS(cmbsz));
printf(" %-8s : %x\n", "WDS", NVME_CMBSZ_WDS(cmbsz));
printf(" %-8s : %x\n", "SZU", NVME_CMBSZ_SZU(cmbsz));
printf(" %-8s : %x\n", "SZ", NVME_CMBSZ_SZ(cmbsz));
printf(" %-8s : %llx\n", "bytes", nvme_cmb_size(cmbsz));
printf("%-10s : %x\n", "BPINFO", bpinfo);
printf(" %-8s : %x\n", "BPSZ", NVME_BPINFO_BPSZ(bpinfo));
printf(" %-8s : %x\n", "BRS", NVME_BPINFO_BRS(bpinfo));
printf(" %-8s : %x\n", "ABPID", NVME_BPINFO_ABPID(bpinfo));
printf("%-10s : %x\n", "BPRSEL", bprsel);
printf(" %-8s : %x\n", "BPRSZ", NVME_BPRSEL_BPRSZ(bprsel));
printf(" %-8s : %x\n", "BPROF", NVME_BPRSEL_BPROF(bprsel));
printf(" %-8s : %x\n", "BPID", NVME_BPRSEL_BPID(bprsel));
printf("%-10s : %llx\n", "BPMBL", bpmbl);
printf("%-10s : %llx\n", "CMBMSC", cmbmsc);
printf(" %-8s : %llx\n", "CRE", NVME_CMBMSC_CRE(cmbmsc));
printf(" %-8s : %llx\n", "CMSE", NVME_CMBMSC_CMSE(cmbmsc));
printf(" %-8s : %llx\n", "CBA", NVME_CMBMSC_CBA(cmbmsc));
printf("%-10s : %x\n", "CMBSTS", cmbsts);
printf(" %-8s : %x\n", "CBAI", NVME_CMBSTS_CBAI(cmbsts));
printf("%-10s : %x\n", "PMRCAP", pmrcap);
printf(" %-8s : %x\n", "RDS", NVME_PMRCAP_RDS(pmrcap));
printf(" %-8s : %x\n", "WDS", NVME_PMRCAP_WDS(pmrcap));
printf(" %-8s : %x\n", "BIR", NVME_PMRCAP_BIR(pmrcap));
printf(" %-8s : %x\n", "PMRTU", NVME_PMRCAP_PMRTU(pmrcap));
printf(" %-8s : %x\n", "PMRWMB", NVME_PMRCAP_PMRWMB(pmrcap));
printf(" %-8s : %x\n", "PMRTO", NVME_PMRCAP_PMRTO(pmrcap));
printf(" %-8s : %x\n", "CMSS", NVME_PMRCAP_CMSS(pmrcap));
printf("%-10s : %x\n", "PMRCTL", pmrctl);
printf(" %-8s : %x\n", "EN", NVME_PMRCTL_EN(pmrctl));
printf("%-10s : %x\n", "PMRSTS", pmrsts);
printf(" %-8s : %x\n", "ERR", NVME_PMRSTS_ERR(pmrsts));
printf(" %-8s : %x\n", "NRDY", NVME_PMRSTS_NRDY(pmrsts));
printf(" %-8s : %x\n", "HSTS", NVME_PMRSTS_HSTS(pmrsts));
printf(" %-8s : %x\n", "CBAI", NVME_PMRSTS_CBAI(pmrsts));
printf("%-10s : %x\n", "PMREBS", pmrebs);
printf(" %-8s : %x\n", "PMRSZU", NVME_PMREBS_PMRSZU(pmrebs));
printf(" %-8s : %x\n", "RBB", NVME_PMREBS_RBB(pmrebs));
printf(" %-8s : %x\n", "PMRWBZ", NVME_PMREBS_PMRWBZ(pmrebs));
printf(" %-8s : %llx\n", "bytes", nvme_pmr_size(pmrebs));
printf("%-10s : %x\n", "PMRSWTP", pmrswtp);
printf(" %-8s : %x\n", "PMRSWTU", NVME_PMRSWTP_PMRSWTU(pmrswtp));
printf(" %-8s : %x\n", "PMRSWTV", NVME_PMRSWTP_PMRSWTV(pmrswtp));
printf(" %-8s : %llx\n", "tput", nvme_pmr_throughput(pmrswtp));
printf("%-10s : %llx\n", "PMRMSC", pmrmsc);
printf(" %-8s : %llx\n", "CMSE", NVME_PMRMSC_CMSE(pmrmsc));
printf(" %-8s : %llx\n", "CBA", NVME_PMRMSC_CBA(pmrmsc));
}
int main(int argc, char **argv)
{
int ret, fd;
char *path;
void *regs;
if (argc != 2) {
fprintf(stderr, "%s nvme<X>\n", argv[0]);
return 1;
}
ret = asprintf(&path, "/sys/class/nvme/%s/device/resource0", argv[1]);
if (ret < 0)
return 0;
printf("open %s\n", path);
fd = open(path, O_RDONLY | O_SYNC);
if (fd < 0) {
fprintf(stderr, "failed to open %s\n", path);
free(path);
return 1;
}
regs = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0);
if (regs == MAP_FAILED) {
fprintf(stderr, "failed to map device BAR\n");
fprintf(stderr, "did your kernel enable CONFIG_IO_STRICT_DEVMEM?\n");
free(path);
close(fd);
return 1;
}
nvme_print_registers(regs);
munmap(regs, getpagesize());
free(path);
close(fd);
return 0;
}

432
test/test.c Normal file
View file

@ -0,0 +1,432 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* This file is part of libnvme.
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
*
* Authors: Keith Busch <keith.busch@wdc.com>
*/
/**
* Basic libnvme test: uses scan filters, single controllers, and many admin
* command APIs for identifications, logs, and features. No verification for
* specific values are performed: the test will only report which commands
* executed were completed successfully or with an error. User inspection of
* the output woould be required to know if everything is working when the
* program exists successfully; an ungraceful exit means a bug exists
* somewhere.
*/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <inttypes.h>
#include <uuid/uuid.h>
#include <libnvme.h>
#include <ccan/endian/endian.h>
static bool nvme_match_subsysnqn_filter(nvme_subsystem_t s,
nvme_ctrl_t c, nvme_ns_t ns, void *f_args)
{
char *nqn_match = f_args;
if (s)
return strcmp(nvme_subsystem_get_nqn(s), nqn_match) == 0;
return true;
}
static int test_ctrl(nvme_ctrl_t c)
{
static __u8 buf[0x1000];
enum nvme_get_features_sel sel = NVME_GET_FEATURES_SEL_CURRENT;
int ret, temp, fd = nvme_ctrl_get_fd(c);
struct nvme_error_log_page error[64];
struct nvme_smart_log smart = { 0 };
struct nvme_firmware_slot fw = { 0 };
struct nvme_ns_list ns_list = { 0 };
struct nvme_cmd_effects_log cfx = { 0 };
struct nvme_self_test_log st = { 0 };
struct nvme_telemetry_log *telem = (void *)buf;
struct nvme_endurance_group_log eglog = { 0 };
struct nvme_ana_group_desc *analog = (void *)buf;
struct nvme_resv_notification_log resvnotify = { 0 };
struct nvme_sanitize_log_page sanlog = { 0 };
struct nvme_id_uuid_list uuid = { 0 };
struct nvme_id_ns_granularity_list gran = { 0 };
struct nvme_secondary_ctrl_list sec = { 0 };
struct nvme_primary_ctrl_cap prim = { 0 };
struct nvme_ctrl_list ctrlist = { 0 };
struct nvme_id_ctrl id = { 0 };
__u32 result;
ret = nvme_ctrl_identify(c, &id);
if (ret) {
printf("ERROR: no identify for:%s\n", nvme_ctrl_get_name(c));
return ret;
}
else {
printf("PASSED: Identify controller\n");
}
ret = nvme_get_log_smart(fd, NVME_NSID_ALL, true, &smart);
if (ret) {
printf("ERROR: no smart log for:%s %#x\n", nvme_ctrl_get_name(c), ret);
return ret;
}
else {
printf("PASSED: smart log\n");
}
temp = ((smart.temperature[1] << 8) | smart.temperature[0]) - 273;
printf("Controller:%s\n", nvme_ctrl_get_name(c));
printf("\nIdentify:\n");
printf(" vid:%#04x\n", le16_to_cpu(id.vid));
printf(" ssvid:%#04x\n", le16_to_cpu(id.ssvid));
printf(" oacs:%#x\n", id.oacs);
printf(" lpa:%#x\n", id.lpa);
printf(" sn:%-.20s\n", id.sn);
printf(" model:%-.40s\n", id.mn);
ret = nvme_identify_allocated_ns_list(fd, 0, &ns_list);
if (!ret)
printf(" PASSED: Allocated NS List\n");
else
printf(" ERROR: Allocated NS List:%x\n", ret);
ret = nvme_identify_active_ns_list(fd, 0, &ns_list);
if (!ret)
printf(" PASSED: Active NS List\n");
else
printf(" ERROR: Active NS List:%x\n", ret);
ret = nvme_identify_ctrl_list(fd, 0, &ctrlist);
if (!ret)
printf(" PASSED: Ctrl List\n");
else
printf(" ERROR: CtrlList:%x\n", ret);
ret = nvme_identify_nsid_ctrl_list(fd, 1, 0, &ctrlist);
if (!ret)
printf(" PASSED: NSID Ctrl List\n");
else
printf(" ERROR: NSID CtrlList:%x\n", ret);
ret = nvme_identify_primary_ctrl(fd, 0, &prim);
if (!ret)
printf(" PASSED: Identify Primary\n");
else
printf(" ERROR: Identify Primary:%x\n", ret);
ret = nvme_identify_secondary_ctrl_list(fd, 1, 0, &sec);
if (!ret)
printf(" PASSED: Identify Secondary\n");
else
printf(" ERROR: Identify Secondary:%x\n", ret);
ret = nvme_identify_ns_granularity(fd, &gran);
if (!ret)
printf(" PASSED: Identify NS granularity\n");
else
printf(" ERROR: Identify NS granularity:%x\n", ret);
ret = nvme_identify_uuid(fd, &uuid);
if (!ret)
printf(" PASSED: Identify UUID List\n");
else
printf(" ERROR: Identify UUID List:%x\n", ret);
printf("\nLogs\n");
printf(" SMART: Current temperature:%d percent used:%d%%\n", temp,
smart.percent_used);
ret = nvme_get_log_sanitize(fd, true, &sanlog);
if (!ret)
printf(" Sanitize Log:\n");
else
printf(" ERROR: Sanitize Log:%x\n", ret);
ret = nvme_get_log_reservation(fd, true, &resvnotify);
if (!ret)
printf(" Reservation Log\n");
else
printf(" ERROR: Reservation Log:%x\n", ret);
ret = nvme_get_log_ana_groups(fd, true, sizeof(buf), analog);
if (!ret)
printf(" ANA Groups\n");
else
printf(" ERROR: ANA Groups:%x\n", ret);
ret = nvme_get_log_endurance_group(fd, 0, &eglog);
if (!ret)
printf(" Endurance Group\n");
else
printf(" ERROR: Endurance Group:%x\n", ret);
ret = nvme_get_log_telemetry_ctrl(fd, true, 0, sizeof(buf), telem);
if (!ret)
printf(" Telemetry Controller\n");
else
printf(" ERROR: Telemetry Controller:%x\n", ret);
ret = nvme_get_log_device_self_test(fd, &st);
if (!ret)
printf(" Device Self Test\n");
else
printf(" ERROR: Device Self Test:%x\n", ret);
ret = nvme_get_log_cmd_effects(fd, NVME_CSI_NVM, &cfx);
if (!ret)
printf(" Command Effects\n");
else
printf(" ERROR: Command Effects:%x\n", ret);
ret = nvme_get_log_changed_ns_list(fd, true, &ns_list);
if (!ret)
printf(" Change NS List\n");
else
printf(" ERROR: Change NS List:%x\n", ret);
ret = nvme_get_log_fw_slot(fd, true, &fw);
if (!ret)
printf(" FW Slot\n");
else
printf(" ERROR: FW Slot%x\n", ret);
ret = nvme_get_log_error(fd, 64, true, error);
if (!ret)
printf(" Error Log\n");
else
printf(" ERROR: Error Log:%x\n", ret);
printf("\nFeatures\n");
ret = nvme_get_features_arbitration(fd, sel, &result);
if (!ret)
printf(" Arbitration:%x\n", result);
else if (ret > 0)
printf(" ERROR: Arbitration:%x\n", ret);
ret = nvme_get_features_power_mgmt(fd, sel, &result);
if (!ret)
printf(" Power Management:%x\n", result);
else if (ret > 0)
printf(" ERROR: Power Management:%x\n", ret);
ret = nvme_get_features_temp_thresh(fd, sel, &result);
if (!ret)
printf(" Temperature Threshold:%x\n", result);
else if (ret > 0)
printf(" ERROR: Temperature Threshold:%x\n", ret);
ret = nvme_get_features_err_recovery(fd, sel, &result);
if (!ret)
printf(" Error Recovery:%x\n", result);
else if (ret > 0)
printf(" ERROR: Error Recovery:%x\n", ret);
ret = nvme_get_features_volatile_wc(fd, sel, &result);
if (!ret)
printf(" Volatile Write Cache:%x\n", result);
else if (ret > 0)
printf(" ERROR: Volatile Write Cache:%x\n", ret);
ret = nvme_get_features_num_queues(fd, sel, &result);
if (!ret)
printf(" Number of Queues:%x\n", result);
else if (ret > 0)
printf(" ERROR: Number of Queues:%x\n", ret);
ret = nvme_get_features_irq_coalesce(fd, sel, &result);
if (!ret)
printf(" IRQ Coalescing:%x\n", result);
else if (ret > 0)
printf(" ERROR: IRQ Coalescing:%x\n", ret);
ret = nvme_get_features_write_atomic(fd, sel, &result);
if (!ret)
printf(" Write Atomic:%x\n", result);
else if (ret > 0)
printf(" ERROR: Write Atomic:%x\n", ret);
ret = nvme_get_features_async_event(fd, sel, &result);
if (!ret)
printf(" Asycn Event Config:%x\n", result);
else if (ret > 0)
printf(" ERROR: Asycn Event Config:%x\n", ret);
ret = nvme_get_features_hctm(fd, sel, &result);
if (!ret)
printf(" HCTM:%x\n", result);
else if (ret > 0)
printf(" ERROR: HCTM:%x\n", ret);
ret = nvme_get_features_nopsc(fd, sel, &result);
if (!ret)
printf(" NOP Power State Config:%x\n", result);
else if (ret > 0)
printf(" ERROR: NOP Power State Configrbitration:%x\n", ret);
ret = nvme_get_features_rrl(fd, sel, &result);
if (!ret)
printf(" Read Recover Levels:%x\n", result);
else if (ret > 0)
printf(" ERROR: Read Recover Levels:%x\n", ret);
ret = nvme_get_features_lba_sts_interval(fd, sel, &result);
if (!ret)
printf(" LBA Status Interval:%x\n", result);
else if (ret > 0)
printf(" ERROR: LBA Status Interval:%x\n", ret);
ret = nvme_get_features_sanitize(fd, sel, &result);
if (!ret)
printf(" Sanitize:%x\n", result);
else if (ret > 0)
printf(" ERROR: SW Progress Marker:%x\n", ret);
ret = nvme_get_features_sw_progress(fd, sel, &result);
if (!ret)
printf(" SW Progress Marker:%x\n", result);
else if (ret > 0)
printf(" ERROR: Sanitize:%x\n", ret);
ret = nvme_get_features_resv_mask(fd, sel, &result);
if (!ret)
printf(" Reservation Mask:%x\n", result);
else if (ret > 0)
printf(" ERROR: Reservation Mask:%x\n", ret);
ret = nvme_get_features_resv_persist(fd, sel, &result);
if (!ret)
printf(" Reservation Persistence:%x\n", result);
else if (ret > 0)
printf(" ERROR: Reservation Persistence:%x\n", ret);
return 0;
}
static int test_namespace(nvme_ns_t n)
{
int ret, nsid = nvme_ns_get_nsid(n), fd = nvme_ns_get_fd(n);
struct nvme_id_ns ns = { 0 }, allocated = { 0 };
struct nvme_ns_id_desc descs = { 0 };
__u32 result = 0;
__u8 flbas;
ret = nvme_ns_identify(n, &ns);
if (ret)
return ret;
nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &flbas);
printf("%s: nsze:%" PRIu64 " lba size:%d\n",
nvme_ns_get_name(n), le64_to_cpu(ns.nsze),
1 << ns.lbaf[flbas].ds);
ret = nvme_identify_allocated_ns(fd, nsid, &allocated);
if (!ret)
printf(" Identify allocated ns\n");
else
printf(" ERROR: Identify allocated ns:%x\n", ret);
ret = nvme_identify_ns_descs(fd, nsid, &descs);
if (!ret)
printf(" Identify NS Descriptors\n");
else
printf(" ERROR: Identify NS Descriptors:%x\n", ret);
ret = nvme_get_features_write_protect(fd, nsid,
NVME_GET_FEATURES_SEL_CURRENT, &result);
if (!ret)
printf(" Write Protect:%x\n", result);
else if (ret > 0)
printf(" ERROR: Write Protect:%x\n", ret);
return 0;
}
static void print_hex(const uint8_t *x, int len)
{
int i;
for (i = 0; i < len; i++)
printf("%02x", x[i]);
}
int main(int argc, char **argv)
{
nvme_root_t r;
nvme_host_t h;
nvme_subsystem_t s;
nvme_ctrl_t c;
nvme_path_t p;
nvme_ns_t n;
const char *ctrl = "nvme4";
const char *nqn_match = "testnqn";
printf("Test filter for common loop back target\n");
r = nvme_create_root(NULL, DEFAULT_LOGLEVEL);
if (!r)
return 1;
nvme_scan_topology(r, nvme_match_subsysnqn_filter, (void *)nqn_match);
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
printf("%s - NQN=%s\n", nvme_subsystem_get_name(s),
nvme_subsystem_get_nqn(s));
nvme_subsystem_for_each_ctrl(s, c) {
printf(" %s %s %s %s\n", nvme_ctrl_get_name(c),
nvme_ctrl_get_transport(c),
nvme_ctrl_get_address(c),
nvme_ctrl_get_state(c));
}
}
}
printf("\n");
if (argc > 1)
ctrl = argv[1];
printf("Test scan specific controller\n");
c = nvme_scan_ctrl(r, ctrl);
if (c) {
printf("%s %s %s %s\n", nvme_ctrl_get_name(c),
nvme_ctrl_get_transport(c),
nvme_ctrl_get_address(c),
nvme_ctrl_get_state(c));
nvme_free_ctrl(c);
}
printf("\n");
nvme_free_tree(r);
r = nvme_scan(NULL);
if (!r)
return -1;
printf("Test walking the topology\n");
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
printf("%s - NQN=%s\n", nvme_subsystem_get_name(s),
nvme_subsystem_get_nqn(s));
nvme_subsystem_for_each_ctrl(s, c) {
printf(" `- %s %s %s %s\n",
nvme_ctrl_get_name(c),
nvme_ctrl_get_transport(c),
nvme_ctrl_get_address(c),
nvme_ctrl_get_state(c));
nvme_ctrl_for_each_ns(c, n) {
char uuid_str[40];
uuid_t uuid;
printf(" `- %s lba size:%d lba max:%" PRIu64 "\n",
nvme_ns_get_name(n),
nvme_ns_get_lba_size(n),
nvme_ns_get_lba_count(n));
printf(" eui:");
print_hex(nvme_ns_get_eui64(n), 8);
printf(" nguid:");
print_hex(nvme_ns_get_nguid(n), 16);
nvme_ns_get_uuid(n, uuid);
uuid_unparse_lower(uuid, uuid_str);
printf(" uuid:%s csi:%d\n", uuid_str,
nvme_ns_get_csi(n));
}
nvme_ctrl_for_each_path(c, p)
printf(" `- %s %s\n",
nvme_path_get_name(p),
nvme_path_get_ana_state(p));
}
nvme_subsystem_for_each_ns(s, n) {
printf(" `- %s lba size:%d lba max:%" PRIu64 "\n",
nvme_ns_get_name(n),
nvme_ns_get_lba_size(n),
nvme_ns_get_lba_count(n));
}
}
printf("\n");
}
printf("Test identification, logs, and features\n");
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
nvme_subsystem_for_each_ctrl(s, c) {
test_ctrl(c);
printf("\n");
nvme_ctrl_for_each_ns(c, n) {
test_namespace(n);
printf("\n");
}
}
nvme_subsystem_for_each_ns(s, n) {
test_namespace(n);
printf("\n");
}
}
}
nvme_free_tree(r);
return 0;
}

23
test/tree.py Normal file
View file

@ -0,0 +1,23 @@
#!/usr/bin/python3
'''
SPDX-License-Identifier: LGPL-3.1-or-later
This file is part of libnvme.
Copyright (c) 2021 SUSE Software Solutions AG
Authors: Hannes Reinecke <hare@suse.de>
Scans the NVMe subsystem and prints out all found hosts,
subsystems, and controllers
'''
import libnvme
r = libnvme.nvme_root()
for h in r.hosts():
print (h)
for s in h.subsystems():
print (s)
for c in s.controllers():
print (c)

88
test/zns.c Normal file
View file

@ -0,0 +1,88 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* This file is part of libnvme.
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
*
* Authors: Keith Busch <keith.busch@wdc.com>
*/
/**
* Search out for ZNS type namespaces, and if found, report their properties.
*/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <libnvme.h>
#include <inttypes.h>
#include <ccan/endian/endian.h>
static void show_zns_properties(nvme_ns_t n)
{
struct nvme_zns_id_ns zns_ns;
struct nvme_zns_id_ctrl zns_ctrl;
struct nvme_zone_report *zr;
__u32 result;
zr = calloc(1, 0x1000);
if (!zr)
return;
if (nvme_zns_identify_ns(nvme_ns_get_fd(n), nvme_ns_get_nsid(n),
&zns_ns)) {
fprintf(stderr, "failed to identify zns ns\n");;
}
printf("zoc:%x ozcs:%x mar:%x mor:%x\n", le16_to_cpu(zns_ns.zoc),
le16_to_cpu(zns_ns.ozcs), le32_to_cpu(zns_ns.mar),
le32_to_cpu(zns_ns.mor));
if (nvme_zns_identify_ctrl(nvme_ns_get_fd(n), &zns_ctrl)) {
fprintf(stderr, "failed to identify zns ctrl\n");;
return;
}
printf("zasl:%u\n", zns_ctrl.zasl);
if (nvme_zns_report_zones(nvme_ns_get_fd(n), nvme_ns_get_nsid(n), 0,
NVME_ZNS_ZRAS_REPORT_ALL, false,
true, 0x1000, (void *)zr,
NVME_DEFAULT_IOCTL_TIMEOUT, &result)) {
fprintf(stderr, "failed to report zones, result %x\n",
le32_to_cpu(result));
return;
}
printf("nr_zones:%"PRIu64"\n", le64_to_cpu(zr->nr_zones));
free(zr);
}
int main()
{
nvme_subsystem_t s;
nvme_root_t r;
nvme_host_t h;
nvme_ctrl_t c;
nvme_ns_t n;
r = nvme_scan(NULL);
if (!r)
return -1;
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
nvme_subsystem_for_each_ctrl(s, c) {
nvme_ctrl_for_each_ns(c, n) {
if (nvme_ns_get_csi(n) == NVME_CSI_ZNS)
show_zns_properties(n);
}
}
nvme_subsystem_for_each_ns(s, n) {
if (nvme_ns_get_csi(n) == NVME_CSI_ZNS)
show_zns_properties(n);
}
}
}
nvme_free_tree(r);
}