nvmf: Add ZNS specific identify functions for NVMe-oF ZNS support

In order to connect to a zoned SPDK NVMe-oF target the ZNS specific
identify functions must be implemented and the supported ZNS opcodes
must be set accordingly.

Implementing ZNS specific identify functions to return the 'I/O Command
Set specific Identify Namespace data structure (CNS 05h)'
(`spdk_nvmf_ns_identify_iocs_specific`) and 'I/O Command Set specific
Identify Controller data structure (CNS 06h)'
(`spdk_nvmf_ctrlr_identify_iocs_specific`).

Those functions return a null filled data structure for any I/O Command
Set other than ZNS.

Signed-off-by: Dennis Maisenbacher <dennis.maisenbacher@wdc.com>
Change-Id: I6b9529ce0a86400afb01d4e09cbdb3e5c3a68514
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16044
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Dennis Maisenbacher 2022-12-15 14:50:03 +01:00 committed by Tomasz Zawadzki
parent 102d266d1a
commit a36785df71
9 changed files with 404 additions and 3 deletions

View File

@ -25,6 +25,42 @@ enum spdk_nvmf_request_exec_status {
int spdk_nvmf_ctrlr_identify_ctrlr(struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvme_ctrlr_data *cdata);
/**
* Fills the I/O Command Set specific Identify Namespace data structure (CNS
* 05h)
*
* \param ctrlr The NVMe-oF controller
* \param cmd The NVMe command
* \param rsp The NVMe command completion
* \param nsdata The filled in I/O command set specific identify namespace
* attributes
* \param nsdata_size The size of nsdata
* \return \ref spdk_nvmf_request_exec_status
*/
int spdk_nvmf_ns_identify_iocs_specific(struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvme_cmd *cmd,
struct spdk_nvme_cpl *rsp,
void *nsdata,
size_t nsdata_size);
/**
* Fills the I/O Command Set specific Identify Controller data structure (CNS
* 06h)
*
* \param ctrlr The NVMe-oF controller
* \param cmd The NVMe command
* \param rsp The NVMe command completion
* \param cdata The filled in I/O command set specific identify controller
* attributes
* \param cdata_size The size of cdata
* \return \ref spdk_nvmf_request_exec_status
*/
int spdk_nvmf_ctrlr_identify_iocs_specific(struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvme_cmd *cmd,
struct spdk_nvme_cpl *rsp,
void *cdata,
size_t cdata_size);
/**
* Fills the identify namespace attributes for the specified controller
*

View File

@ -9,6 +9,8 @@
#include "nvmf_internal.h"
#include "transport.h"
#include "spdk/bdev.h"
#include "spdk/bdev_zone.h"
#include "spdk/bit_array.h"
#include "spdk/endian.h"
#include "spdk/thread.h"
@ -371,6 +373,21 @@ nvmf_ctrlr_cdata_init(struct spdk_nvmf_transport *transport, struct spdk_nvmf_su
}
}
static bool
nvmf_subsys_has_multi_iocs(struct spdk_nvmf_subsystem *subsystem)
{
struct spdk_nvmf_ns *ns;
uint32_t i;
for (i = 0; i < subsystem->max_nsid; i++) {
ns = subsystem->ns[i];
if (ns && ns->bdev && spdk_bdev_is_zoned(ns->bdev)) {
return true;
}
}
return false;
}
static struct spdk_nvmf_ctrlr *
nvmf_ctrlr_create(struct spdk_nvmf_subsystem *subsystem,
struct spdk_nvmf_request *req,
@ -380,6 +397,7 @@ nvmf_ctrlr_create(struct spdk_nvmf_subsystem *subsystem,
struct spdk_nvmf_ctrlr *ctrlr;
struct spdk_nvmf_transport *transport = req->qpair->transport;
struct spdk_nvme_transport_id listen_trid = {};
bool subsys_has_multi_iocs = false;
ctrlr = calloc(1, sizeof(*ctrlr));
if (ctrlr == NULL) {
@ -477,7 +495,14 @@ nvmf_ctrlr_create(struct spdk_nvmf_subsystem *subsystem,
/* ready timeout - 500 msec units */
ctrlr->vcprop.cap.bits.to = NVMF_CTRLR_RESET_SHN_TIMEOUT_IN_MS / 500;
ctrlr->vcprop.cap.bits.dstrd = 0; /* fixed to 0 for NVMe-oF */
ctrlr->vcprop.cap.bits.css = SPDK_NVME_CAP_CSS_NVM; /* NVM command set */
subsys_has_multi_iocs = nvmf_subsys_has_multi_iocs(subsystem);
if (subsys_has_multi_iocs) {
ctrlr->vcprop.cap.bits.css =
SPDK_NVME_CAP_CSS_IOCS; /* One or more I/O command sets supported */
} else {
ctrlr->vcprop.cap.bits.css = SPDK_NVME_CAP_CSS_NVM; /* NVM command set */
}
ctrlr->vcprop.cap.bits.mpsmin = 0; /* 2 ^ (12 + mpsmin) == 4k */
ctrlr->vcprop.cap.bits.mpsmax = 0; /* 2 ^ (12 + mpsmax) == 4k */
@ -488,6 +513,10 @@ nvmf_ctrlr_create(struct spdk_nvmf_subsystem *subsystem,
ctrlr->vcprop.cc.raw = 0;
ctrlr->vcprop.cc.bits.en = 0; /* Init controller disabled */
if (subsys_has_multi_iocs) {
ctrlr->vcprop.cc.bits.css =
SPDK_NVME_CC_CSS_IOCS; /* All supported I/O Command Sets */
}
ctrlr->vcprop.csts.raw = 0;
ctrlr->vcprop.csts.bits.rdy = 0; /* Init controller as not ready */
@ -1238,8 +1267,11 @@ nvmf_prop_set_cc(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value)
}
if (diff.bits.css) {
SPDK_ERRLOG("I/O Command Set Selected (CSS) 0x%x not supported!\n", cc.bits.css);
return false;
if (cc.bits.css > SPDK_NVME_CC_CSS_IOCS) {
SPDK_ERRLOG("I/O Command Set Selected (CSS) 0x%x not supported!\n", cc.bits.css);
return false;
}
diff.bits.css = 0;
}
if (diff.raw != 0) {
@ -2812,6 +2844,108 @@ spdk_nvmf_ctrlr_identify_ctrlr(struct spdk_nvmf_ctrlr *ctrlr, struct spdk_nvme_c
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
static int
nvmf_ns_identify_iocs_zns(struct spdk_nvmf_ns *ns,
struct spdk_nvme_cmd *cmd,
struct spdk_nvme_cpl *rsp,
struct spdk_nvme_zns_ns_data *nsdata_zns)
{
nsdata_zns->zoc.variable_zone_capacity = 0;
nsdata_zns->zoc.zone_active_excursions = 0;
nsdata_zns->ozcs.read_across_zone_boundaries = 1;
/* Underflowing the zero based mar and mor bdev helper results in the correct
value of FFFFFFFFh. */
nsdata_zns->mar = spdk_bdev_get_max_active_zones(ns->bdev) - 1;
nsdata_zns->mor = spdk_bdev_get_max_open_zones(ns->bdev) - 1;
nsdata_zns->rrl = 0;
nsdata_zns->frl = 0;
nsdata_zns->lbafe[0].zsze = spdk_bdev_get_zone_size(ns->bdev);
rsp->status.sct = SPDK_NVME_SCT_GENERIC;
rsp->status.sc = SPDK_NVME_SC_SUCCESS;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
int
spdk_nvmf_ns_identify_iocs_specific(struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvme_cmd *cmd,
struct spdk_nvme_cpl *rsp,
void *nsdata,
size_t nsdata_size)
{
uint8_t csi = cmd->cdw11_bits.identify.csi;
struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys;
struct spdk_nvmf_ns *ns = _nvmf_subsystem_get_ns_safe(subsystem, cmd->nsid, rsp);
memset(nsdata, 0, nsdata_size);
if (ns == NULL) {
rsp->status.sct = SPDK_NVME_SCT_GENERIC;
rsp->status.sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
switch (csi) {
case SPDK_NVME_CSI_ZNS:
return nvmf_ns_identify_iocs_zns(ns, cmd, rsp, nsdata);
default:
break;
}
SPDK_DEBUGLOG(nvmf,
"Returning zero filled struct for the iocs specific ns "
"identify command and CSI 0x%02x\n",
csi);
rsp->status.sct = SPDK_NVME_SCT_GENERIC;
rsp->status.sc = SPDK_NVME_SC_SUCCESS;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
static int
nvmf_ctrlr_identify_iocs_zns(struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvme_cmd *cmd,
struct spdk_nvme_cpl *rsp,
struct spdk_nvme_zns_ctrlr_data *cdata_zns)
{
/* The unit of max_zone_append_size_kib is KiB.
The unit of zasl is the minimum memory page size
(2 ^ (12 + CAP.MPSMIN) KiB)
and is reported as a power of two (2^n). */
cdata_zns->zasl = spdk_u64log2(ctrlr->subsys->max_zone_append_size_kib >>
(12 + ctrlr->vcprop.cap.bits.mpsmin));
rsp->status.sct = SPDK_NVME_SCT_GENERIC;
rsp->status.sc = SPDK_NVME_SC_SUCCESS;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
int
spdk_nvmf_ctrlr_identify_iocs_specific(struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvme_cmd *cmd,
struct spdk_nvme_cpl *rsp,
void *cdata,
size_t cdata_size)
{
uint8_t csi = cmd->cdw11_bits.identify.csi;
memset(cdata, 0, cdata_size);
switch (csi) {
case SPDK_NVME_CSI_ZNS:
return nvmf_ctrlr_identify_iocs_zns(ctrlr, cmd, rsp, cdata);
default:
break;
}
SPDK_DEBUGLOG(nvmf,
"Returning zero filled struct for the iocs specific ctrlr "
"identify command and CSI 0x%02x\n",
csi);
rsp->status.sct = SPDK_NVME_SCT_GENERIC;
rsp->status.sc = SPDK_NVME_SC_SUCCESS;
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}
static int
nvmf_ctrlr_identify_active_ns_list(struct spdk_nvmf_subsystem *subsystem,
struct spdk_nvme_cmd *cmd,
@ -2900,6 +3034,7 @@ nvmf_ctrlr_identify_ns_id_descriptor_list(
ADD_ID_DESC(SPDK_NVME_NIDT_EUI64, ns->opts.eui64, sizeof(ns->opts.eui64));
ADD_ID_DESC(SPDK_NVME_NIDT_NGUID, ns->opts.nguid, sizeof(ns->opts.nguid));
ADD_ID_DESC(SPDK_NVME_NIDT_UUID, &ns->opts.uuid, sizeof(ns->opts.uuid));
ADD_ID_DESC(SPDK_NVME_NIDT_CSI, &ns->csi, sizeof(uint8_t));
/*
* The list is automatically 0-terminated, both in the temporary buffer
@ -2946,6 +3081,8 @@ nvmf_ctrlr_identify(struct spdk_nvmf_request *req)
*/
_init_copy_iovs_ctx(&copy_ctx, req->iov, req->iovcnt);
SPDK_DEBUGLOG(nvmf, "Received identify command with CNS 0x%02x\n", cns);
switch (cns) {
case SPDK_NVME_IDENTIFY_NS:
ret = spdk_nvmf_ctrlr_identify_ns(ctrlr, cmd, rsp, (void *)&tmpbuf);
@ -2960,6 +3097,12 @@ nvmf_ctrlr_identify(struct spdk_nvmf_request *req)
ret = nvmf_ctrlr_identify_ns_id_descriptor_list(subsystem, cmd, rsp,
tmpbuf, req->length);
break;
case SPDK_NVME_IDENTIFY_NS_IOCS:
ret = spdk_nvmf_ns_identify_iocs_specific(ctrlr, cmd, rsp, (void *)&tmpbuf, req->length);
break;
case SPDK_NVME_IDENTIFY_CTRLR_IOCS:
ret = spdk_nvmf_ctrlr_identify_iocs_specific(ctrlr, cmd, rsp, (void *)&tmpbuf, req->length);
break;
default:
goto invalid_cns;
}

View File

@ -165,6 +165,8 @@ struct spdk_nvmf_ns {
bool ptpl_activated;
/* ZCOPY supported on bdev device */
bool zcopy;
/* Command Set Identifier */
enum spdk_nvme_csi csi;
};
/*
@ -263,6 +265,10 @@ struct spdk_nvmf_subsystem {
bool destroying;
bool async_destroy;
/* Zoned storage related fields */
bool zone_append_supported;
uint64_t max_zone_append_size_kib;
struct spdk_nvmf_tgt *tgt;
/* Array of pointers to namespaces of size max_nsid indexed by nsid - 1 */

View File

@ -84,6 +84,7 @@
# public functions in nvmf_cmd.h
spdk_nvmf_ctrlr_identify_ctrlr;
spdk_nvmf_ctrlr_identify_iocs_specific;
spdk_nvmf_ctrlr_identify_ns;
spdk_nvmf_set_custom_admin_cmd_hdlr;
spdk_nvmf_set_passthru_admin_cmd;
@ -96,6 +97,7 @@
spdk_nvmf_request_get_response;
spdk_nvmf_request_get_req_to_abort;
spdk_nvmf_bdev_ctrlr_abort_cmd;
spdk_nvmf_ns_identify_iocs_specific;
# public functions in nvmf_transport.h
spdk_nvmf_transport_register;

View File

@ -18,6 +18,7 @@
#include "spdk/json.h"
#include "spdk/file.h"
#include "spdk/bit_array.h"
#include "spdk/bdev.h"
#define __SPDK_BDEV_MODULE_ONLY
#include "spdk/bdev_module.h"
@ -405,6 +406,19 @@ _nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem)
return 0;
}
static struct spdk_nvmf_ns *
_nvmf_subsystem_get_first_zoned_ns(struct spdk_nvmf_subsystem *subsystem)
{
struct spdk_nvmf_ns *ns = spdk_nvmf_subsystem_get_first_ns(subsystem);
while (ns != NULL) {
if (ns->csi == SPDK_NVME_CSI_ZNS) {
return ns;
}
ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns);
}
return NULL;
}
int
spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem, nvmf_subsystem_destroy_cb cpl_cb,
void *cpl_cb_arg)
@ -1578,6 +1592,8 @@ spdk_nvmf_subsystem_add_ns_ext(struct spdk_nvmf_subsystem *subsystem, const char
struct spdk_nvmf_ns *ns;
struct spdk_nvmf_reservation_info info = {0};
int rc;
bool zone_append_supported;
uint64_t max_zone_append_size_kib;
if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
@ -1680,6 +1696,26 @@ spdk_nvmf_subsystem_add_ns_ext(struct spdk_nvmf_subsystem *subsystem, const char
memcpy(opts.nguid, spdk_bdev_get_uuid(ns->bdev), sizeof(opts.nguid));
}
if (spdk_bdev_is_zoned(ns->bdev)) {
SPDK_DEBUGLOG(nvmf, "The added namespace is backed by a zoned block device.\n");
ns->csi = SPDK_NVME_CSI_ZNS;
zone_append_supported = spdk_bdev_io_type_supported(ns->bdev,
SPDK_BDEV_IO_TYPE_ZONE_APPEND);
max_zone_append_size_kib = spdk_bdev_get_max_zone_append_size(
ns->bdev) * spdk_bdev_get_block_size(ns->bdev);
if (_nvmf_subsystem_get_first_zoned_ns(subsystem) != NULL &&
(subsystem->zone_append_supported != zone_append_supported ||
subsystem->max_zone_append_size_kib != max_zone_append_size_kib)) {
SPDK_ERRLOG("Namespaces with different zone append support or different zone append size are not allowed.\n");
goto err_ns_reservation_restore;
}
subsystem->zone_append_supported = zone_append_supported;
subsystem->max_zone_append_size_kib = max_zone_append_size_kib;
}
ns->opts = opts;
ns->subsystem = subsystem;
subsystem->ns[opts.nsid - 1] = ns;

View File

@ -4,6 +4,8 @@
* Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include "spdk/bdev_zone.h"
#include "spdk/nvme_spec.h"
#include "spdk/stdinc.h"
#include "spdk_cunit.h"
@ -19,8 +21,16 @@ struct spdk_bdev {
int ut_mock;
uint64_t blockcnt;
uint32_t blocklen;
bool zoned;
uint32_t zone_size;
uint32_t max_open_zones;
uint32_t max_active_zones;
};
const uint32_t MAX_OPEN_ZONES = 12;
const uint32_t MAX_ACTIVE_ZONES = 34;
const uint32_t ZONE_SIZE = 56;
const char subsystem_default_sn[SPDK_NVME_CTRLR_SN_LEN + 1] = "subsys_default_sn";
const char subsystem_default_mn[SPDK_NVME_CTRLR_MN_LEN + 1] = "subsys_default_mn";
@ -194,6 +204,12 @@ DEFINE_STUB(spdk_bdev_reset, int, (struct spdk_bdev_desc *desc, struct spdk_io_c
spdk_bdev_io_completion_cb cb, void *cb_arg), 0);
DEFINE_STUB_V(spdk_bdev_free_io, (struct spdk_bdev_io *bdev_io));
DEFINE_STUB(spdk_bdev_get_max_active_zones, uint32_t, (const struct spdk_bdev *bdev),
MAX_ACTIVE_ZONES);
DEFINE_STUB(spdk_bdev_get_max_open_zones, uint32_t, (const struct spdk_bdev *bdev), MAX_OPEN_ZONES);
DEFINE_STUB(spdk_bdev_get_zone_size, uint64_t, (const struct spdk_bdev *bdev), ZONE_SIZE);
DEFINE_STUB(spdk_bdev_is_zoned, bool, (const struct spdk_bdev *bdev), false);
int
spdk_nvmf_qpair_disconnect(struct spdk_nvmf_qpair *qpair, nvmf_qpair_disconnect_cb cb_fn, void *ctx)
{
@ -1039,6 +1055,76 @@ test_identify_ns(void)
CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata)));
}
static void
test_identify_ns_iocs_specific(void)
{
struct spdk_nvmf_subsystem subsystem = {};
struct spdk_nvmf_transport transport = {};
struct spdk_nvmf_qpair admin_qpair = { .transport = &transport };
struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .admin_qpair = &admin_qpair };
struct spdk_nvme_cmd cmd = {};
struct spdk_nvme_cpl rsp = {};
struct spdk_nvme_zns_ns_data nsdata = {};
struct spdk_bdev bdev[2] = {{.blockcnt = 1234, .zoned = true, .zone_size = ZONE_SIZE, .max_open_zones = MAX_OPEN_ZONES, .max_active_zones = MAX_ACTIVE_ZONES}, {.blockcnt = 5678}};
struct spdk_nvmf_ns ns[2] = {{.bdev = &bdev[0]}, {.bdev = &bdev[1]}};
struct spdk_nvmf_ns *ns_arr[2] = {&ns[0], &ns[1]};
subsystem.ns = ns_arr;
subsystem.max_nsid = SPDK_COUNTOF(ns_arr);
cmd.cdw11_bits.identify.csi = SPDK_NVME_CSI_ZNS;
/* Invalid ZNS NSID 0 */
cmd.nsid = 0;
memset(&nsdata, 0xFF, sizeof(nsdata));
memset(&rsp, 0, sizeof(rsp));
CU_ASSERT(spdk_nvmf_ns_identify_iocs_specific(&ctrlr, &cmd, &rsp,
&nsdata, sizeof(nsdata)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT);
CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata)));
/* Valid ZNS NSID 1 */
cmd.nsid = 1;
memset(&nsdata, 0xFF, sizeof(nsdata));
memset(&rsp, 0, sizeof(rsp));
CU_ASSERT(spdk_nvmf_ns_identify_iocs_specific(&ctrlr, &cmd, &rsp,
&nsdata, sizeof(nsdata)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS);
CU_ASSERT(nsdata.ozcs.read_across_zone_boundaries == 1);
CU_ASSERT(nsdata.mar == MAX_ACTIVE_ZONES - 1);
CU_ASSERT(nsdata.mor == MAX_OPEN_ZONES - 1);
CU_ASSERT(nsdata.lbafe[0].zsze == ZONE_SIZE);
nsdata.ozcs.read_across_zone_boundaries = 0;
nsdata.mar = 0;
nsdata.mor = 0;
nsdata.lbafe[0].zsze = 0;
CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata)));
cmd.cdw11_bits.identify.csi = SPDK_NVME_CSI_NVM;
/* Valid NVM NSID 2 */
cmd.nsid = 2;
memset(&nsdata, 0xFF, sizeof(nsdata));
memset(&rsp, 0, sizeof(rsp));
CU_ASSERT(spdk_nvmf_ns_identify_iocs_specific(&ctrlr, &cmd, &rsp,
&nsdata, sizeof(nsdata)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS);
CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata)));
/* Invalid NVM NSID 3 */
cmd.nsid = 0;
memset(&nsdata, 0xFF, sizeof(nsdata));
memset(&rsp, 0, sizeof(rsp));
CU_ASSERT(spdk_nvmf_ns_identify_iocs_specific(&ctrlr, &cmd, &rsp,
&nsdata, sizeof(nsdata)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT);
CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata)));
}
static void
test_set_get_features(void)
{
@ -1587,6 +1673,77 @@ test_identify_ctrlr(void)
CU_ASSERT(cdata.nvmf_specific.ioccsz == expected_ioccsz);
}
static void
test_identify_ctrlr_iocs_specific(void)
{
struct spdk_nvmf_subsystem subsystem = { .max_zone_append_size_kib = 0 };
struct spdk_nvmf_registers vcprop = { .cap.bits.mpsmin = 0 };
struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .vcprop = vcprop };
struct spdk_nvme_cmd cmd = {};
struct spdk_nvme_cpl rsp = {};
struct spdk_nvme_zns_ctrlr_data ctrlr_data = {};
cmd.cdw11_bits.identify.csi = SPDK_NVME_CSI_ZNS;
/* ZNS max_zone_append_size_kib no limit */
memset(&ctrlr_data, 0xFF, sizeof(ctrlr_data));
memset(&rsp, 0, sizeof(rsp));
CU_ASSERT(spdk_nvmf_ctrlr_identify_iocs_specific(&ctrlr, &cmd, &rsp,
&ctrlr_data, sizeof(ctrlr_data)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS);
CU_ASSERT(ctrlr_data.zasl == 0);
CU_ASSERT(spdk_mem_all_zero(&ctrlr_data, sizeof(ctrlr_data)));
/* ZNS max_zone_append_size_kib = 4096 */
memset(&ctrlr_data, 0xFF, sizeof(ctrlr_data));
memset(&rsp, 0, sizeof(rsp));
subsystem.max_zone_append_size_kib = 4096;
CU_ASSERT(spdk_nvmf_ctrlr_identify_iocs_specific(&ctrlr, &cmd, &rsp,
&ctrlr_data, sizeof(ctrlr_data)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS);
CU_ASSERT(ctrlr_data.zasl == 0);
CU_ASSERT(spdk_mem_all_zero(&ctrlr_data, sizeof(ctrlr_data)));
/* ZNS max_zone_append_size_kib = 60000 */
memset(&ctrlr_data, 0xFF, sizeof(ctrlr_data));
memset(&rsp, 0, sizeof(rsp));
subsystem.max_zone_append_size_kib = 60000;
CU_ASSERT(spdk_nvmf_ctrlr_identify_iocs_specific(&ctrlr, &cmd, &rsp,
&ctrlr_data, sizeof(ctrlr_data)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS);
CU_ASSERT(ctrlr_data.zasl == 3);
ctrlr_data.zasl = 0;
CU_ASSERT(spdk_mem_all_zero(&ctrlr_data, sizeof(ctrlr_data)));
/* ZNS max_zone_append_size_kib = 60000; mpsmin = 2 */
memset(&ctrlr_data, 0xFF, sizeof(ctrlr_data));
memset(&rsp, 0, sizeof(rsp));
ctrlr.vcprop.cap.bits.mpsmin = 2;
subsystem.max_zone_append_size_kib = 60000;
CU_ASSERT(spdk_nvmf_ctrlr_identify_iocs_specific(&ctrlr, &cmd, &rsp,
&ctrlr_data, sizeof(ctrlr_data)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS);
CU_ASSERT(ctrlr_data.zasl == 1);
ctrlr_data.zasl = 0;
CU_ASSERT(spdk_mem_all_zero(&ctrlr_data, sizeof(ctrlr_data)));
ctrlr.vcprop.cap.bits.mpsmin = 0;
cmd.cdw11_bits.identify.csi = SPDK_NVME_CSI_NVM;
/* NVM */
memset(&ctrlr_data, 0xFF, sizeof(ctrlr_data));
memset(&rsp, 0, sizeof(rsp));
CU_ASSERT(spdk_nvmf_ctrlr_identify_iocs_specific(&ctrlr, &cmd, &rsp,
&ctrlr_data, sizeof(ctrlr_data)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS);
CU_ASSERT(spdk_mem_all_zero(&ctrlr_data, sizeof(ctrlr_data)));
}
static int
custom_admin_cmd_hdlr(struct spdk_nvmf_request *req)
{
@ -2899,6 +3056,7 @@ main(int argc, char **argv)
CU_ADD_TEST(suite, test_connect);
CU_ADD_TEST(suite, test_get_ns_id_desc_list);
CU_ADD_TEST(suite, test_identify_ns);
CU_ADD_TEST(suite, test_identify_ns_iocs_specific);
CU_ADD_TEST(suite, test_reservation_write_exclusive);
CU_ADD_TEST(suite, test_reservation_exclusive_access);
CU_ADD_TEST(suite, test_reservation_write_exclusive_regs_only_and_all_regs);
@ -2907,6 +3065,7 @@ main(int argc, char **argv)
CU_ADD_TEST(suite, test_get_dif_ctx);
CU_ADD_TEST(suite, test_set_get_features);
CU_ADD_TEST(suite, test_identify_ctrlr);
CU_ADD_TEST(suite, test_identify_ctrlr_iocs_specific);
CU_ADD_TEST(suite, test_custom_admin_cmd);
CU_ADD_TEST(suite, test_fused_compare_and_write);
CU_ADD_TEST(suite, test_multi_async_event_reqs);

View File

@ -76,6 +76,11 @@ DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice, int,
DEFINE_STUB(spdk_nvme_transport_id_trtype_str, const char *,
(enum spdk_nvme_transport_type trtype), NULL);
DEFINE_STUB(spdk_bdev_is_zoned, bool, (const struct spdk_bdev *bdev), false);
DEFINE_STUB(spdk_bdev_get_max_zone_append_size, uint32_t,
(const struct spdk_bdev *bdev), 0);
const char *
spdk_bdev_get_name(const struct spdk_bdev *bdev)
{

View File

@ -74,6 +74,12 @@ DEFINE_STUB(spdk_nvme_transport_id_trtype_str,
const char *,
(enum spdk_nvme_transport_type trtype), NULL);
DEFINE_STUB(spdk_bdev_is_zoned, bool,
(const struct spdk_bdev *bdev), false);
DEFINE_STUB(spdk_bdev_get_max_zone_append_size, uint32_t,
(const struct spdk_bdev *bdev), 0);
int
spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts)

View File

@ -7,6 +7,7 @@
#include "spdk/stdinc.h"
#include "spdk/nvmf_spec.h"
#include "spdk_cunit.h"
#include "spdk/bdev_zone.h"
#include "spdk_internal/mock.h"
@ -227,6 +228,13 @@ DEFINE_STUB(spdk_bdev_reset, int, (struct spdk_bdev_desc *desc, struct spdk_io_c
spdk_bdev_io_completion_cb cb, void *cb_arg), 0);
DEFINE_STUB_V(spdk_bdev_free_io, (struct spdk_bdev_io *bdev_io));
DEFINE_STUB(spdk_bdev_get_max_active_zones, uint32_t,
(const struct spdk_bdev *bdev), 0);
DEFINE_STUB(spdk_bdev_get_max_open_zones, uint32_t,
(const struct spdk_bdev *bdev), 0);
DEFINE_STUB(spdk_bdev_is_zoned, bool, (const struct spdk_bdev *bdev), false);
DEFINE_STUB(spdk_bdev_get_zone_size, uint64_t, (const struct spdk_bdev *bdev), 0);
struct spdk_io_channel *
spdk_accel_get_io_channel(void)
{