nvme: add initial namespace types support

Add support for getting the Command Set Identifier for a given namespace.

The SPDK_NVME_CAP_CSS_IOCS feature can be implemented on top of an old NVMe
specification. If the feature is set, retrieve the NS ID Descriptor List
regardless of the NVMe specification version. The quirk is still respected.

Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
Change-Id: I7b257115ecb0d813ba75201c0f48960c7070dcc9
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4085
Community-CI: Broadcom CI
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Niklas Cassel 2020-09-07 11:59:35 +00:00 committed by Tomasz Zawadzki
parent 5c861295dd
commit 174a5fe140
7 changed files with 99 additions and 3 deletions

View File

@ -2274,6 +2274,15 @@ uint32_t spdk_nvme_ns_get_optimal_io_boundary(struct spdk_nvme_ns *ns);
*/ */
const struct spdk_uuid *spdk_nvme_ns_get_uuid(const struct spdk_nvme_ns *ns); const struct spdk_uuid *spdk_nvme_ns_get_uuid(const struct spdk_nvme_ns *ns);
/**
* Get the Command Set Identifier for the given namespace.
*
* \param ns Namespace to query.
*
* \return the namespace Command Set Identifier.
*/
enum spdk_nvme_csi spdk_nvme_ns_get_csi(const struct spdk_nvme_ns *ns);
/** /**
* \brief Namespace command support flags. * \brief Namespace command support flags.
*/ */

View File

