examples/display-tree
examples/display-columnar
examples/telemetry-listen
+examples/discover-loop
config-host.h
config-host.mak
CFLAGS ?= -g -O2
-override CFLAGS += -Wall -D_GNU_SOURCE -L../src/ -I../src/
+override CFLAGS += -Wall -D_GNU_SOURCE -L../src/ -I../src/ -lsystemd
include ../Makefile.quiet
include ../config-host.mak
endif
-all_targets += telemetry-listen display-tree display-columnar
+all_targets += telemetry-listen display-tree display-columnar discover-loop
all: $(all_targets)
-test_srcs := telemetry-listen.c display-tree.c display-columnar.c
+test_srcs := telemetry-listen.c display-tree.c display-columnar.c discover-loop.c
test_objs := $(patsubst %.c,%.ol,$(test_srcs))
--- /dev/null
+/**
+ * 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>
+
+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_ctrl_t c;
+ char *hnqn;
+ int ret;
+
+ struct nvme_fabrics_config cfg = {
+ .nqn = NVME_DISC_SUBSYS_NAME,
+ .transport = "loop",
+ .tos = -1,
+ };
+
+ hnqn = nvmf_hostnqn_from_file(),
+ cfg.hostnqn = hnqn;
+
+ c = nvmf_add_ctrl(&cfg);
+ if (!c) {
+ fprintf(stderr, "no controller found\n");
+ return errno;
+ }
+
+ ret = nvmf_get_discovery_log(c, &log, 4);
+ nvme_ctrl_disconnect(c);
+ nvme_free_ctrl(c);
+
+ if (ret)
+ fprintf(stderr, "nvmf-discover-log:%x\n", ret);
+ else
+ print_discover_log(log);
+
+ free(hnqn);
+ return 0;
+}
/**
- * display-tree: Scans the nvme topology, prints as an ascii tree with some
- * selected attributes for each component.
+ * display-columnar: Scans the nvme topology, prints each record type in a
+ * column format for easy visual scanning.
*/
#include <stdio.h>
#include <libnvme.h>
override CFLAGS += -Wall -fPIC
SO_CFLAGS=-shared $(CFLAGS)
L_CFLAGS=$(CFLAGS)
-LINK_FLAGS= -L /usr/lib64
+LINK_FLAGS= -L /usr/lib64 -lsystemd
LINK_FLAGS+=$(LDFLAGS)
ENABLE_SHARED ?= 1
SED ?= sed
nvme_setup_ctrl_list;
nvme_dsm_range;
nvme_get_log_page;
+ __nvme_get_log_page;
nvme_get_ana_log_len;
nvme_namespace_attach_ctrls;
nvme_namespace_detach_ctrls;
return ret;
ret = __nvmf_add_ctrl(argstr);
- printf("ctrl:%s ret:%d\n", argstr, ret);
-
free(argstr);
return ret;
}
errno = EINVAL;
return NULL;
}
- cfg.transport = nvmf_trtype_str(e->trtype);
+
+ switch (e->trtype) {
+ case NVMF_TRTYPE_RDMA:
+ cfg.transport = "rdma";
+ break;
+ case NVMF_TRTYPE_FC:
+ cfg.transport = "fc";
+ break;
+ case NVMF_TRTYPE_TCP:
+ cfg.transport = "tcp";
+ break;
+ case NVMF_TRTYPE_LOOP:
+ cfg.transport = "loop";
+ break;
+ default:
+ break;
+ }
cfg.nqn = e->subnqn;
if (e->treq & NVMF_TREQ_DISABLE_SQFLOW)
static int nvme_discovery_log(int fd, __u32 len, struct nvmf_discovery_log *log)
{
- return nvme_get_log_page(fd, 0, NVME_LOG_LID_DISCOVER, true, len, log);
+ return __nvme_get_log_page(fd, 0, NVME_LOG_LID_DISCOVER, true, 512, len, log);
}
int nvmf_get_discovery_log(nvme_ctrl_t c, struct nvmf_discovery_log **logp,
static struct stat nvme_stat;
int err = fstat(fd, &nvme_stat);
- if (err < 0) {
- perror("fstat");
+ if (err < 0)
return errno;
- }
+
if (!S_ISCHR(nvme_stat.st_mode)) {
errno = ENOTBLK;
return -1;
return err;
}
-int nvme_get_log_page(int fd, __u32 nsid, __u8 log_id, bool rae,
- __u32 data_len, void *data)
+int __nvme_get_log_page(int fd, __u32 nsid, __u8 log_id, bool rae,
+ __u32 xfer_len, __u32 data_len, void *data)
{
- __u64 offset = 0, xfer_len = data_len;
+ __u64 offset = 0, xfer;
void *ptr = data;
int ret;
* avoids having to check the MDTS value of the controller.
*/
do {
- xfer_len = data_len - offset;
- if (xfer_len > 4096)
- xfer_len = 4096;
+ xfer = data_len - offset;
+ if (xfer > xfer_len)
+ xfer = xfer_len;
ret = nvme_get_log(fd, log_id, nsid, offset, NVME_LOG_LSP_NONE,
NVME_LOG_LSI_NONE, rae, NVME_UUID_NONE,
- xfer_len, ptr);
+ xfer, ptr);
if (ret)
return ret;
- offset += xfer_len;
- ptr += xfer_len;
+ offset += xfer;
+ ptr += xfer;
} while (offset < data_len);
return 0;
}
+int nvme_get_log_page(int fd, __u32 nsid, __u8 log_id, bool rae,
+ __u32 data_len, void *data)
+{
+ return __nvme_get_log_page(fd, nsid, log_id, rae, 4086, data_len, data);
+}
+
int nvme_get_telemetry_log(int fd, bool create, bool ctrl, int data_area,
void **buf, __u32 *log_size)
{
void nvme_setup_dsm_range(struct nvme_dsm_range *dsm, __u32 *ctx_attrs,
__u32 *llbas, __u64 *slbas, __u16 nr_ranges);
+/**
+ * __nvme_get_log_page() -
+ * @fd:
+ * @nsid:
+ * @log_id:
+ * @rae:
+ * @xfer_len: Max partial log transfer size to request while splitting
+ * @data_len:
+ * @data:
+ */
+int __nvme_get_log_page(int fd, __u32 nsid, __u8 log_id, bool rae,
+ __u32 xfer_len, __u32 data_len, void *data);
+
/**
* nvme_get_log_page() -
+ * @fd:
+ * @nsid:
+ * @log_id:
+ * @rae:
+ * @data_len:
+ * @data:
+ *
+ * Calls __nvme_get_log_page() with a default 4k transfer length.
*/
int nvme_get_log_page(int fd, __u32 nsid, __u8 log_id, bool rae,
__u32 data_len, void *data);