nvme/rdma: factor out NVMe-oF discovery
This can be used for other NVMe-oF transports. Change-Id: Ic8d2dc483220eb3690cb756bcd750d19c93d98e6 Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-on: https://review.gerrithub.io/416576 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
d81d3fa935
commit
ee9ca4b324
@ -37,6 +37,9 @@
|
|||||||
|
|
||||||
#include "nvme_internal.h"
|
#include "nvme_internal.h"
|
||||||
|
|
||||||
|
#include "spdk/endian.h"
|
||||||
|
#include "spdk/string.h"
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nvme_fabric_prop_set_cmd(struct spdk_nvme_ctrlr *ctrlr,
|
nvme_fabric_prop_set_cmd(struct spdk_nvme_ctrlr *ctrlr,
|
||||||
uint32_t offset, uint8_t size, uint64_t value)
|
uint32_t offset, uint8_t size, uint64_t value)
|
||||||
@ -137,3 +140,131 @@ nvme_fabric_ctrlr_get_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint
|
|||||||
{
|
{
|
||||||
return nvme_fabric_prop_get_cmd(ctrlr, offset, SPDK_NVMF_PROP_SIZE_8, value);
|
return nvme_fabric_prop_get_cmd(ctrlr, offset, SPDK_NVMF_PROP_SIZE_8, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvme_fabric_discover_probe(struct spdk_nvmf_discovery_log_page_entry *entry,
|
||||||
|
void *cb_ctx, spdk_nvme_probe_cb probe_cb)
|
||||||
|
{
|
||||||
|
struct spdk_nvme_transport_id trid;
|
||||||
|
uint8_t *end;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
memset(&trid, 0, sizeof(trid));
|
||||||
|
|
||||||
|
if (entry->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY) {
|
||||||
|
SPDK_WARNLOG("Skipping unsupported discovery service referral\n");
|
||||||
|
return;
|
||||||
|
} else if (entry->subtype != SPDK_NVMF_SUBTYPE_NVME) {
|
||||||
|
SPDK_WARNLOG("Skipping unknown subtype %u\n", entry->subtype);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trid.trtype = entry->trtype;
|
||||||
|
if (!spdk_nvme_transport_available(trid.trtype)) {
|
||||||
|
SPDK_WARNLOG("NVMe transport type %u not available; skipping probe\n",
|
||||||
|
trid.trtype);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trid.adrfam = entry->adrfam;
|
||||||
|
|
||||||
|
/* Ensure that subnqn is null terminated. */
|
||||||
|
end = memchr(entry->subnqn, '\0', SPDK_NVMF_NQN_MAX_LEN + 1);
|
||||||
|
if (!end) {
|
||||||
|
SPDK_ERRLOG("Discovery entry SUBNQN is not null terminated\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
len = end - entry->subnqn;
|
||||||
|
memcpy(trid.subnqn, entry->subnqn, len);
|
||||||
|
trid.subnqn[len] = '\0';
|
||||||
|
|
||||||
|
/* Convert traddr to a null terminated string. */
|
||||||
|
len = spdk_strlen_pad(entry->traddr, sizeof(entry->traddr), ' ');
|
||||||
|
memcpy(trid.traddr, entry->traddr, len);
|
||||||
|
if (spdk_str_chomp(trid.traddr) != 0) {
|
||||||
|
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Trailing newlines removed from discovery TRADDR\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert trsvcid to a null terminated string. */
|
||||||
|
len = spdk_strlen_pad(entry->trsvcid, sizeof(entry->trsvcid), ' ');
|
||||||
|
memcpy(trid.trsvcid, entry->trsvcid, len);
|
||||||
|
if (spdk_str_chomp(trid.trsvcid) != 0) {
|
||||||
|
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Trailing newlines removed from discovery TRSVCID\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDK_DEBUGLOG(SPDK_LOG_NVME, "subnqn=%s, trtype=%u, traddr=%s, trsvcid=%s\n",
|
||||||
|
trid.subnqn, trid.trtype,
|
||||||
|
trid.traddr, trid.trsvcid);
|
||||||
|
|
||||||
|
nvme_ctrlr_probe(&trid, NULL, probe_cb, cb_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvme_fabric_get_discovery_log_page(struct spdk_nvme_ctrlr *ctrlr,
|
||||||
|
void *log_page, uint32_t size, uint64_t offset)
|
||||||
|
{
|
||||||
|
struct nvme_completion_poll_status status;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_DISCOVERY, 0, log_page, size, offset,
|
||||||
|
nvme_completion_poll_cb, &status);
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spdk_nvme_wait_for_completion(ctrlr->adminq, &status)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nvme_fabric_ctrlr_discover(struct spdk_nvme_ctrlr *ctrlr,
|
||||||
|
void *cb_ctx, spdk_nvme_probe_cb probe_cb)
|
||||||
|
{
|
||||||
|
struct spdk_nvmf_discovery_log_page *log_page;
|
||||||
|
struct spdk_nvmf_discovery_log_page_entry *log_page_entry;
|
||||||
|
char buffer[4096];
|
||||||
|
int rc;
|
||||||
|
uint64_t i, numrec, buffer_max_entries_first, buffer_max_entries, log_page_offset = 0;
|
||||||
|
uint64_t remaining_num_rec = 0;
|
||||||
|
uint16_t recfmt;
|
||||||
|
|
||||||
|
memset(buffer, 0x0, 4096);
|
||||||
|
buffer_max_entries_first = (sizeof(buffer) - offsetof(struct spdk_nvmf_discovery_log_page,
|
||||||
|
entries[0])) /
|
||||||
|
sizeof(struct spdk_nvmf_discovery_log_page_entry);
|
||||||
|
buffer_max_entries = sizeof(buffer) / sizeof(struct spdk_nvmf_discovery_log_page_entry);
|
||||||
|
do {
|
||||||
|
rc = nvme_fabric_get_discovery_log_page(ctrlr, buffer, sizeof(buffer), log_page_offset);
|
||||||
|
if (rc < 0) {
|
||||||
|
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Get Log Page - Discovery error\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!remaining_num_rec) {
|
||||||
|
log_page = (struct spdk_nvmf_discovery_log_page *)buffer;
|
||||||
|
recfmt = from_le16(&log_page->recfmt);
|
||||||
|
if (recfmt != 0) {
|
||||||
|
SPDK_ERRLOG("Unrecognized discovery log record format %" PRIu16 "\n", recfmt);
|
||||||
|
return -EPROTO;
|
||||||
|
}
|
||||||
|
remaining_num_rec = log_page->numrec;
|
||||||
|
log_page_offset = offsetof(struct spdk_nvmf_discovery_log_page, entries[0]);
|
||||||
|
log_page_entry = &log_page->entries[0];
|
||||||
|
numrec = spdk_min(remaining_num_rec, buffer_max_entries_first);
|
||||||
|
} else {
|
||||||
|
numrec = spdk_min(remaining_num_rec, buffer_max_entries);
|
||||||
|
log_page_entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numrec; i++) {
|
||||||
|
nvme_fabric_discover_probe(log_page_entry++, cb_ctx, probe_cb);
|
||||||
|
}
|
||||||
|
remaining_num_rec -= numrec;
|
||||||
|
log_page_offset += numrec * sizeof(struct spdk_nvmf_discovery_log_page_entry);
|
||||||
|
} while (remaining_num_rec != 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -684,6 +684,8 @@ int nvme_fabric_ctrlr_set_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
|
|||||||
int nvme_fabric_ctrlr_set_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t value);
|
int nvme_fabric_ctrlr_set_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t value);
|
||||||
int nvme_fabric_ctrlr_get_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t *value);
|
int nvme_fabric_ctrlr_get_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t *value);
|
||||||
int nvme_fabric_ctrlr_get_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t *value);
|
int nvme_fabric_ctrlr_get_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t *value);
|
||||||
|
int nvme_fabric_ctrlr_discover(struct spdk_nvme_ctrlr *ctrlr, void *cb_ctx,
|
||||||
|
spdk_nvme_probe_cb probe_cb);
|
||||||
|
|
||||||
static inline struct nvme_request *
|
static inline struct nvme_request *
|
||||||
nvme_allocate_request(struct spdk_nvme_qpair *qpair,
|
nvme_allocate_request(struct spdk_nvme_qpair *qpair,
|
||||||
|
@ -1088,84 +1088,6 @@ nvme_rdma_ctrlr_enable(struct spdk_nvme_ctrlr *ctrlr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
nvme_fabrics_get_log_discovery_page(struct spdk_nvme_ctrlr *ctrlr,
|
|
||||||
void *log_page, uint32_t size, uint64_t offset)
|
|
||||||
{
|
|
||||||
struct nvme_completion_poll_status status;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = spdk_nvme_ctrlr_cmd_get_log_page(ctrlr, SPDK_NVME_LOG_DISCOVERY, 0, log_page, size, offset,
|
|
||||||
nvme_completion_poll_cb, &status);
|
|
||||||
if (rc < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spdk_nvme_wait_for_completion(ctrlr->adminq, &status)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nvme_rdma_discovery_probe(struct spdk_nvmf_discovery_log_page_entry *entry,
|
|
||||||
void *cb_ctx, spdk_nvme_probe_cb probe_cb)
|
|
||||||
{
|
|
||||||
struct spdk_nvme_transport_id trid;
|
|
||||||
uint8_t *end;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
memset(&trid, 0, sizeof(trid));
|
|
||||||
|
|
||||||
if (entry->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY) {
|
|
||||||
SPDK_WARNLOG("Skipping unsupported discovery service referral\n");
|
|
||||||
return;
|
|
||||||
} else if (entry->subtype != SPDK_NVMF_SUBTYPE_NVME) {
|
|
||||||
SPDK_WARNLOG("Skipping unknown subtype %u\n", entry->subtype);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
trid.trtype = entry->trtype;
|
|
||||||
if (!spdk_nvme_transport_available(trid.trtype)) {
|
|
||||||
SPDK_WARNLOG("NVMe transport type %u not available; skipping probe\n",
|
|
||||||
trid.trtype);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
trid.adrfam = entry->adrfam;
|
|
||||||
|
|
||||||
/* Ensure that subnqn is null terminated. */
|
|
||||||
end = memchr(entry->subnqn, '\0', SPDK_NVMF_NQN_MAX_LEN + 1);
|
|
||||||
if (!end) {
|
|
||||||
SPDK_ERRLOG("Discovery entry SUBNQN is not null terminated\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
len = end - entry->subnqn;
|
|
||||||
memcpy(trid.subnqn, entry->subnqn, len);
|
|
||||||
trid.subnqn[len] = '\0';
|
|
||||||
|
|
||||||
/* Convert traddr to a null terminated string. */
|
|
||||||
len = spdk_strlen_pad(entry->traddr, sizeof(entry->traddr), ' ');
|
|
||||||
memcpy(trid.traddr, entry->traddr, len);
|
|
||||||
if (spdk_str_chomp(trid.traddr) != 0) {
|
|
||||||
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Trailing newlines removed from discovery TRADDR\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert trsvcid to a null terminated string. */
|
|
||||||
len = spdk_strlen_pad(entry->trsvcid, sizeof(entry->trsvcid), ' ');
|
|
||||||
memcpy(trid.trsvcid, entry->trsvcid, len);
|
|
||||||
if (spdk_str_chomp(trid.trsvcid) != 0) {
|
|
||||||
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Trailing newlines removed from discovery TRSVCID\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
SPDK_DEBUGLOG(SPDK_LOG_NVME, "subnqn=%s, trtype=%u, traddr=%s, trsvcid=%s\n",
|
|
||||||
trid.subnqn, trid.trtype,
|
|
||||||
trid.traddr, trid.trsvcid);
|
|
||||||
|
|
||||||
nvme_ctrlr_probe(&trid, NULL, probe_cb, cb_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function must only be called while holding g_spdk_nvme_driver->lock */
|
/* This function must only be called while holding g_spdk_nvme_driver->lock */
|
||||||
int
|
int
|
||||||
nvme_rdma_ctrlr_scan(const struct spdk_nvme_transport_id *discovery_trid,
|
nvme_rdma_ctrlr_scan(const struct spdk_nvme_transport_id *discovery_trid,
|
||||||
@ -1176,14 +1098,8 @@ nvme_rdma_ctrlr_scan(const struct spdk_nvme_transport_id *discovery_trid,
|
|||||||
{
|
{
|
||||||
struct spdk_nvme_ctrlr_opts discovery_opts;
|
struct spdk_nvme_ctrlr_opts discovery_opts;
|
||||||
struct spdk_nvme_ctrlr *discovery_ctrlr;
|
struct spdk_nvme_ctrlr *discovery_ctrlr;
|
||||||
struct spdk_nvmf_discovery_log_page *log_page;
|
|
||||||
struct spdk_nvmf_discovery_log_page_entry *log_page_entry;
|
|
||||||
union spdk_nvme_cc_register cc;
|
union spdk_nvme_cc_register cc;
|
||||||
char buffer[4096];
|
|
||||||
int rc;
|
int rc;
|
||||||
uint64_t i, numrec, buffer_max_entries_first, buffer_max_entries, log_page_offset = 0;
|
|
||||||
uint64_t remaining_num_rec = 0;
|
|
||||||
uint16_t recfmt;
|
|
||||||
struct nvme_completion_poll_status status;
|
struct nvme_completion_poll_status status;
|
||||||
|
|
||||||
if (strcmp(discovery_trid->subnqn, SPDK_NVMF_DISCOVERY_NQN) != 0) {
|
if (strcmp(discovery_trid->subnqn, SPDK_NVMF_DISCOVERY_NQN) != 0) {
|
||||||
@ -1196,7 +1112,6 @@ nvme_rdma_ctrlr_scan(const struct spdk_nvme_transport_id *discovery_trid,
|
|||||||
/* For discovery_ctrlr set the timeout to 0 */
|
/* For discovery_ctrlr set the timeout to 0 */
|
||||||
discovery_opts.keep_alive_timeout_ms = 0;
|
discovery_opts.keep_alive_timeout_ms = 0;
|
||||||
|
|
||||||
memset(buffer, 0x0, 4096);
|
|
||||||
discovery_ctrlr = nvme_rdma_ctrlr_construct(discovery_trid, &discovery_opts, NULL);
|
discovery_ctrlr = nvme_rdma_ctrlr_construct(discovery_trid, &discovery_opts, NULL);
|
||||||
if (discovery_ctrlr == NULL) {
|
if (discovery_ctrlr == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -1238,47 +1153,11 @@ nvme_rdma_ctrlr_scan(const struct spdk_nvme_transport_id *discovery_trid,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_max_entries_first = (sizeof(buffer) - offsetof(struct spdk_nvmf_discovery_log_page,
|
rc = nvme_fabric_ctrlr_discover(discovery_ctrlr, cb_ctx, probe_cb);
|
||||||
entries[0])) /
|
|
||||||
sizeof(struct spdk_nvmf_discovery_log_page_entry);
|
|
||||||
buffer_max_entries = sizeof(buffer) / sizeof(struct spdk_nvmf_discovery_log_page_entry);
|
|
||||||
do {
|
|
||||||
rc = nvme_fabrics_get_log_discovery_page(discovery_ctrlr, buffer, sizeof(buffer), log_page_offset);
|
|
||||||
if (rc < 0) {
|
|
||||||
SPDK_DEBUGLOG(SPDK_LOG_NVME, "nvme_fabrics_get_log_discovery_page error\n");
|
|
||||||
nvme_ctrlr_destruct(discovery_ctrlr);
|
nvme_ctrlr_destruct(discovery_ctrlr);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!remaining_num_rec) {
|
|
||||||
log_page = (struct spdk_nvmf_discovery_log_page *)buffer;
|
|
||||||
recfmt = from_le16(&log_page->recfmt);
|
|
||||||
if (recfmt != 0) {
|
|
||||||
SPDK_ERRLOG("Unrecognized discovery log record format %" PRIu16 "\n", recfmt);
|
|
||||||
nvme_ctrlr_destruct(discovery_ctrlr);
|
|
||||||
return -EPROTO;
|
|
||||||
}
|
|
||||||
remaining_num_rec = log_page->numrec;
|
|
||||||
log_page_offset = offsetof(struct spdk_nvmf_discovery_log_page, entries[0]);
|
|
||||||
log_page_entry = &log_page->entries[0];
|
|
||||||
numrec = spdk_min(remaining_num_rec, buffer_max_entries_first);
|
|
||||||
} else {
|
|
||||||
numrec = spdk_min(remaining_num_rec, buffer_max_entries);
|
|
||||||
log_page_entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < numrec; i++) {
|
|
||||||
nvme_rdma_discovery_probe(log_page_entry++, cb_ctx, probe_cb);
|
|
||||||
}
|
|
||||||
remaining_num_rec -= numrec;
|
|
||||||
log_page_offset += numrec * sizeof(struct spdk_nvmf_discovery_log_page_entry);
|
|
||||||
} while (remaining_num_rec != 0);
|
|
||||||
|
|
||||||
nvme_ctrlr_destruct(discovery_ctrlr);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct spdk_nvme_ctrlr *nvme_rdma_ctrlr_construct(const struct spdk_nvme_transport_id *trid,
|
struct spdk_nvme_ctrlr *nvme_rdma_ctrlr_construct(const struct spdk_nvme_transport_id *trid,
|
||||||
const struct spdk_nvme_ctrlr_opts *opts,
|
const struct spdk_nvme_ctrlr_opts *opts,
|
||||||
void *devhandle)
|
void *devhandle)
|
||||||
|
Loading…
Reference in New Issue
Block a user