Formalize NVMe controller consumer life cycle.

This fixes possible double call of fail_fn, for example on hot removal.
It also allows ctrlr_fn to safely return NULL cookie in case of failure
and not get useless ns_fn or fail_fn call with NULL cookie later.

MFC after:	2 weeks
This commit is contained in:
mav 2019-08-21 02:17:39 +00:00
parent 29a745bf9b
commit 56ca87e15a

View File

@ -330,16 +330,21 @@ nvme_notify(struct nvme_consumer *cons,
return;
cmpset = atomic_cmpset_32(&ctrlr->notification_sent, 0, 1);
if (cmpset == 0)
return;
if (cons->ctrlr_fn != NULL)
ctrlr_cookie = (*cons->ctrlr_fn)(ctrlr);
else
ctrlr_cookie = NULL;
ctrlr_cookie = (void *)(uintptr_t)0xdeadc0dedeadc0de;
ctrlr->cons_cookie[cons->id] = ctrlr_cookie;
/* ctrlr_fn has failed. Nothing to notify here any more. */
if (ctrlr_cookie == NULL)
return;
if (ctrlr->is_failed) {
ctrlr->cons_cookie[cons->id] = NULL;
if (cons->fail_fn != NULL)
(*cons->fail_fn)(ctrlr_cookie);
/*
@ -395,13 +400,16 @@ nvme_notify_async_consumers(struct nvme_controller *ctrlr,
uint32_t log_page_size)
{
struct nvme_consumer *cons;
void *ctrlr_cookie;
uint32_t i;
for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
cons = &nvme_consumer[i];
if (cons->id != INVALID_CONSUMER_ID && cons->async_fn != NULL)
(*cons->async_fn)(ctrlr->cons_cookie[i], async_cpl,
if (cons->id != INVALID_CONSUMER_ID && cons->async_fn != NULL &&
(ctrlr_cookie = ctrlr->cons_cookie[i]) != NULL) {
(*cons->async_fn)(ctrlr_cookie, async_cpl,
log_page_id, log_page_buffer, log_page_size);
}
}
}
@ -409,6 +417,7 @@ void
nvme_notify_fail_consumers(struct nvme_controller *ctrlr)
{
struct nvme_consumer *cons;
void *ctrlr_cookie;
uint32_t i;
/*
@ -422,8 +431,12 @@ nvme_notify_fail_consumers(struct nvme_controller *ctrlr)
for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
cons = &nvme_consumer[i];
if (cons->id != INVALID_CONSUMER_ID && cons->fail_fn != NULL)
cons->fail_fn(ctrlr->cons_cookie[i]);
if (cons->id != INVALID_CONSUMER_ID &&
(ctrlr_cookie = ctrlr->cons_cookie[i]) != NULL) {
ctrlr->cons_cookie[i] = NULL;
if (cons->fail_fn != NULL)
cons->fail_fn(ctrlr_cookie);
}
}
}
@ -432,6 +445,7 @@ nvme_notify_ns(struct nvme_controller *ctrlr, int nsid)
{
struct nvme_consumer *cons;
struct nvme_namespace *ns = &ctrlr->ns[nsid - 1];
void *ctrlr_cookie;
uint32_t i;
if (!ctrlr->is_initialized)
@ -439,9 +453,9 @@ nvme_notify_ns(struct nvme_controller *ctrlr, int nsid)
for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
cons = &nvme_consumer[i];
if (cons->id != INVALID_CONSUMER_ID && cons->ns_fn != NULL)
ns->cons_cookie[cons->id] =
(*cons->ns_fn)(ns, ctrlr->cons_cookie[cons->id]);
if (cons->id != INVALID_CONSUMER_ID && cons->ns_fn != NULL &&
(ctrlr_cookie = ctrlr->cons_cookie[i]) != NULL)
ns->cons_cookie[i] = (*cons->ns_fn)(ns, ctrlr_cookie);
}
}