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

89
examples/discover-loop.c Normal file
View file

@ -0,0 +1,89 @@
// 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>
*/
/**
* discover-loop: Use fabrics commands to discover any loop targets and print
* those records. You must have at least one configured nvme loop target on the
* system (no existing connection required). The output will look more
* interesting with more targets.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <libnvme.h>
#include <ccan/endian/endian.h>
static void print_discover_log(struct nvmf_discovery_log *log)
{
int i, numrec = le64_to_cpu(log->numrec);
printf(".\n");
printf("|-- genctr:%llx\n", log->genctr);
printf("|-- numrec:%x\n", numrec);
printf("`-- recfmt:%x\n", log->recfmt);
for (i = 0; i < numrec; i++) {
struct nvmf_disc_log_entry *e = &log->entries[i];
printf(" %c-- Entry:%d\n", (i < numrec - 1) ? '|' : '`', i);
printf(" %c |-- trtype:%x\n", (i < numrec - 1) ? '|' : ' ', e->trtype);
printf(" %c |-- adrfam:%x\n", (i < numrec - 1) ? '|' : ' ', e->adrfam);
printf(" %c |-- subtype:%x\n", (i < numrec - 1) ? '|' : ' ', e->subtype);
printf(" %c |-- treq:%x\n", (i < numrec - 1) ? '|' : ' ', e->treq);
printf(" %c |-- portid:%x\n", (i < numrec - 1) ? '|' : ' ', e->portid);
printf(" %c |-- cntlid:%x\n", (i < numrec - 1) ? '|' : ' ', e->cntlid);
printf(" %c |-- asqsz:%x\n", (i < numrec - 1) ? '|' : ' ', e->asqsz);
printf(" %c |-- trsvcid:%s\n", (i < numrec - 1) ? '|' : ' ', e->trsvcid);
printf(" %c |-- subnqn:%s\n", (i < numrec - 1) ? '|' : ' ', e->subnqn);
printf(" %c `-- traddr:%s\n", (i < numrec - 1) ? '|' : ' ', e->traddr);
}
}
int main()
{
struct nvmf_discovery_log *log = NULL;
nvme_root_t r;
nvme_host_t h;
nvme_ctrl_t c;
int ret;
struct nvme_fabrics_config cfg;
nvmf_default_config(&cfg);
r = nvme_scan(NULL);
h = nvme_default_host(r);
if (!h) {
fprintf(stderr, "Failed to allocated memory\n");
return ENOMEM;
}
c = nvme_create_ctrl(r, NVME_DISC_SUBSYS_NAME, "loop",
NULL, NULL, NULL, NULL);
if (!c) {
fprintf(stderr, "Failed to allocate memory\n");
return ENOMEM;
}
ret = nvmf_add_ctrl(h, c, &cfg);
if (ret < 0) {
fprintf(stderr, "no controller found\n");
return errno;
}
ret = nvmf_get_discovery_log(c, &log, 4);
nvme_disconnect_ctrl(c);
nvme_free_ctrl(c);
if (ret)
fprintf(stderr, "nvmf-discover-log:%x\n", ret);
else
print_discover_log(log);
nvme_free_tree(r);
return 0;
}

35
examples/discover-loop.py Normal file
View file

@ -0,0 +1,35 @@
#!/usr/bin/python3
'''
Example script for nvme discovery
Copyright (c) 2021 Hannes Reinecke, SUSE Software Solutions
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
'''
from libnvme import nvme
r = nvme.root()
h = nvme.host(r)
c = nvme.ctrl(nvme.NVME_DISC_SUBSYS_NAME, 'loop')
try:
c.connect(h)
except:
sys.exit("Failed to connect!")
print("connected to %s subsys %s" % (c.name, c.subsystem.name))
try:
d = c.discover()
print (d)
except:
print("Failed to discover!")
pass
c.disconnect()

121
examples/display-columnar.c Normal file
View file

@ -0,0 +1,121 @@
// 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>
*/
/**
* display-columnar: Scans the nvme topology, prints each record type in a
* column format for easy visual scanning.
*/
#include <stdio.h>
#include <inttypes.h>
#include <libnvme.h>
static const char dash[101] = {[0 ... 99] = '-'};
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;
printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers");
printf("%-.16s %-.96s %-.16s\n", dash, dash, dash);
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
bool first = true;
printf("%-16s %-96s ", nvme_subsystem_get_name(s),
nvme_subsystem_get_nqn(s));
nvme_subsystem_for_each_ctrl(s, c) {
printf("%s%s", first ? "": ", ",
nvme_ctrl_get_name(c));
first = false;
}
printf("\n");
}
}
printf("\n");
printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s %-16s\n", "Device",
"SN", "MN", "FR", "TxPort", "Address", "Subsystem", "Namespaces");
printf("%-.8s %-.20s %-.40s %-.8s %-.6s %-.14s %-.12s %-.16s\n", dash, dash,
dash, dash, dash, dash, dash, dash);
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
nvme_subsystem_for_each_ctrl(s, c) {
bool first = true;
printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s ",
nvme_ctrl_get_name(c),
nvme_ctrl_get_serial(c),
nvme_ctrl_get_model(c),
nvme_ctrl_get_firmware(c),
nvme_ctrl_get_transport(c),
nvme_ctrl_get_address(c),
nvme_subsystem_get_name(s));
nvme_ctrl_for_each_ns(c, n) {
printf("%s%s", first ? "": ", ",
nvme_ns_get_name(n));
first = false;
}
nvme_ctrl_for_each_path(c, p) {
printf("%s%s", first ? "": ", ",
nvme_ns_get_name(nvme_path_get_ns(p)));
first = false;
}
printf("\n");
}
}
}
printf("\n");
printf("%-12s %-8s %-16s %-8s %-16s\n", "Device", "NSID", "Sectors", "Format", "Controllers");
printf("%-.12s %-.8s %-.16s %-.8s %-.16s\n", dash, dash, dash, dash, dash);
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)
printf("%-12s %-8d %-16" PRIu64 " %-8d %s\n",
nvme_ns_get_name(n),
nvme_ns_get_nsid(n),
nvme_ns_get_lba_count(n),
nvme_ns_get_lba_size(n),
nvme_ctrl_get_name(c));
}
nvme_subsystem_for_each_ns(s, n) {
bool first = true;
printf("%-12s %-8d %-16" PRIu64 " %-8d ",
nvme_ns_get_name(n),
nvme_ns_get_nsid(n),
nvme_ns_get_lba_count(n),
nvme_ns_get_lba_size(n));
nvme_subsystem_for_each_ctrl(s, c) {
printf("%s%s", first ? "" : ", ",
nvme_ctrl_get_name(c));
first = false;
}
printf("\n");
}
}
}
return 0;
}

