nvmf: update reservation state to subsytem poll group

Each subsystem's poll group will have a copy of namespace's
reservation information, for those NVMe commands which may
change the reservation state, the commnad itself should be
returned after updating each subsystem poll group's
reservation state.  Then it's safe to check the reservation
state in each poll group's thread.

Change-Id: I64a5baedee9024bcac3957b29eb0330a20f21684
Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446213
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Changpeng Liu 2019-03-01 00:48:26 -05:00 committed by Jim Harris
parent c8f7bd031f
commit 1fd5b1da33

View File

@ -1446,7 +1446,7 @@ nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey,
ns->holder = holder; ns->holder = holder;
} }
static void static bool
nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns, nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns,
struct spdk_nvmf_ctrlr *ctrlr, struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvmf_request *req) struct spdk_nvmf_request *req)
@ -1456,6 +1456,7 @@ nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns,
struct spdk_nvme_reservation_register_data key; struct spdk_nvme_reservation_register_data key;
struct spdk_nvmf_registrant *reg; struct spdk_nvmf_registrant *reg;
uint8_t status = SPDK_NVME_SC_SUCCESS; uint8_t status = SPDK_NVME_SC_SUCCESS;
bool update_sgroup = false;
int rc; int rc;
rrega = cmd->cdw10 & 0x7u; rrega = cmd->cdw10 & 0x7u;
@ -1510,6 +1511,7 @@ nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns,
goto exit; goto exit;
} }
nvmf_ns_reservation_remove_registrant(ns, reg); nvmf_ns_reservation_remove_registrant(ns, reg);
update_sgroup = true;
break; break;
case SPDK_NVME_RESERVE_REPLACE_KEY: case SPDK_NVME_RESERVE_REPLACE_KEY:
if (!reg || (!iekey && reg->rkey != key.crkey)) { if (!reg || (!iekey && reg->rkey != key.crkey)) {
@ -1533,10 +1535,10 @@ nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns,
exit: exit:
req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
req->rsp->nvme_cpl.status.sc = status; req->rsp->nvme_cpl.status.sc = status;
return; return update_sgroup;
} }
static void static bool
nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns, nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
struct spdk_nvmf_ctrlr *ctrlr, struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvmf_request *req) struct spdk_nvmf_request *req)
@ -1547,6 +1549,7 @@ nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
struct spdk_nvmf_registrant *reg; struct spdk_nvmf_registrant *reg;
bool all_regs = false; bool all_regs = false;
uint32_t count = 0; uint32_t count = 0;
bool update_sgroup = true;
uint8_t status = SPDK_NVME_SC_SUCCESS; uint8_t status = SPDK_NVME_SC_SUCCESS;
racqa = cmd->cdw10 & 0x7u; racqa = cmd->cdw10 & 0x7u;
@ -1561,6 +1564,7 @@ nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
if (iekey) { if (iekey) {
SPDK_ERRLOG("Ignore existing key field set to 1\n"); SPDK_ERRLOG("Ignore existing key field set to 1\n");
status = SPDK_NVME_SC_INVALID_FIELD; status = SPDK_NVME_SC_INVALID_FIELD;
update_sgroup = false;
goto exit; goto exit;
} }
@ -1570,6 +1574,7 @@ nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
SPDK_ERRLOG("No registrant or current key doesn't match " SPDK_ERRLOG("No registrant or current key doesn't match "
"with existing registrant key\n"); "with existing registrant key\n");
status = SPDK_NVME_SC_RESERVATION_CONFLICT; status = SPDK_NVME_SC_RESERVATION_CONFLICT;
update_sgroup = false;
goto exit; goto exit;
} }
@ -1580,12 +1585,14 @@ nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
/* it's not an error for the holder to acquire same reservation type again */ /* it's not an error for the holder to acquire same reservation type again */
if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) { if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) {
/* do nothing */ /* do nothing */
update_sgroup = false;
} else if (ns->holder == NULL) { } else if (ns->holder == NULL) {
/* fisrt time to acquire the reservation */ /* fisrt time to acquire the reservation */
nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg); nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg);
} else { } else {
SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n"); SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n");
status = SPDK_NVME_SC_RESERVATION_CONFLICT; status = SPDK_NVME_SC_RESERVATION_CONFLICT;
update_sgroup = false;
goto exit; goto exit;
} }
break; break;
@ -1614,6 +1621,7 @@ nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
/* PRKEY is zero */ /* PRKEY is zero */
SPDK_ERRLOG("Current PRKEY is zero\n"); SPDK_ERRLOG("Current PRKEY is zero\n");
status = SPDK_NVME_SC_RESERVATION_CONFLICT; status = SPDK_NVME_SC_RESERVATION_CONFLICT;
update_sgroup = false;
goto exit; goto exit;
} }
} else { } else {
@ -1626,22 +1634,24 @@ nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
if (count == 0) { if (count == 0) {
SPDK_ERRLOG("PRKEY doesn't match any registrant\n"); SPDK_ERRLOG("PRKEY doesn't match any registrant\n");
status = SPDK_NVME_SC_RESERVATION_CONFLICT; status = SPDK_NVME_SC_RESERVATION_CONFLICT;
update_sgroup = false;
goto exit; goto exit;
} }
} }
} }
break; break;
default: default:
update_sgroup = false;
break; break;
} }
exit: exit:
req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
req->rsp->nvme_cpl.status.sc = status; req->rsp->nvme_cpl.status.sc = status;
return; return update_sgroup;
} }
static void static bool
nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns, nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
struct spdk_nvmf_ctrlr *ctrlr, struct spdk_nvmf_ctrlr *ctrlr,
struct spdk_nvmf_request *req) struct spdk_nvmf_request *req)
@ -1651,6 +1661,7 @@ nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
struct spdk_nvmf_registrant *reg; struct spdk_nvmf_registrant *reg;
uint64_t crkey; uint64_t crkey;
uint8_t status = SPDK_NVME_SC_SUCCESS; uint8_t status = SPDK_NVME_SC_SUCCESS;
bool update_sgroup = true;
rrela = cmd->cdw10 & 0x7u; rrela = cmd->cdw10 & 0x7u;
iekey = (cmd->cdw10 >> 3) & 0x1u; iekey = (cmd->cdw10 >> 3) & 0x1u;
@ -1663,6 +1674,7 @@ nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
if (iekey) { if (iekey) {
SPDK_ERRLOG("Ignore existing key field set to 1\n"); SPDK_ERRLOG("Ignore existing key field set to 1\n");
status = SPDK_NVME_SC_INVALID_FIELD; status = SPDK_NVME_SC_INVALID_FIELD;
update_sgroup = false;
goto exit; goto exit;
} }
@ -1671,6 +1683,7 @@ nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
SPDK_ERRLOG("No registrant or current key doesn't match " SPDK_ERRLOG("No registrant or current key doesn't match "
"with existing registrant key\n"); "with existing registrant key\n");
status = SPDK_NVME_SC_RESERVATION_CONFLICT; status = SPDK_NVME_SC_RESERVATION_CONFLICT;
update_sgroup = false;
goto exit; goto exit;
} }
@ -1678,15 +1691,18 @@ nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
case SPDK_NVME_RESERVE_RELEASE: case SPDK_NVME_RESERVE_RELEASE:
if (!ns->holder) { if (!ns->holder) {
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n"); SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n");
update_sgroup = false;
goto exit; goto exit;
} }
if (ns->rtype != rtype) { if (ns->rtype != rtype) {
SPDK_ERRLOG("Type doesn't match\n"); SPDK_ERRLOG("Type doesn't match\n");
status = SPDK_NVME_SC_INVALID_FIELD; status = SPDK_NVME_SC_INVALID_FIELD;
update_sgroup = false;
goto exit; goto exit;
} }
if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) { if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
/* not the reservation holder, this isn't an error */ /* not the reservation holder, this isn't an error */
update_sgroup = false;
goto exit; goto exit;
} }
nvmf_ns_reservation_release_reservation(ns); nvmf_ns_reservation_release_reservation(ns);
@ -1696,13 +1712,14 @@ nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
break; break;
default: default:
status = SPDK_NVME_SC_INVALID_FIELD; status = SPDK_NVME_SC_INVALID_FIELD;
update_sgroup = false;
goto exit; goto exit;
} }
exit: exit:
req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
req->rsp->nvme_cpl.status.sc = status; req->rsp->nvme_cpl.status.sc = status;
return; return update_sgroup;
} }
static void static void
@ -1774,7 +1791,6 @@ exit:
return; return;
} }
static void static void
spdk_nvmf_ns_reservation_complete(void *ctx) spdk_nvmf_ns_reservation_complete(void *ctx)
{ {
@ -1783,15 +1799,26 @@ spdk_nvmf_ns_reservation_complete(void *ctx)
spdk_nvmf_request_complete(req); spdk_nvmf_request_complete(req);
} }
static void
_nvmf_ns_reservation_update_done(struct spdk_nvmf_subsystem *subsystem,
void *cb_arg, int status)
{
struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)cb_arg;
struct spdk_nvmf_poll_group *group = req->qpair->group;
spdk_thread_send_msg(group->thread, spdk_nvmf_ns_reservation_complete, req);
}
void void
spdk_nvmf_ns_reservation_request(void *ctx) spdk_nvmf_ns_reservation_request(void *ctx)
{ {
struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx; struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx;
struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
struct spdk_nvmf_poll_group *group = req->qpair->group;
struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr; struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr;
struct subsystem_update_ns_ctx *update_ctx;
uint32_t nsid; uint32_t nsid;
struct spdk_nvmf_ns *ns; struct spdk_nvmf_ns *ns;
bool update_sgroup = false;
nsid = cmd->nsid; nsid = cmd->nsid;
ns = _spdk_nvmf_subsystem_get_ns(ctrlr->subsys, nsid); ns = _spdk_nvmf_subsystem_get_ns(ctrlr->subsys, nsid);
@ -1799,13 +1826,13 @@ spdk_nvmf_ns_reservation_request(void *ctx)
switch (cmd->opc) { switch (cmd->opc) {
case SPDK_NVME_OPC_RESERVATION_REGISTER: case SPDK_NVME_OPC_RESERVATION_REGISTER:
nvmf_ns_reservation_register(ns, ctrlr, req); update_sgroup = nvmf_ns_reservation_register(ns, ctrlr, req);
break; break;
case SPDK_NVME_OPC_RESERVATION_ACQUIRE: case SPDK_NVME_OPC_RESERVATION_ACQUIRE:
nvmf_ns_reservation_acquire(ns, ctrlr, req); update_sgroup = nvmf_ns_reservation_acquire(ns, ctrlr, req);
break; break;
case SPDK_NVME_OPC_RESERVATION_RELEASE: case SPDK_NVME_OPC_RESERVATION_RELEASE:
nvmf_ns_reservation_release(ns, ctrlr, req); update_sgroup = nvmf_ns_reservation_release(ns, ctrlr, req);
break; break;
case SPDK_NVME_OPC_RESERVATION_REPORT: case SPDK_NVME_OPC_RESERVATION_REPORT:
nvmf_ns_reservation_report(ns, ctrlr, req); nvmf_ns_reservation_report(ns, ctrlr, req);
@ -1813,5 +1840,22 @@ spdk_nvmf_ns_reservation_request(void *ctx)
default: default:
break; break;
} }
spdk_thread_send_msg(group->thread, spdk_nvmf_ns_reservation_complete, req);
/* update reservation information to subsystem's poll group */
if (update_sgroup) {
update_ctx = calloc(1, sizeof(*update_ctx));
if (update_ctx == NULL) {
SPDK_ERRLOG("Can't alloc subsystem poll group update context\n");
goto update_done;
}
update_ctx->subsystem = ctrlr->subsys;
update_ctx->cb_fn = _nvmf_ns_reservation_update_done;
update_ctx->cb_arg = req;
spdk_nvmf_subsystem_update_ns(ctrlr->subsys, subsystem_update_ns_done, update_ctx);
return;
}
update_done:
_nvmf_ns_reservation_update_done(ctrlr->subsys, (void *)req, 0);
} }