diff options
author | Jim Harris <jimharris@FreeBSD.org> | 2013-03-26 21:58:38 +0000 |
---|---|---|
committer | Jim Harris <jimharris@FreeBSD.org> | 2013-03-26 21:58:38 +0000 |
commit | 232e2edb6cd50465bd62b9f7cbc9fd83531c02ca (patch) | |
tree | db8e7e98a528b185943c39f106d44bc2c0f09197 /sys/dev/nvme/nvme.c | |
parent | 3d7eb41c1b3c48bf2ac69cddd378f4e266ed6bb6 (diff) | |
download | src-232e2edb6cd50465bd62b9f7cbc9fd83531c02ca.tar.gz src-232e2edb6cd50465bd62b9f7cbc9fd83531c02ca.zip |
Add the ability to internally mark a controller as failed, if it is unable to
start or reset. Also add a notifier for NVMe consumers for controller fail
conditions and plumb this notifier for nvd(4) to destroy the associated
GEOM disks when a failure occurs.
This requires a bit of work to cover the races when a consumer is sending
I/O requests to a controller that is transitioning to the failed state. To
help cover this condition, add a task to defer completion of I/Os submitted
to a failed controller, so that the consumer will still always receive its
completions in a different context than the submission.
Sponsored by: Intel
Reviewed by: carl
Notes
Notes:
svn path=/head/; revision=248767
Diffstat (limited to 'sys/dev/nvme/nvme.c')
-rw-r--r-- | sys/dev/nvme/nvme.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/sys/dev/nvme/nvme.c b/sys/dev/nvme/nvme.c index 27870106bf48..afebae735ef2 100644 --- a/sys/dev/nvme/nvme.c +++ b/sys/dev/nvme/nvme.c @@ -44,6 +44,7 @@ struct nvme_consumer { nvme_cons_ns_fn_t ns_fn; nvme_cons_ctrlr_fn_t ctrlr_fn; nvme_cons_async_fn_t async_fn; + nvme_cons_fail_fn_t fail_fn; }; struct nvme_consumer nvme_consumer[NVME_MAX_CONSUMERS]; @@ -349,9 +350,23 @@ nvme_notify_async_consumers(struct nvme_controller *ctrlr, } } +void +nvme_notify_fail_consumers(struct nvme_controller *ctrlr) +{ + struct nvme_consumer *cons; + uint32_t i; + + 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]); + } +} + struct nvme_consumer * nvme_register_consumer(nvme_cons_ns_fn_t ns_fn, nvme_cons_ctrlr_fn_t ctrlr_fn, - nvme_cons_async_fn_t async_fn) + nvme_cons_async_fn_t async_fn, + nvme_cons_fail_fn_t fail_fn) { int i; @@ -365,6 +380,7 @@ nvme_register_consumer(nvme_cons_ns_fn_t ns_fn, nvme_cons_ctrlr_fn_t ctrlr_fn, nvme_consumer[i].ns_fn = ns_fn; nvme_consumer[i].ctrlr_fn = ctrlr_fn; nvme_consumer[i].async_fn = async_fn; + nvme_consumer[i].fail_fn = fail_fn; nvme_notify_consumer(&nvme_consumer[i]); return (&nvme_consumer[i]); |