71
examples/display-tree.c Normal file
View file

@ -0,0 +1,71 @@
// 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>
*/
/**
* display-tree: Scans the nvme topology, prints as an ascii tree with some
* selected attributes for each component.
*/
#include <stdio.h>
#include <libnvme.h>
int main()
{
nvme_root_t r;
nvme_host_t h;
nvme_subsystem_t s, _s;
nvme_ctrl_t c, _c;
nvme_path_t p, _p;
nvme_ns_t n, _n;
r = nvme_scan(NULL);
if (!r)
return -1;
printf(".\n");
nvme_for_each_host(r, h) {
nvme_for_each_subsystem_safe(h, s, _s) {
printf("%c-- %s - NQN=%s\n", _s ? '|' : '`',
nvme_subsystem_get_name(s),
nvme_subsystem_get_nqn(s));
nvme_subsystem_for_each_ns_safe(s, n, _n) {
printf("%c |-- %s lba size:%d lba max:%lu\n",
_s ? '|' : ' ',
nvme_ns_get_name(n),
nvme_ns_get_lba_size(n),
nvme_ns_get_lba_count(n));
}
nvme_subsystem_for_each_ctrl_safe(s, c, _c) {
printf("%c %c-- %s %s %s %s\n",
_s ? '|' : ' ', _c ? '|' : '`',
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_safe(c, n, _n)
printf("%c %c %c-- %s lba size:%d lba max:%lu\n",
_s ? '|' : ' ', _c ? '|' : ' ',
_n ? '|' : '`',
nvme_ns_get_name(n),
nvme_ns_get_lba_size(n),
nvme_ns_get_lba_count(n));
nvme_ctrl_for_each_path_safe(c, p, _p)
printf("%c %c %c-- %s %s\n",
_s ? '|' : ' ', _c ? '|' : ' ',
_p ? '|' : '`',
nvme_path_get_name(p),
nvme_path_get_ana_state(p));
}
}
}
nvme_free_tree(r);
return 0;
}

34
examples/meson.build Normal file
View file

@ -0,0 +1,34 @@
# 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>
#
executable(
'telemetry-listen',
['telemetry-listen.c'],
link_with: libnvme,
include_directories: [incdir, internal_incdir]
)
executable(
'display-columnar',
['display-columnar.c'],
link_with: libnvme,
include_directories: [incdir, internal_incdir]
)
executable(
'display-tree',
['display-tree.c'],
link_with: libnvme,
include_directories: [incdir, internal_incdir]
)
executable(
'discover-loop',
['discover-loop.c'],
link_with: libnvme,
include_directories: [incdir, internal_incdir]
)

167
examples/telemetry-listen.c Normal file
View file

@ -0,0 +1,167 @@
// 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>
*/
/**
* Open all nvme controller's uevent and listen for changes. If NVME_AEN event
* is observed with controller telemetry data, read the log and save it to a
* file in /var/log/ with the device's unique name and epoch timestamp.
*/
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <libnvme.h>
#include <ccan/endian/endian.h>
struct events {
nvme_ctrl_t c;
int uevent_fd;
};
static int open_uevent(nvme_ctrl_t c)
{
char buf[0x1000];
if (snprintf(buf, sizeof(buf), "%s/uevent", nvme_ctrl_get_sysfs_dir(c)) < 0)
return -1;
return open(buf, O_RDONLY);
}
static void save_telemetry(nvme_ctrl_t c)
{
char buf[0x1000];
size_t log_size;
int ret, fd;
struct nvme_telemetry_log *log;
time_t s;
/* Clear the log (rae == false) at the end to see new telemetry events later */
ret = nvme_get_ctrl_telemetry(nvme_ctrl_get_fd(c), false, &log, NVME_TELEMETRY_DA_3, &log_size);
if (ret)
return;
s = time(NULL);
ret = snprintf(buf, sizeof(buf), "/var/log/%s-telemetry-%ld",
nvme_ctrl_get_subsysnqn(c), s);
if (ret < 0) {
free(log);
return;
}
log_size = (le16_to_cpu(log->dalb3) + 1) * NVME_LOG_TELEM_BLOCK_SIZE;
fd = open(buf, O_CREAT|O_WRONLY, S_IRUSR|S_IRGRP);
if (fd < 0) {
free(log);
return;
}
ret = write(fd, log, log_size);
if (ret < 0)
printf("failed to write telemetry log\n");
else
printf("telemetry log save as %s, wrote:%d size:%ld\n", buf,
ret, log_size);
close(fd);
free(log);
}
static void check_telemetry(nvme_ctrl_t c, int ufd)
{
char buf[0x1000] = { 0 };
char *p, *ptr;
if (read(ufd, buf, sizeof(buf)) < 0)
return;
ptr = buf;
while ((p = strsep(&ptr, "\n")) != NULL) {
__u32 aen, type, info, lid;
if (sscanf(p, "NVME_AEN=0x%08x", &aen) != 1)
continue;
type = aen & 0x07;
info = (aen >> 8) & 0xff;
lid = (aen >> 16) & 0xff;
printf("%s: aen type:%x info:%x lid:%d\n",
nvme_ctrl_get_name(c), type, info, lid);
if (type == NVME_AER_NOTICE &&
info == NVME_AER_NOTICE_TELEMETRY)
save_telemetry(c);
}
}
static void wait_events(fd_set *fds, struct events *e, int nr)
{
int ret, i;
for (i = 0; i < nr; i++)
check_telemetry(e[i].c, e[i].uevent_fd);
while (1) {
ret = select(nr, fds, NULL, NULL, NULL);
if (ret < 0)
return;
for (i = 0; i < nr; i++) {
if (!FD_ISSET(e[i].uevent_fd, fds))
continue;
check_telemetry(e[i].c, e[i].uevent_fd);
}
}
}
int main()
{
struct events *e;
fd_set fds;
int i = 0;
nvme_subsystem_t s;
nvme_ctrl_t c;
nvme_host_t h;
nvme_root_t r;
r = nvme_scan(NULL);
if (!r)
return EXIT_FAILURE;
nvme_for_each_host(r, h)
nvme_for_each_subsystem(h, s)
nvme_subsystem_for_each_ctrl(s, c)
i++;
e = calloc(i, sizeof(e));
FD_ZERO(&fds);
i = 0;
nvme_for_each_host(r, h) {
nvme_for_each_subsystem(h, s) {
nvme_subsystem_for_each_ctrl(s, c) {
int fd = open_uevent(c);
if (fd < 0)
continue;
FD_SET(fd, &fds);
e[i].uevent_fd = fd;
e[i].c = c;
i++;
}
}
}
wait_events(&fds, e, i);
nvme_free_tree(r);
free(e);
return EXIT_SUCCESS;
}