Adding upstream version 1.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
809e3412a9
commit
336fe81026
743 changed files with 51081 additions and 0 deletions
66
test/cpp.cc
Normal file
66
test/cpp.cc
Normal 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
39
test/meson.build
Normal 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
231
test/register.c
Normal 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
432
test/test.c
Normal 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
23
test/tree.py
Normal 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
88
test/zns.c
Normal 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);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue