nvme: add function to check if controller supports zone append

Zone append is an optional command in the Zoned Namespace Command Set.
Add a convenience function to check if the controller supports the zone
append command.

The ratified NVMe TP 4056 added a CSI field (in cdw14) to the Get Log Page
command. However, since there already exist two public functions to get a
log page (spdk_nvme_ctrlr_cmd_get_log_page() and
spdk_nvme_ctrlr_cmd_get_log_page_ext()), avoid creating a third one for
now, since nvme_ctrlr_get_zns_cmd_and_effects_log() itself can leverage
one of the existing public functions.

Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
Change-Id: I99516dbac8db6714488b4d6cabe64c27f46d6153
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5078
Community-CI: Broadcom CI
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
This commit is contained in:
Niklas Cassel 2020-11-10 13:10:24 +00:00 committed by Tomasz Zawadzki
parent 35596d34b0
commit 38d59d8b5a
4 changed files with 95 additions and 1 deletions

View File

@ -425,6 +425,7 @@ enum spdk_nvme_ctrlr_flags {
SPDK_NVME_CTRLR_WRR_SUPPORTED = 1 << 2, /**< Weighted Round Robin is supported */
SPDK_NVME_CTRLR_COMPARE_AND_WRITE_SUPPORTED = 1 << 3, /**< Compare and write fused operations supported */
SPDK_NVME_CTRLR_SGL_REQUIRES_DWORD_ALIGNMENT = 1 << 4, /**< Dword alignment is required for SGL */
SPDK_NVME_CTRLR_ZONE_APPEND_SUPPORTED = 1 << 5, /**< Zone Append is supported (within Zoned Namespaces) */
};
/**

View File

@ -1160,6 +1160,10 @@ nvme_ctrlr_state_string(enum nvme_ctrlr_state state)
return "identify controller iocs specific";
case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_IOCS_SPECIFIC:
return "wait for identify controller iocs specific";
case NVME_CTRLR_STATE_GET_ZNS_CMD_EFFECTS_LOG:
return "get zns cmd and effects log page";
case NVME_CTRLR_STATE_WAIT_FOR_GET_ZNS_CMD_EFFECTS_LOG:
return "wait for get zns cmd and effects log page";
case NVME_CTRLR_STATE_SET_NUM_QUEUES:
return "set number of queues";
case NVME_CTRLR_STATE_WAIT_FOR_SET_NUM_QUEUES:
@ -1592,6 +1596,64 @@ nvme_ctrlr_identify(struct spdk_nvme_ctrlr *ctrlr)
return 0;
}
static void
nvme_ctrlr_get_zns_cmd_and_effects_log_done(void *arg, const struct spdk_nvme_cpl *cpl)
{
struct spdk_nvme_cmds_and_effect_log_page *log_page;
struct spdk_nvme_ctrlr *ctrlr = arg;
if (spdk_nvme_cpl_is_error(cpl)) {
SPDK_ERRLOG("nvme_ctrlr_get_zns_cmd_and_effects_log failed!\n");
spdk_free(ctrlr->tmp_ptr);
ctrlr->tmp_ptr = NULL;
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_ERROR, NVME_TIMEOUT_INFINITE);
return;
}
log_page = ctrlr->tmp_ptr;
if (log_page->io_cmds_supported[SPDK_NVME_OPC_ZONE_APPEND].csupp) {
ctrlr->flags |= SPDK_NVME_CTRLR_ZONE_APPEND_SUPPORTED;
}
spdk_free(ctrlr->tmp_ptr);
ctrlr->tmp_ptr = NULL;
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_SET_NUM_QUEUES, ctrlr->opts.admin_timeout_ms);
}
static int
nvme_ctrlr_get_zns_cmd_and_effects_log(struct spdk_nvme_ctrlr *ctrlr)
{
int rc;
assert(!ctrlr->tmp_ptr);
ctrlr->tmp_ptr = spdk_zmalloc(sizeof(struct spdk_nvme_cmds_and_effect_log_page), 64, NULL,
SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_SHARE | SPDK_MALLOC_DMA);
if (!ctrlr->tmp_ptr) {
rc = -ENOMEM;
goto error;
}
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_WAIT_FOR_GET_ZNS_CMD_EFFECTS_LOG,
ctrlr->opts.admin_timeout_ms);
rc = spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_COMMAND_EFFECTS_LOG,
0, ctrlr->tmp_ptr, sizeof(struct spdk_nvme_cmds_and_effect_log_page),
0, 0, 0, SPDK_NVME_CSI_ZNS << 24,
nvme_ctrlr_get_zns_cmd_and_effects_log_done, ctrlr);
if (rc != 0) {
goto error;
}
return 0;
error:
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_ERROR, NVME_TIMEOUT_INFINITE);
spdk_free(ctrlr->tmp_ptr);
ctrlr->tmp_ptr = NULL;
return rc;
}
static void
nvme_ctrlr_identify_zns_specific_done(void *arg, const struct spdk_nvme_cpl *cpl)
{
@ -1600,9 +1662,12 @@ nvme_ctrlr_identify_zns_specific_done(void *arg, const struct spdk_nvme_cpl *cpl
if (spdk_nvme_cpl_is_error(cpl)) {
/* no need to print an error, the controller simply does not support ZNS */
nvme_ctrlr_free_zns_specific_data(ctrlr);
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_SET_NUM_QUEUES,
ctrlr->opts.admin_timeout_ms);
return;
}
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_SET_NUM_QUEUES,
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_GET_ZNS_CMD_EFFECTS_LOG,
ctrlr->opts.admin_timeout_ms);
}
@ -3053,6 +3118,10 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr)
rc = nvme_ctrlr_identify_iocs_specific(ctrlr);
break;
case NVME_CTRLR_STATE_GET_ZNS_CMD_EFFECTS_LOG:
rc = nvme_ctrlr_get_zns_cmd_and_effects_log(ctrlr);
break;
case NVME_CTRLR_STATE_SET_NUM_QUEUES:
nvme_ctrlr_update_nvmf_ioccsz(ctrlr);
rc = nvme_ctrlr_set_num_queues(ctrlr);
@ -3118,6 +3187,7 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr)
case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY:
case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_IOCS_SPECIFIC:
case NVME_CTRLR_STATE_WAIT_FOR_GET_ZNS_CMD_EFFECTS_LOG:
case NVME_CTRLR_STATE_WAIT_FOR_SET_NUM_QUEUES:
case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_ACTIVE_NS:
case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_NS:

