nvmf: add namespace reservation release command support

The reservation holder may release the reservation on
a namespace, release notification feature is supported
in comming patches.

Change-Id: If5d3158e691fcc782f7cf0b67a326bf62edf0531
Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/436938
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Changpeng Liu 2019-02-28 21:14:24 -05:00
parent ef7827dc06
commit 84ee3a62c7
2 changed files with 90 additions and 3 deletions

View File

@ -2129,6 +2129,7 @@ spdk_nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req)
return spdk_nvmf_bdev_ctrlr_dsm_cmd(bdev, desc, ch, req);
case SPDK_NVME_OPC_RESERVATION_REGISTER:
case SPDK_NVME_OPC_RESERVATION_ACQUIRE:
case SPDK_NVME_OPC_RESERVATION_RELEASE:
spdk_thread_send_msg(ctrlr->subsys->thread, spdk_nvmf_ns_reservation_request, req);
return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS;
default:

View File

@ -1335,6 +1335,14 @@ nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns,
return 0;
}
static void
nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns)
{
ns->rtype = 0;
ns->crkey = 0;
ns->holder = NULL;
}
/* release the reservation if the last registrant was removed */
static void
nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns,
@ -1354,9 +1362,7 @@ nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns,
ns->holder = next_reg;
} else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
/* release the reservation */
ns->rtype = 0;
ns->crkey = 0;
ns->holder = NULL;
nvmf_ns_reservation_release_reservation(ns);
}
}
@ -1403,6 +1409,19 @@ nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns,
return count;
}
static uint32_t
nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns)
{
struct spdk_nvmf_registrant *reg, *reg_tmp;
uint32_t count = 0;
TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) {
nvmf_ns_reservation_remove_registrant(ns, reg);
count++;
}
return count;
}
static void
nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey,
enum spdk_nvme_reservation_type rtype,
@ -1609,6 +1628,70 @@ exit:
return;
}
static void
nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvmf_request *req)
{
struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
uint8_t rrela, iekey, rtype;
struct spdk_nvmf_registrant *reg;
uint64_t crkey;
uint8_t status = SPDK_NVME_SC_SUCCESS;
rrela = cmd->cdw10 & 0x7u;
iekey = (cmd->cdw10 >> 3) & 0x1u;
rtype = (cmd->cdw10 >> 8) & 0xffu;
memcpy(&crkey, req->data, sizeof(crkey));
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, "
"CRKEY 0x%"PRIx64"\n", rrela, iekey, rtype, crkey);
if (iekey) {
SPDK_ERRLOG("Ignore existing key field set to 1\n");
status = SPDK_NVME_SC_INVALID_FIELD;
goto exit;
}
reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
if (!reg || reg->rkey != crkey) {
SPDK_ERRLOG("No registrant or current key doesn't match "
"with existing registrant key\n");
status = SPDK_NVME_SC_RESERVATION_CONFLICT;
goto exit;
}
switch (rrela) {
case SPDK_NVME_RESERVE_RELEASE:
if (!ns->holder) {
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n");
goto exit;
}
if (ns->rtype != rtype) {
SPDK_ERRLOG("Type doesn't match\n");
status = SPDK_NVME_SC_INVALID_FIELD;
goto exit;
}
if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
/* not the reservation holder, this isn't an error */
goto exit;
}
nvmf_ns_reservation_release_reservation(ns);
break;
case SPDK_NVME_RESERVE_CLEAR:
nvmf_ns_reservation_clear_all_registrants(ns);
break;
default:
status = SPDK_NVME_SC_INVALID_FIELD;
goto exit;
}
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)
{
@ -1638,6 +1721,9 @@ spdk_nvmf_ns_reservation_request(void *ctx)
case SPDK_NVME_OPC_RESERVATION_ACQUIRE:
nvmf_ns_reservation_acquire(ns, ctrlr, req);
break;
case SPDK_NVME_OPC_RESERVATION_RELEASE:
nvmf_ns_reservation_release(ns, ctrlr, req);
break;
default:
break;
}