From 4b55682e3a006a2b14e69cca66b0f08c3061c37f Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Thu, 28 Feb 2019 22:49:26 -0500 Subject: [PATCH] nvmf: add namespace reservation report command support For number of registered controllers field in Reservation Status Data Structure, we caculate all the controllers in the subsystem which Host Identifier are same with existing registrants. Change-Id: Ib4de22c7020dbd8294f448f23c0c5c8c142629dd Signed-off-by: Changpeng Liu Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/436939 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- lib/nvmf/ctrlr.c | 1 + lib/nvmf/subsystem.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/lib/nvmf/ctrlr.c b/lib/nvmf/ctrlr.c index 41fac1335..16a39a3bf 100644 --- a/lib/nvmf/ctrlr.c +++ b/lib/nvmf/ctrlr.c @@ -2130,6 +2130,7 @@ spdk_nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req) case SPDK_NVME_OPC_RESERVATION_REGISTER: case SPDK_NVME_OPC_RESERVATION_ACQUIRE: case SPDK_NVME_OPC_RESERVATION_RELEASE: + case SPDK_NVME_OPC_RESERVATION_REPORT: spdk_thread_send_msg(ctrlr->subsys->thread, spdk_nvmf_ns_reservation_request, req); return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; default: diff --git a/lib/nvmf/subsystem.c b/lib/nvmf/subsystem.c index 275863a5b..cd9949574 100644 --- a/lib/nvmf/subsystem.c +++ b/lib/nvmf/subsystem.c @@ -1705,6 +1705,76 @@ exit: return; } +static void +nvmf_ns_reservation_report(struct spdk_nvmf_ns *ns, + struct spdk_nvmf_ctrlr *ctrlr, + struct spdk_nvmf_request *req) +{ + struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; + struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys; + struct spdk_nvmf_ctrlr *ctrlr_tmp; + struct spdk_nvmf_registrant *reg, *tmp; + struct spdk_nvme_reservation_status_extended_data *status_data; + struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data; + uint8_t *payload; + uint32_t len, count = 0; + uint32_t regctl = 0; + uint8_t status = SPDK_NVME_SC_SUCCESS; + + /* NVMeoF uses Extended Data Structure */ + if ((cmd->cdw11 & 0x00000001u) == 0) { + SPDK_ERRLOG("NVMeoF uses extended controller data structure, " + "please set EDS bit in cdw11 and try again\n"); + status = SPDK_NVME_SC_INVALID_FIELD; + goto exit; + } + + /* Get number of registerd controllers, one Host may have more than + * one controller based on different ports. + */ + TAILQ_FOREACH(ctrlr_tmp, &subsystem->ctrlrs, link) { + reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr_tmp->hostid); + if (reg) { + regctl++; + } + } + + len = sizeof(*status_data) + sizeof(*ctrlr_data) * regctl; + payload = calloc(1, len); + if (!payload) { + status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; + goto exit; + } + + status_data = (struct spdk_nvme_reservation_status_extended_data *)payload; + status_data->data.gen = ns->gen; + status_data->data.rtype = ns->rtype; + status_data->data.regctl = regctl; + /* TODO: Don't support Persist Through Power Loss State for now */ + status_data->data.ptpls = 0; + + TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) { + assert(count <= regctl); + ctrlr_data = (struct spdk_nvme_registered_ctrlr_extended_data *) + (payload + sizeof(*status_data) + sizeof(*ctrlr_data) * count); + /* Set to 0xffffh for dynamic controller */ + ctrlr_data->cntlid = 0xffff; + ctrlr_data->rcsts.status = (ns->holder == reg) ? true : false; + ctrlr_data->rkey = reg->rkey; + spdk_uuid_copy((struct spdk_uuid *)ctrlr_data->hostid, ®->hostid); + count++; + } + + memcpy(req->data, payload, spdk_min(len, (cmd->cdw10 + 1) * sizeof(uint32_t))); + free(payload); + +exit: + req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; + req->rsp->nvme_cpl.status.sc = status; + return; +} + + static void spdk_nvmf_ns_reservation_complete(void *ctx) { @@ -1737,6 +1807,9 @@ spdk_nvmf_ns_reservation_request(void *ctx) case SPDK_NVME_OPC_RESERVATION_RELEASE: nvmf_ns_reservation_release(ns, ctrlr, req); break; + case SPDK_NVME_OPC_RESERVATION_REPORT: + nvmf_ns_reservation_report(ns, ctrlr, req); + break; default: break; }