@ -980,6 +980,14 @@ SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cmd_cdw10) == 4, "Incorrect size");
union spdk_nvme_cmd_cdw11 { union spdk_nvme_cmd_cdw11 {
uint32_t raw; uint32_t raw;
struct {
/* NVM Set Identifier */
uint32_t nvmsetid : 16;
uint32_t reserved : 8;
/* Command Set Identifier */
uint32_t csi : 8;
} identify;
struct { struct {
/* Physically Contiguous */ /* Physically Contiguous */
uint32_t pc : 1; uint32_t pc : 1;
@ -2852,6 +2860,9 @@ enum spdk_nvme_nidt {
/** Namespace UUID */ /** Namespace UUID */
SPDK_NVME_NIDT_UUID = 0x03, SPDK_NVME_NIDT_UUID = 0x03,
/** Namespace Command Set Identifier */
SPDK_NVME_NIDT_CSI = 0x04,
}; };
struct spdk_nvme_ns_id_desc { struct spdk_nvme_ns_id_desc {
@ -2875,6 +2886,12 @@ struct spdk_nvme_ctrlr_list {
}; };
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_ctrlr_list) == 4096, "Incorrect size"); SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_ctrlr_list) == 4096, "Incorrect size");
enum spdk_nvme_csi {
SPDK_NVME_CSI_NVM = 0x0,
SPDK_NVME_CSI_KV = 0x1,
SPDK_NVME_CSI_ZNS = 0x2,
};
enum spdk_nvme_secure_erase_setting { enum spdk_nvme_secure_erase_setting {
SPDK_NVME_FMT_NVM_SES_NO_SECURE_ERASE = 0x0, SPDK_NVME_FMT_NVM_SES_NO_SECURE_ERASE = 0x0,
SPDK_NVME_FMT_NVM_SES_USER_DATA_ERASE = 0x1, SPDK_NVME_FMT_NVM_SES_USER_DATA_ERASE = 0x1,

View File

@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
SO_VER := 4 SO_VER := 4
SO_MINOR := 0 SO_MINOR := 1
C_SRCS = nvme_ctrlr_cmd.c nvme_ctrlr.c nvme_fabric.c nvme_ns_cmd.c nvme_ns.c nvme_pcie.c nvme_qpair.c nvme.c nvme_quirks.c nvme_transport.c nvme_uevent.c nvme_ctrlr_ocssd_cmd.c \ C_SRCS = nvme_ctrlr_cmd.c nvme_ctrlr.c nvme_fabric.c nvme_ns_cmd.c nvme_ns.c nvme_pcie.c nvme_qpair.c nvme.c nvme_quirks.c nvme_transport.c nvme_uevent.c nvme_ctrlr_ocssd_cmd.c \
nvme_ns_ocssd_cmd.c nvme_tcp.c nvme_opal.c nvme_io_msg.c nvme_poll_group.c nvme_ns_ocssd_cmd.c nvme_tcp.c nvme_opal.c nvme_io_msg.c nvme_poll_group.c

View File

@ -1731,7 +1731,8 @@ nvme_ctrlr_identify_id_desc_namespaces(struct spdk_nvme_ctrlr *ctrlr)
struct spdk_nvme_ns *ns; struct spdk_nvme_ns *ns;
int rc; int rc;
if (ctrlr->vs.raw < SPDK_NVME_VERSION(1, 3, 0) || if ((ctrlr->vs.raw < SPDK_NVME_VERSION(1, 3, 0) &&
!(ctrlr->cap.bits.css & SPDK_NVME_CAP_CSS_IOCS)) ||
(ctrlr->quirks & NVME_QUIRK_IDENTIFY_CNS)) { (ctrlr->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Version < 1.3; not attempting to retrieve NS ID Descriptor List\n"); SPDK_DEBUGLOG(SPDK_LOG_NVME, "Version < 1.3; not attempting to retrieve NS ID Descriptor List\n");
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_CONFIGURE_AER, nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_CONFIGURE_AER,

View File

@ -157,7 +157,8 @@ nvme_ctrlr_identify_id_desc(struct spdk_nvme_ns *ns)
memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list)); memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list));
if (ns->ctrlr->vs.raw < SPDK_NVME_VERSION(1, 3, 0) || if ((ns->ctrlr->vs.raw < SPDK_NVME_VERSION(1, 3, 0) &&
!(ns->ctrlr->cap.bits.css & SPDK_NVME_CAP_CSS_IOCS)) ||
(ns->ctrlr->quirks & NVME_QUIRK_IDENTIFY_CNS)) { (ns->ctrlr->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Version < 1.3; not attempting to retrieve NS ID Descriptor List\n"); SPDK_DEBUGLOG(SPDK_LOG_NVME, "Version < 1.3; not attempting to retrieve NS ID Descriptor List\n");
return 0; return 0;
@ -360,6 +361,29 @@ spdk_nvme_ns_get_uuid(const struct spdk_nvme_ns *ns)
return uuid; return uuid;
} }
enum spdk_nvme_csi
spdk_nvme_ns_get_csi(const struct spdk_nvme_ns *ns) {
const uint8_t *csi;
size_t csi_size;
csi = nvme_ns_find_id_desc(ns, SPDK_NVME_NIDT_CSI, &csi_size);
if (csi && csi_size != sizeof(*csi))
{
SPDK_WARNLOG("Invalid NIDT_CSI descriptor length reported: %zu (expected: %zu)\n",
csi_size, sizeof(*csi));
return SPDK_NVME_CSI_NVM;
}
if (!csi)
{
if (ns->ctrlr->cap.bits.css & SPDK_NVME_CAP_CSS_IOCS) {
SPDK_WARNLOG("CSI not reported for NSID: %" PRIu32 "\n", ns->id);
}
return SPDK_NVME_CSI_NVM;
}
return *csi;
}
int nvme_ns_construct(struct spdk_nvme_ns *ns, uint32_t id, int nvme_ns_construct(struct spdk_nvme_ns *ns, uint32_t id,
struct spdk_nvme_ctrlr *ctrlr) struct spdk_nvme_ctrlr *ctrlr)
{ {

View File

@ -107,6 +107,7 @@
spdk_nvme_ns_get_dealloc_logical_block_read_value; spdk_nvme_ns_get_dealloc_logical_block_read_value;
spdk_nvme_ns_get_optimal_io_boundary; spdk_nvme_ns_get_optimal_io_boundary;
spdk_nvme_ns_get_uuid; spdk_nvme_ns_get_uuid;
spdk_nvme_ns_get_csi;
spdk_nvme_ns_get_flags; spdk_nvme_ns_get_flags;
spdk_nvme_ns_cmd_write; spdk_nvme_ns_cmd_write;

View File

@ -135,6 +135,49 @@ test_nvme_ns_uuid(void)
CU_ASSERT(memcmp(uuid, &expected_uuid, sizeof(*uuid)) == 0); CU_ASSERT(memcmp(uuid, &expected_uuid, sizeof(*uuid)) == 0);
} }
static void
test_nvme_ns_csi(void)
{
struct spdk_nvme_ctrlr ctrlr = {};
struct spdk_nvme_ns ns = { .ctrlr = &ctrlr };
enum spdk_nvme_csi csi;
/* Empty list - SPDK_NVME_CSI_NVM should be returned */
memset(ns.id_desc_list, 0, sizeof(ns.id_desc_list));
csi = spdk_nvme_ns_get_csi(&ns);
CU_ASSERT(csi == SPDK_NVME_CSI_NVM);
/* NVM CSI - SPDK_NVME_CSI_NVM should be returned */
memset(ns.id_desc_list, 0, sizeof(ns.id_desc_list));
ns.id_desc_list[0] = 0x4; /* NIDT == CSI */
ns.id_desc_list[1] = 0x1; /* NIDL */
ns.id_desc_list[4] = 0x0; /* SPDK_NVME_CSI_NVM */
csi = spdk_nvme_ns_get_csi(&ns);
CU_ASSERT(csi == SPDK_NVME_CSI_NVM);
/* NGUID followed by ZNS CSI - SPDK_NVME_CSI_ZNS should be returned */
memset(ns.id_desc_list, 0, sizeof(ns.id_desc_list));
ns.id_desc_list[0] = 0x02; /* NIDT == NGUID */
ns.id_desc_list[1] = 0x10; /* NIDL */
memset(&ns.id_desc_list[4], 0xCC, 0x10);
ns.id_desc_list[20] = 0x4; /* NIDT == CSI */
ns.id_desc_list[21] = 0x1; /* NIDL */
ns.id_desc_list[24] = 0x2; /* SPDK_NVME_CSI_ZNS */
csi = spdk_nvme_ns_get_csi(&ns);
CU_ASSERT(csi == SPDK_NVME_CSI_ZNS);
/* KV CSI followed by NGUID - SPDK_NVME_CSI_KV should be returned */
memset(ns.id_desc_list, 0, sizeof(ns.id_desc_list));
ns.id_desc_list[0] = 0x4; /* NIDT == CSI */
ns.id_desc_list[1] = 0x1; /* NIDL */
ns.id_desc_list[4] = 0x1; /* SPDK_NVME_CSI_KV */
ns.id_desc_list[5] = 0x02; /* NIDT == NGUID */
ns.id_desc_list[6] = 0x10; /* NIDL */
memset(&ns.id_desc_list[9], 0xCC, 0x10);
csi = spdk_nvme_ns_get_csi(&ns);
CU_ASSERT(csi == SPDK_NVME_CSI_KV);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
CU_pSuite suite = NULL; CU_pSuite suite = NULL;
@ -147,6 +190,7 @@ int main(int argc, char **argv)
CU_ADD_TEST(suite, test_nvme_ns_construct); CU_ADD_TEST(suite, test_nvme_ns_construct);
CU_ADD_TEST(suite, test_nvme_ns_uuid); CU_ADD_TEST(suite, test_nvme_ns_uuid);
CU_ADD_TEST(suite, test_nvme_ns_csi);
CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests(); CU_basic_run_tests();