examples/nvme/identify: print zone report excerpt for zoned namespaces
If the namespace is a zoned namespace, get and print a zone report. Since a ZNS drive can have thousands of zones, request a zone report containing only the first 8 zones. The code does take a ZNS drive with less than 8 zones into account, even though such a drive is unlikely to exist in the wild. Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com> Change-Id: I28ecb4d7c60ab5a911d7b1faae595f43ef6706e1 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4794 Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Broadcom CI
This commit is contained in:
parent
6dec7623be
commit
3301f8214b
@ -38,6 +38,7 @@
|
||||
#include "spdk/nvme.h"
|
||||
#include "spdk/vmd.h"
|
||||
#include "spdk/nvme_ocssd.h"
|
||||
#include "spdk/nvme_zns.h"
|
||||
#include "spdk/env.h"
|
||||
#include "spdk/nvme_intel.h"
|
||||
#include "spdk/nvmf_spec.h"
|
||||
@ -49,6 +50,7 @@
|
||||
#define MAX_DISCOVERY_LOG_ENTRIES ((uint64_t)1000)
|
||||
|
||||
#define NUM_CHUNK_INFO_ENTRIES 8
|
||||
#define MAX_ZONE_DESC_ENTRIES 8
|
||||
|
||||
static int outstanding_commands;
|
||||
|
||||
@ -85,6 +87,10 @@ static struct spdk_ocssd_geometry_data geometry_data;
|
||||
|
||||
static struct spdk_ocssd_chunk_information_entry g_ocssd_chunk_info_page[NUM_CHUNK_INFO_ENTRIES ];
|
||||
|
||||
static struct spdk_nvme_zns_zone_report *g_zone_report;
|
||||
static size_t g_zone_report_size;
|
||||
static uint64_t g_nr_zones_requested;
|
||||
|
||||
static bool g_hex_dump = false;
|
||||
|
||||
static int g_shm_id = -1;
|
||||
@ -149,6 +155,15 @@ hex_dump(const void *data, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exit_and_free_qpair(struct spdk_nvme_qpair *qpair)
|
||||
{
|
||||
if (qpair) {
|
||||
spdk_nvme_ctrlr_free_io_qpair(qpair);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
get_feature_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
@ -182,6 +197,27 @@ get_ocssd_geometry_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
|
||||
outstanding_commands--;
|
||||
}
|
||||
|
||||
static void
|
||||
get_zns_zone_report_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct spdk_nvme_qpair *qpair = cb_arg;
|
||||
|
||||
if (spdk_nvme_cpl_is_error(cpl)) {
|
||||
printf("get zns zone report failed\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we requested a partial report, verify that the firmware returned the
|
||||
* correct number of zones.
|
||||
*/
|
||||
if (g_zone_report->nr_zones != g_nr_zones_requested) {
|
||||
printf("Invalid number of zones returned: %"PRIu64" (expected: %"PRIu64")\n",
|
||||
g_zone_report->nr_zones, g_nr_zones_requested);
|
||||
exit_and_free_qpair(qpair);
|
||||
}
|
||||
outstanding_commands--;
|
||||
}
|
||||
|
||||
static int
|
||||
get_feature(struct spdk_nvme_ctrlr *ctrlr, uint8_t fid)
|
||||
{
|
||||
@ -565,6 +601,39 @@ get_ocssd_geometry(struct spdk_nvme_ns *ns, struct spdk_ocssd_geometry_data *geo
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_zns_zone_report(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair)
|
||||
{
|
||||
g_nr_zones_requested = spdk_nvme_zns_ns_get_num_zones(ns);
|
||||
/*
|
||||
* Rather than getting the whole zone report, which could contain thousands of zones,
|
||||
* get maximum MAX_ZONE_DESC_ENTRIES, so that we don't flood stdout.
|
||||
*/
|
||||
g_nr_zones_requested = spdk_min(g_nr_zones_requested, MAX_ZONE_DESC_ENTRIES);
|
||||
outstanding_commands = 0;
|
||||
|
||||
g_zone_report_size = sizeof(struct spdk_nvme_zns_zone_report) +
|
||||
g_nr_zones_requested * sizeof(struct spdk_nvme_zns_zone_desc);
|
||||
g_zone_report = calloc(1, g_zone_report_size);
|
||||
if (g_zone_report == NULL) {
|
||||
printf("Zone report allocation failed!\n");
|
||||
exit_and_free_qpair(qpair);
|
||||
}
|
||||
|
||||
if (spdk_nvme_zns_report_zones(ns, qpair, g_zone_report, g_zone_report_size,
|
||||
0, SPDK_NVME_ZRA_LIST_ALL, true,
|
||||
get_zns_zone_report_completion, qpair)) {
|
||||
printf("spdk_nvme_zns_report_zones() failed\n");
|
||||
exit_and_free_qpair(qpair);
|
||||
} else {
|
||||
outstanding_commands++;
|
||||
}
|
||||
|
||||
while (outstanding_commands) {
|
||||
spdk_nvme_qpair_process_completions(qpair, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_hex_be(const void *v, size_t size)
|
||||
{
|
||||
@ -700,6 +769,23 @@ print_ocssd_geometry(struct spdk_ocssd_geometry_data *geometry_data)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_zns_zone_report(void)
|
||||
{
|
||||
uint64_t i;
|
||||
|
||||
printf("NVMe ZNS Zone Report Glance\n");
|
||||
printf("===========================\n");
|
||||
|
||||
for (i = 0; i < g_zone_report->nr_zones; i++) {
|
||||
struct spdk_nvme_zns_zone_desc *desc = &g_zone_report->descs[i];
|
||||
printf("Zone: %"PRIu64" ZSLBA: 0x%016"PRIx64" ZCAP: 0x%016"PRIx64" WP: 0x%016"PRIx64" ZS: %x ZT: %x ZA: %x\n",
|
||||
i, desc->zslba, desc->zcap, desc->wp, desc->zs >> 4, desc->zt, desc->za);
|
||||
}
|
||||
free(g_zone_report);
|
||||
g_zone_report = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
|
||||
{
|
||||
@ -823,6 +909,15 @@ print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
|
||||
print_ocssd_geometry(&geometry_data);
|
||||
get_ocssd_chunk_info_log_page(ns);
|
||||
print_ocssd_chunk_info(g_ocssd_chunk_info_page, NUM_CHUNK_INFO_ENTRIES);
|
||||
} else if (spdk_nvme_ns_get_csi(ns) == SPDK_NVME_CSI_ZNS) {
|
||||
struct spdk_nvme_qpair *qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
|
||||
if (qpair == NULL) {
|
||||
printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
get_zns_zone_report(ns, qpair);
|
||||
print_zns_zone_report();
|
||||
spdk_nvme_ctrlr_free_io_qpair(qpair);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user