diff --git a/examples/nvme/identify/identify.c b/examples/nvme/identify/identify.c index c6fb20e70..1bbe8840d 100644 --- a/examples/nvme/identify/identify.c +++ b/examples/nvme/identify/identify.c @@ -36,6 +36,7 @@ #include "spdk/endian.h" #include "spdk/log.h" #include "spdk/nvme.h" +#include "spdk/nvme_ocssd.h" #include "spdk/env.h" #include "spdk/nvme_intel.h" #include "spdk/nvmf_spec.h" @@ -73,6 +74,8 @@ 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 struct spdk_ocssd_geometry_data geometry_data; + static bool g_hex_dump = false; static int g_shm_id = -1; @@ -157,6 +160,15 @@ get_log_page_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl) outstanding_commands--; } +static void +get_ocssd_geometry_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl) +{ + if (spdk_nvme_cpl_is_error(cpl)) { + printf("get ocssd geometry failed\n"); + } + outstanding_commands--; +} + static int get_feature(struct spdk_nvme_ctrlr *ctrlr, uint8_t fid) { @@ -448,6 +460,26 @@ get_log_pages(struct spdk_nvme_ctrlr *ctrlr) } } +static void +get_ocssd_geometry(struct spdk_nvme_ns *ns, struct spdk_ocssd_geometry_data *geometry_data) +{ + struct spdk_nvme_ctrlr *ctrlr = spdk_nvme_ns_get_ctrlr(ns); + int nsid = spdk_nvme_ns_get_id(ns); + outstanding_commands = 0; + + if (spdk_nvme_ocssd_ctrlr_cmd_geometry(ctrlr, nsid, geometry_data, + sizeof(*geometry_data), get_ocssd_geometry_completion, NULL)) { + printf("Get OpenChannel SSD geometry failed\n"); + exit(1); + } else { + outstanding_commands++; + } + + while (outstanding_commands) { + spdk_nvme_ctrlr_process_admin_completions(ctrlr); + } +} + static void print_hex_be(const void *v, size_t size) { @@ -516,6 +548,44 @@ print_ascii_string(const void *buf, size_t size) } } +static void +print_ocssd_geometry(struct spdk_ocssd_geometry_data *geometry_data) +{ + printf("Namespace OCSSD Geometry\n"); + printf("=======================\n"); + + if (geometry_data->mjr < 2) { + printf("Open-Channel Spec version is less than 2.0\n"); + printf("OC version: maj:%d\n", geometry_data->mjr); + return; + } + + printf("OC version: maj:%d min:%d\n", geometry_data->mjr, geometry_data->mnr); + printf("LBA format:\n"); + printf(" Group bits: %d\n", geometry_data->lbaf.grp_len); + printf(" PU bits: %d\n", geometry_data->lbaf.pu_len); + printf(" Chunk bits: %d\n", geometry_data->lbaf.chk_len); + printf(" Logical block bits: %d\n", geometry_data->lbaf.lbk_len); + + printf("Media and Controller Capabilities:\n"); + printf(" Namespace supports Vector Chunk Copy: %s\n", + geometry_data->mccap.vec_chk_cpy ? "Supported" : "Not Supported"); + printf(" Namespace supports multiple resets a free chunk: %s\n", + geometry_data->mccap.multi_reset ? "Supported" : "Not Supported"); + + printf("Wear-level Index Delta Threshold: %d\n", geometry_data->wit); + printf("Groups (channels): %d\n", geometry_data->num_grp); + printf("PUs (LUNs) per group: %d\n", geometry_data->num_pu); + printf("Chunks per LUN: %d\n", geometry_data->num_chk); + printf("Logical blks per chunk: %d\n", geometry_data->clba); + printf("MIN write size: %d\n", geometry_data->ws_min); + printf("OPT write size: %d\n", geometry_data->ws_opt); + printf("Cache min write size: %d\n", geometry_data->mw_cunits); + printf("Max open chunks: %d\n", geometry_data->maxoc); + printf("Max open chunks per PU: %d\n", geometry_data->maxocpu); + printf("\n"); +} + static void print_namespace(struct spdk_nvme_ns *ns) { @@ -611,6 +681,11 @@ print_namespace(struct spdk_nvme_ns *ns) printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d\n", i, 1 << nsdata->lbaf[i].lbads, nsdata->lbaf[i].ms); printf("\n"); + + if (spdk_nvme_ctrlr_is_ocssd_supported(spdk_nvme_ns_get_ctrlr(ns))) { + get_ocssd_geometry(ns, &geometry_data); + print_ocssd_geometry(&geometry_data); + } } static const char *