diff --git a/include/spdk/nvme_spec.h b/include/spdk/nvme_spec.h index 9f924420b..55a974edd 100644 --- a/include/spdk/nvme_spec.h +++ b/include/spdk/nvme_spec.h @@ -1356,6 +1356,18 @@ enum spdk_nvme_nvm_opcode { SPDK_NVME_OPC_RESERVATION_RELEASE = 0x15, }; +/** + * Zoned Namespace command set opcodes + * + * In addition to the opcodes of the NVM command set, the Zoned Namespace + * command set supports the following opcodes. + */ +enum spdk_nvme_zns_opcode { + SPDK_NVME_OPC_ZONE_MGMT_SEND = 0x79, + SPDK_NVME_OPC_ZONE_MGMT_RECV = 0x7a, + SPDK_NVME_OPC_ZONE_APPEND = 0x7d, +}; + /** * Data transfer (bits 1:0) of an NVMe opcode. * @@ -3057,6 +3069,15 @@ struct spdk_nvme_fw_commit { }; SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_fw_commit) == 4, "Incorrect size"); +/* ZNS Zone Send Action (ZSA) cdw13 */ +enum spdk_nvme_zns_zone_send_action { + SPDK_NVME_ZONE_CLOSE = 0x1, + SPDK_NVME_ZONE_FINISH = 0x2, + SPDK_NVME_ZONE_OPEN = 0x3, + SPDK_NVME_ZONE_RESET = 0x4, + SPDK_NVME_ZONE_OFFLINE = 0x5, +}; + #define spdk_nvme_cpl_is_error(cpl) \ ((cpl)->status.sc != SPDK_NVME_SC_SUCCESS || \ (cpl)->status.sct != SPDK_NVME_SCT_GENERIC) diff --git a/include/spdk/nvme_zns.h b/include/spdk/nvme_zns.h index 8e14b254d..807ec63e8 100644 --- a/include/spdk/nvme_zns.h +++ b/include/spdk/nvme_zns.h @@ -74,6 +74,91 @@ const struct spdk_nvme_zns_ns_data *spdk_nvme_zns_ns_get_data(struct spdk_nvme_n */ const struct spdk_nvme_zns_ctrlr_data *spdk_nvme_zns_ctrlr_get_data(struct spdk_nvme_ctrlr *ctrlr); +/** + * Submit a Close Zone operation to the specified NVMe namespace. + * + * \param ns Namespace. + * \param qpair I/O queue pair to submit the request. + * \param slba starting LBA of the zone to operate on. + * \param select_all If this is set, slba will be ignored, and operation will + * be performed on all zones that are in ZSIO or ZSEO state. + * \param cb_fn Callback function invoked when the I/O command completes. + * \param cb_arg Argument passed to callback function. + * + * \return 0 on success. Negated errno on failure. + */ +int spdk_nvme_zns_close_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint64_t slba, bool select_all, + spdk_nvme_cmd_cb cb_fn, void *cb_arg); + +/** + * Submit a Finish Zone operation to the specified NVMe namespace. + * + * \param ns Namespace. + * \param qpair I/O queue pair to submit the request. + * \param slba starting LBA of the zone to operate on. + * \param select_all If this is set, slba will be ignored, and operation will + * be performed on all zones that are in ZSIO, ZSEO, or ZSC state. + * \param cb_fn Callback function invoked when the I/O command completes. + * \param cb_arg Argument passed to callback function. + * + * \return 0 on success. Negated errno on failure. + */ +int spdk_nvme_zns_finish_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint64_t slba, bool select_all, + spdk_nvme_cmd_cb cb_fn, void *cb_arg); + +/** + * Submit a Open Zone operation to the specified NVMe namespace. + * + * \param ns Namespace. + * \param qpair I/O queue pair to submit the request. + * \param slba starting LBA of the zone to operate on. + * \param select_all If this is set, slba will be ignored, and operation will + * be performed on all zones that are in ZSC state. + * \param cb_fn Callback function invoked when the I/O command completes. + * \param cb_arg Argument passed to callback function. + * + * \return 0 on success. Negated errno on failure. + */ +int spdk_nvme_zns_open_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint64_t slba, bool select_all, + spdk_nvme_cmd_cb cb_fn, void *cb_arg); + +/** + * Submit a Reset Zone operation to the specified NVMe namespace. + * + * \param ns Namespace. + * \param qpair I/O queue pair to submit the request. + * \param slba starting LBA of the zone to operate on. + * \param select_all If this is set, slba will be ignored, and operation will + * be performed on all zones that are in ZSIO, ZSEO, ZSC, or ZSF state. + * \param cb_fn Callback function invoked when the I/O command completes. + * \param cb_arg Argument passed to callback function. + * + * \return 0 on success. Negated errno on failure. + */ +int spdk_nvme_zns_reset_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint64_t slba, bool select_all, + spdk_nvme_cmd_cb cb_fn, void *cb_arg); + +/** + * Submit a Offline Zone operation to the specified NVMe namespace. + * + * \param ns Namespace. + * \param qpair I/O queue pair to submit the request. + * \param slba starting LBA of the zone to operate on. + * \param select_all If this is set, slba will be ignored, and operation will + * be performed on all zones that are in ZSRO state. + * \param cb_fn Callback function invoked when the I/O command completes. + * \param cb_arg Argument passed to callback function. + * + * \return 0 on success. Negated errno on failure. + */ +int spdk_nvme_zns_offline_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint64_t slba, bool select_all, + spdk_nvme_cmd_cb cb_fn, void *cb_arg); + #ifdef __cplusplus } #endif diff --git a/lib/nvme/nvme_zns.c b/lib/nvme/nvme_zns.c index 5f4d42ff5..025aae1cb 100644 --- a/lib/nvme/nvme_zns.c +++ b/lib/nvme/nvme_zns.c @@ -44,3 +44,69 @@ spdk_nvme_zns_ctrlr_get_data(struct spdk_nvme_ctrlr *ctrlr) { return ctrlr->cdata_zns; } + +static int +nvme_zns_zone_mgmt_send(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + uint64_t slba, bool select_all, uint8_t zone_send_action, + spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + struct nvme_request *req; + struct spdk_nvme_cmd *cmd; + + req = nvme_allocate_request_null(qpair, cb_fn, cb_arg); + if (req == NULL) { + return -ENOMEM; + } + + cmd = &req->cmd; + cmd->opc = SPDK_NVME_OPC_ZONE_MGMT_SEND; + cmd->nsid = ns->id; + + if (!select_all) { + *(uint64_t *)&cmd->cdw10 = slba; + } + + cmd->cdw13 = zone_send_action | select_all << 8; + + return nvme_qpair_submit_request(qpair, req); +} + +int +spdk_nvme_zns_close_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, + bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_CLOSE, + cb_fn, cb_arg); +} + +int +spdk_nvme_zns_finish_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, + bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_FINISH, + cb_fn, cb_arg); +} + +int +spdk_nvme_zns_open_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, + bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_OPEN, + cb_fn, cb_arg); +} + +int +spdk_nvme_zns_reset_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, + bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_RESET, + cb_fn, cb_arg); +} + +int +spdk_nvme_zns_offline_zone(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba, + bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + return nvme_zns_zone_mgmt_send(ns, qpair, slba, select_all, SPDK_NVME_ZONE_OFFLINE, + cb_fn, cb_arg); +} diff --git a/lib/nvme/spdk_nvme.map b/lib/nvme/spdk_nvme.map index fba506b73..eac6b5c1a 100644 --- a/lib/nvme/spdk_nvme.map +++ b/lib/nvme/spdk_nvme.map @@ -159,6 +159,11 @@ # public functions from nvme_zns.h spdk_nvme_zns_ns_get_data; spdk_nvme_zns_ctrlr_get_data; + spdk_nvme_zns_close_zone; + spdk_nvme_zns_finish_zone; + spdk_nvme_zns_open_zone; + spdk_nvme_zns_reset_zone; + spdk_nvme_zns_offline_zone; # public functions from nvme_ocssd.h spdk_nvme_ctrlr_is_ocssd_supported;