View File

@ -548,6 +548,16 @@ enum nvme_ctrlr_state {
*/
NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_IOCS_SPECIFIC,
/**
* Get Commands Supported and Effects log page for the Zoned Namespace Command Set.
*/
NVME_CTRLR_STATE_GET_ZNS_CMD_EFFECTS_LOG,
/**
* Waiting for the Get Log Page command to be completed.
*/
NVME_CTRLR_STATE_WAIT_FOR_GET_ZNS_CMD_EFFECTS_LOG,
/**
* Set Number of Queues of the controller.
*/
@ -835,6 +845,9 @@ struct spdk_nvme_ctrlr {
struct spdk_nvme_ana_page *ana_log_page;
uint32_t ana_log_page_size;
/* scratchpad pointer that can be used to send data between two NVME_CTRLR_STATEs */
void *tmp_ptr;
};
struct spdk_nvme_probe_ctx {

View File

@ -257,6 +257,16 @@ spdk_nvme_ctrlr_cmd_get_log_page(struct spdk_nvme_ctrlr *ctrlr, uint8_t log_page
return 0;
}
int
spdk_nvme_ctrlr_cmd_get_log_page_ext(struct spdk_nvme_ctrlr *ctrlr, uint8_t log_page,
uint32_t nsid, void *payload, uint32_t payload_size,
uint64_t offset, uint32_t cdw10, uint32_t cdw11,
uint32_t cdw14, spdk_nvme_cmd_cb cb_fn, void *cb_arg)
{
fake_cpl_sc(cb_fn, cb_arg);
return 0;
}
int
nvme_qpair_submit_request(struct spdk_nvme_qpair *qpair, struct nvme_request *req)
{