nvme: add spdk_nvme_ns_get_uuid() function
This function retrieves the UUID from a namespace, if available. Change-Id: I98c55375948b92eaf429b41fb36dfea4e2b780a2 Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-on: https://review.gerrithub.io/404734 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
3d57e4a8f4
commit
15bd6999db
@ -15,6 +15,8 @@ needed; previously, the response was limited to 32 kilobytes.
|
||||
EXPERIMENTAL: Adds support for WDS and RDS capable CMBs in NVMe controllers. This support is
|
||||
experimental pending a functional allocator to free and reallocate CMB buffers.
|
||||
|
||||
spdk_nvme_ns_get_uuid() has been added to allow retrieval of per-namespace UUIDs when available.
|
||||
|
||||
### NVMe-oF Target
|
||||
|
||||
Namespaces may now be assigned unique identifiers via new optional "eui64" and "nguid" parameters
|
||||
|
@ -1052,6 +1052,15 @@ enum spdk_nvme_dealloc_logical_block_read_value spdk_nvme_ns_get_dealloc_logical
|
||||
*/
|
||||
uint32_t spdk_nvme_ns_get_optimal_io_boundary(struct spdk_nvme_ns *ns);
|
||||
|
||||
/**
|
||||
* Get the UUID for the given namespace.
|
||||
*
|
||||
* \param ns Namespace to query.
|
||||
*
|
||||
* \return Pointer to namespace UUID, or NULL if ns does not have a UUID.
|
||||
*/
|
||||
const struct spdk_uuid *spdk_nvme_ns_get_uuid(const struct spdk_nvme_ns *ns);
|
||||
|
||||
/**
|
||||
* \brief Namespace command support flags.
|
||||
*/
|
||||
|
@ -302,6 +302,9 @@ struct spdk_nvme_ns {
|
||||
uint32_t sectors_per_stripe;
|
||||
uint32_t id;
|
||||
uint16_t flags;
|
||||
|
||||
/* Namespace Identification Descriptor List (CNS = 03h) */
|
||||
uint8_t id_desc_list[4096];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -122,6 +122,30 @@ int nvme_ns_identify_update(struct spdk_nvme_ns *ns)
|
||||
ns->flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
|
||||
ns->pi_type = nsdata->dps.pit;
|
||||
}
|
||||
|
||||
memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list));
|
||||
if (ns->ctrlr->cdata.ver.raw >= SPDK_NVME_VERSION(1, 3, 0)) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Attempting to retrieve NS ID Descriptor List\n");
|
||||
status.done = false;
|
||||
rc = nvme_ctrlr_cmd_identify(ns->ctrlr, SPDK_NVME_IDENTIFY_NS_ID_DESCRIPTOR_LIST, 0, ns->id,
|
||||
ns->id_desc_list, sizeof(ns->id_desc_list),
|
||||
nvme_completion_poll_cb, &status);
|
||||
if (rc == 0) {
|
||||
while (status.done == false) {
|
||||
nvme_robust_mutex_lock(&ns->ctrlr->ctrlr_lock);
|
||||
spdk_nvme_qpair_process_completions(ns->ctrlr->adminq, 0);
|
||||
nvme_robust_mutex_unlock(&ns->ctrlr->ctrlr_lock);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != 0 || spdk_nvme_cpl_is_error(&status.cpl)) {
|
||||
SPDK_WARNLOG("Failed to retrieve NS ID Descriptor List\n");
|
||||
memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list));
|
||||
}
|
||||
} else {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_NVME, "Version < 1.3; not attempting to retrieve NS ID Descriptor List\n");
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -223,6 +247,55 @@ spdk_nvme_ns_get_optimal_io_boundary(struct spdk_nvme_ns *ns)
|
||||
return ns->sectors_per_stripe;
|
||||
}
|
||||
|
||||
static const void *
|
||||
_spdk_nvme_ns_find_id_desc(const struct spdk_nvme_ns *ns, enum spdk_nvme_nidt type, size_t *length)
|
||||
{
|
||||
const struct spdk_nvme_ns_id_desc *desc;
|
||||
size_t offset;
|
||||
|
||||
offset = 0;
|
||||
while (offset + 4 < sizeof(ns->id_desc_list)) {
|
||||
desc = (const struct spdk_nvme_ns_id_desc *)&ns->id_desc_list[offset];
|
||||
|
||||
if (desc->nidl == 0) {
|
||||
/* End of list */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if this descriptor fits within the list.
|
||||
* 4 is the fixed-size descriptor header (not counted in NIDL).
|
||||
*/
|
||||
if (offset + desc->nidl + 4 > sizeof(ns->id_desc_list)) {
|
||||
/* Descriptor longer than remaining space in list (invalid) */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (desc->nidt == type) {
|
||||
*length = desc->nidl;
|
||||
return &desc->nid[0];
|
||||
}
|
||||
|
||||
offset += 4 + desc->nidl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct spdk_uuid *
|
||||
spdk_nvme_ns_get_uuid(const struct spdk_nvme_ns *ns)
|
||||
{
|
||||
const struct spdk_uuid *uuid;
|
||||
size_t uuid_size;
|
||||
|
||||
uuid = _spdk_nvme_ns_find_id_desc(ns, SPDK_NVME_NIDT_UUID, &uuid_size);
|
||||
if (uuid == NULL || uuid_size != sizeof(*uuid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return uuid;
|
||||
}
|
||||
|
||||
int nvme_ns_construct(struct spdk_nvme_ns *ns, uint32_t id,
|
||||
struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
|
@ -71,6 +71,62 @@ test_nvme_ns_construct(void)
|
||||
CU_ASSERT(ns.id == 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nvme_ns_uuid(void)
|
||||
{
|
||||
struct spdk_nvme_ns ns = {};
|
||||
const struct spdk_uuid *uuid;
|
||||
struct spdk_uuid expected_uuid;
|
||||
|
||||
memset(&expected_uuid, 0xA5, sizeof(expected_uuid));
|
||||
|
||||
/* Empty list - no UUID should be found */
|
||||
memset(ns.id_desc_list, 0, sizeof(ns.id_desc_list));
|
||||
uuid = spdk_nvme_ns_get_uuid(&ns);
|
||||
CU_ASSERT(uuid == NULL);
|
||||
|
||||
/* NGUID only (no UUID in list) */
|
||||
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);
|
||||
uuid = spdk_nvme_ns_get_uuid(&ns);
|
||||
CU_ASSERT(uuid == NULL);
|
||||
|
||||
/* Just UUID in the list */
|
||||
memset(ns.id_desc_list, 0, sizeof(ns.id_desc_list));
|
||||
ns.id_desc_list[0] = 0x03; /* NIDT == UUID */
|
||||
ns.id_desc_list[1] = 0x10; /* NIDL */
|
||||
memcpy(&ns.id_desc_list[4], &expected_uuid, sizeof(expected_uuid));
|
||||
uuid = spdk_nvme_ns_get_uuid(&ns);
|
||||
SPDK_CU_ASSERT_FATAL(uuid != NULL);
|
||||
CU_ASSERT(memcmp(uuid, &expected_uuid, sizeof(*uuid)) == 0);
|
||||
|
||||
/* UUID followed by NGUID */
|
||||
memset(ns.id_desc_list, 0, sizeof(ns.id_desc_list));
|
||||
ns.id_desc_list[0] = 0x03; /* NIDT == UUID */
|
||||
ns.id_desc_list[1] = 0x10; /* NIDL */
|
||||
memcpy(&ns.id_desc_list[4], &expected_uuid, sizeof(expected_uuid));
|
||||
ns.id_desc_list[20] = 0x02; /* NIDT == NGUID */
|
||||
ns.id_desc_list[21] = 0x10; /* NIDL */
|
||||
memset(&ns.id_desc_list[24], 0xCC, 0x10);
|
||||
uuid = spdk_nvme_ns_get_uuid(&ns);
|
||||
SPDK_CU_ASSERT_FATAL(uuid != NULL);
|
||||
CU_ASSERT(memcmp(uuid, &expected_uuid, sizeof(*uuid)) == 0);
|
||||
|
||||
/* NGUID followed by UUID */
|
||||
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] = 0x03; /* NIDT = UUID */
|
||||
ns.id_desc_list[21] = 0x10; /* NIDL */
|
||||
memcpy(&ns.id_desc_list[24], &expected_uuid, sizeof(expected_uuid));
|
||||
uuid = spdk_nvme_ns_get_uuid(&ns);
|
||||
SPDK_CU_ASSERT_FATAL(uuid != NULL);
|
||||
CU_ASSERT(memcmp(uuid, &expected_uuid, sizeof(*uuid)) == 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
@ -87,7 +143,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "test_nvme_ns", test_nvme_ns_construct) == NULL
|
||||
CU_add_test(suite, "test_nvme_ns", test_nvme_ns_construct) == NULL ||
|
||||
CU_add_test(suite, "test_nvme_ns_uuid", test_nvme_ns_uuid) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
x
Reference in New Issue
Block a user