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:
parent
ef7827dc06
commit
84ee3a62c7
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user