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:
parent
29a745bf9b
commit
56ca87e15a
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user