nvme/identify: print discovery log contents
Now that we can connect directly to a discovery service via spdk_nvme_connect(), it is useful to have the ability to dump its discovery log page in the identify example. Change-Id: Ie32f7ae2f0725874fed56258aa3c07d619fce0dd Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-on: https://review.gerrithub.io/382208 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: GangCao <gang.cao@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
415dcbf8cd
commit
0722434074
@ -33,6 +33,7 @@
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
|
||||
#include "spdk/endian.h"
|
||||
#include "spdk/log.h"
|
||||
#include "spdk/nvme.h"
|
||||
#include "spdk/env.h"
|
||||
@ -41,6 +42,8 @@
|
||||
#include "spdk/pci_ids.h"
|
||||
#include "spdk/util.h"
|
||||
|
||||
#define MAX_DISCOVERY_LOG_ENTRIES ((uint64_t)1000)
|
||||
|
||||
static int outstanding_commands;
|
||||
|
||||
struct feature {
|
||||
@ -60,6 +63,10 @@ static struct spdk_nvme_intel_temperature_page intel_temperature_page;
|
||||
|
||||
static struct spdk_nvme_intel_marketing_description_page intel_md_page;
|
||||
|
||||
static struct spdk_nvmf_discovery_log_page *g_discovery_page;
|
||||
static size_t g_discovery_page_size;
|
||||
static uint64_t g_discovery_page_numrec;
|
||||
|
||||
static bool g_hex_dump = false;
|
||||
|
||||
static int g_shm_id = -1;
|
||||
@ -249,6 +256,98 @@ get_intel_md_log_page(struct spdk_nvme_ctrlr *ctrlr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
get_discovery_log_page_header_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct spdk_nvmf_discovery_log_page *new_discovery_page;
|
||||
struct spdk_nvme_ctrlr *ctrlr = cb_arg;
|
||||
uint16_t recfmt;
|
||||
uint64_t remaining;
|
||||
uint64_t offset;
|
||||
|
||||
outstanding_commands--;
|
||||
if (spdk_nvme_cpl_is_error(cpl)) {
|
||||
/* Return without printing anything - this may not be a discovery controller */
|
||||
free(g_discovery_page);
|
||||
g_discovery_page = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Got the first 4K of the discovery log page */
|
||||
recfmt = from_le16(&g_discovery_page->recfmt);
|
||||
if (recfmt != 0) {
|
||||
printf("Unrecognized discovery log record format %" PRIu16 "\n", recfmt);
|
||||
return;
|
||||
}
|
||||
|
||||
g_discovery_page_numrec = from_le64(&g_discovery_page->numrec);
|
||||
|
||||
/* Pick an arbitrary limit to avoid ridiculously large buffer size. */
|
||||
if (g_discovery_page_numrec > MAX_DISCOVERY_LOG_ENTRIES) {
|
||||
printf("Discovery log has %" PRIu64 " entries - limiting to %" PRIu64 ".\n",
|
||||
g_discovery_page_numrec, MAX_DISCOVERY_LOG_ENTRIES);
|
||||
g_discovery_page_numrec = MAX_DISCOVERY_LOG_ENTRIES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we now how many entries should be in the log page, we can allocate
|
||||
* the full log page buffer.
|
||||
*/
|
||||
g_discovery_page_size += g_discovery_page_numrec * sizeof(struct
|
||||
spdk_nvmf_discovery_log_page_entry);
|
||||
new_discovery_page = realloc(g_discovery_page, g_discovery_page_size);
|
||||
if (new_discovery_page == NULL) {
|
||||
free(g_discovery_page);
|
||||
printf("Discovery page allocation failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
g_discovery_page = new_discovery_page;
|
||||
|
||||
/* Retrieve the rest of the discovery log page */
|
||||
offset = offsetof(struct spdk_nvmf_discovery_log_page, entries);
|
||||
remaining = g_discovery_page_size - offset;
|
||||
while (remaining) {
|
||||
uint32_t size;
|
||||
|
||||
/* Retrieve up to 4 KB at a time */
|
||||
size = spdk_min(remaining, 4096);
|
||||
|
||||
if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_DISCOVERY,
|
||||
0, (char *)g_discovery_page + offset, size, offset,
|
||||
get_log_page_completion, NULL)) {
|
||||
printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
offset += size;
|
||||
remaining -= size;
|
||||
outstanding_commands++;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
get_discovery_log_page(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
/* Allocate the initial discovery log page buffer - this will be resized later. */
|
||||
g_discovery_page_size = sizeof(*g_discovery_page);
|
||||
g_discovery_page = calloc(1, g_discovery_page_size);
|
||||
if (g_discovery_page == NULL) {
|
||||
printf("Discovery log page allocation failed!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_DISCOVERY,
|
||||
0, g_discovery_page, g_discovery_page_size, 0,
|
||||
get_discovery_log_page_header_completion, ctrlr)) {
|
||||
printf("spdk_nvme_ctrlr_cmd_get_log_page() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_log_pages(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
@ -293,6 +392,11 @@ get_log_pages(struct spdk_nvme_ctrlr *ctrlr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (get_discovery_log_page(ctrlr) == 0) {
|
||||
outstanding_commands++;
|
||||
}
|
||||
|
||||
while (outstanding_commands) {
|
||||
spdk_nvme_ctrlr_process_admin_completions(ctrlr);
|
||||
}
|
||||
@ -964,6 +1068,85 @@ print_controller(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport
|
||||
for (i = 1; i <= spdk_nvme_ctrlr_get_num_ns(ctrlr); i++) {
|
||||
print_namespace(spdk_nvme_ctrlr_get_ns(ctrlr, i));
|
||||
}
|
||||
|
||||
if (g_discovery_page) {
|
||||
printf("Discovery Log Page\n");
|
||||
printf("==================\n");
|
||||
|
||||
if (g_hex_dump) {
|
||||
hex_dump(g_discovery_page, g_discovery_page_size);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("Generation Counter: %" PRIu64 "\n",
|
||||
from_le64(&g_discovery_page->genctr));
|
||||
printf("Number of Records: %" PRIu64 "\n",
|
||||
from_le64(&g_discovery_page->numrec));
|
||||
printf("Record Format: %" PRIu16 "\n",
|
||||
from_le16(&g_discovery_page->recfmt));
|
||||
printf("\n");
|
||||
|
||||
for (i = 0; i < g_discovery_page_numrec; i++) {
|
||||
struct spdk_nvmf_discovery_log_page_entry *entry = &g_discovery_page->entries[i];
|
||||
|
||||
printf("Discovery Log Entry %u\n", i);
|
||||
printf("----------------------\n");
|
||||
printf("Transport Type: %u (%s)\n",
|
||||
entry->trtype, spdk_nvme_transport_id_trtype_str(entry->trtype));
|
||||
printf("Address Family: %u (%s)\n",
|
||||
entry->adrfam, spdk_nvme_transport_id_adrfam_str(entry->adrfam));
|
||||
printf("Subsystem Type: %u (%s)\n",
|
||||
entry->subtype,
|
||||
entry->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY ? "Discovery Service" :
|
||||
entry->subtype == SPDK_NVMF_SUBTYPE_NVME ? "NVM Subsystem" :
|
||||
"Unknown");
|
||||
printf("Transport Requirements:\n");
|
||||
printf(" Secure Channel: %s\n",
|
||||
entry->treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_SPECIFIED ? "Not Specified" :
|
||||
entry->treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED ? "Required" :
|
||||
entry->treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_REQUIRED ? "Not Required" :
|
||||
"Reserved");
|
||||
printf("Port ID: %" PRIu16 " (0x%04" PRIx16 ")\n",
|
||||
from_le16(&entry->portid), from_le16(&entry->portid));
|
||||
printf("Controller ID: %" PRIu16 " (0x%04" PRIx16 ")\n",
|
||||
from_le16(&entry->cntlid), from_le16(&entry->cntlid));
|
||||
printf("Admin Max SQ Size: %" PRIu16 "\n",
|
||||
from_le16(&entry->asqsz));
|
||||
snprintf(str, sizeof(entry->trsvcid) + 1, "%s", entry->trsvcid);
|
||||
printf("Transport Service Identifier: %s\n", str);
|
||||
snprintf(str, sizeof(entry->subnqn) + 1, "%s", entry->subnqn);
|
||||
printf("NVM Subsystem Qualified Name: %s\n", str);
|
||||
snprintf(str, sizeof(entry->traddr) + 1, "%s", entry->traddr);
|
||||
printf("Transport Address: %s\n", str);
|
||||
|
||||
if (entry->trtype == SPDK_NVMF_TRTYPE_RDMA) {
|
||||
printf("Transport Specific Address Subtype - RDMA\n");
|
||||
printf(" RDMA QP Service Type: %u (%s)\n",
|
||||
entry->tsas.rdma.rdma_qptype,
|
||||
entry->tsas.rdma.rdma_qptype == SPDK_NVMF_RDMA_QPTYPE_RELIABLE_CONNECTED ? "Reliable Connected" :
|
||||
entry->tsas.rdma.rdma_qptype == SPDK_NVMF_RDMA_QPTYPE_RELIABLE_DATAGRAM ? "Reliable Datagram" :
|
||||
"Unknown");
|
||||
printf(" RDMA Provider Type: %u (%s)\n",
|
||||
entry->tsas.rdma.rdma_prtype,
|
||||
entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_NONE ? "No provider specified" :
|
||||
entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_IB ? "InfiniBand" :
|
||||
entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_ROCE ? "InfiniBand RoCE" :
|
||||
entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_ROCE2 ? "InfiniBand RoCE v2" :
|
||||
entry->tsas.rdma.rdma_prtype == SPDK_NVMF_RDMA_PRTYPE_IWARP ? "iWARP" :
|
||||
"Unknown");
|
||||
printf(" RDMA CM Service: %u (%s)\n",
|
||||
entry->tsas.rdma.rdma_cms,
|
||||
entry->tsas.rdma.rdma_cms == SPDK_NVMF_RDMA_CMS_RDMA_CM ? "RDMA_CM" :
|
||||
"Unknown");
|
||||
if (entry->adrfam == SPDK_NVMF_ADRFAM_IB) {
|
||||
printf(" RDMA Partition Key: %" PRIu32 "\n",
|
||||
from_le32(&entry->tsas.rdma.rdma_pkey));
|
||||
}
|
||||
}
|
||||
}
|
||||
free(g_discovery_page);
|
||||
g_discovery_page = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user