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:
parent
102d266d1a
commit
a36785df71
@ -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
|
||||
*
|
||||
|
149
lib/nvmf/ctrlr.c
149
lib/nvmf/ctrlr.c
@ -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(©_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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user