diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h --- a/sys/dev/nvme/nvme.h +++ b/sys/dev/nvme/nvme.h @@ -1929,8 +1929,11 @@ typedef void (*nvme_cons_fail_fn_t)(void *); enum nvme_namespace_flags { - NVME_NS_DEALLOCATE_SUPPORTED = 0x1, - NVME_NS_FLUSH_SUPPORTED = 0x2, + NVME_NS_DEALLOCATE_SUPPORTED = 0x01, + NVME_NS_FLUSH_SUPPORTED = 0x02, + NVME_NS_ADDED = 0x04, + NVME_NS_CHANGED = 0x08, + NVME_NS_GONE = 0x10, }; int nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -1216,10 +1216,20 @@ } else if (aer->log_page_id == NVME_LOG_CHANGED_NAMESPACE) { struct nvme_ns_list *nsl = (struct nvme_ns_list *)aer->log_page_buffer; + struct nvme_controller *ctrlr = aer->ctrlr; + for (int i = 0; i < nitems(nsl->ns) && nsl->ns[i] != 0; i++) { + struct nvme_namespace *ns; + uint32_t id = nsl->ns[i]; + if (nsl->ns[i] > NVME_MAX_NAMESPACES) break; - nvme_notify_ns(aer->ctrlr, nsl->ns[i]); + + ns = &ctrlr->ns[id - 1]; + ns->flags |= NVME_NS_CHANGED; + nvme_ns_construct(ns, id, ctrlr); + nvme_notify_ns(ctrlr, id); + ns->flags &= ~NVME_NS_CHANGED; } } diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c --- a/sys/dev/nvme/nvme_ns.c +++ b/sys/dev/nvme/nvme_ns.c @@ -78,7 +78,7 @@ break; case NVME_PASSTHROUGH_CMD: pt = (struct nvme_pt_command *)arg; - return (nvme_ctrlr_passthrough_cmd(ctrlr, pt, ns->id, + return (nvme_ctrlr_passthrough_cmd(ctrlr, pt, ns->id, 1 /* is_user_buffer */, 0 /* is_admin_cmd */)); case NVME_GET_NSID: { @@ -558,8 +558,10 @@ * standard says the entire id will be zeros, so this is a * cheap way to test for that. */ - if (ns->data.nsze == 0) - return (ENXIO); + if (ns->data.nsze == 0) { + ns->flags |= NVME_NS_GONE; + return ((ns->flags & NVME_NS_ADDED) ? 0 : ENXIO); + } flbas_fmt = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, ns->data.flbas); @@ -623,6 +625,7 @@ ns->cdev->si_drv2 = make_dev_alias(ns->cdev, "%sns%d", device_get_nameunit(ctrlr->dev), ns->id); ns->cdev->si_flags |= SI_UNMAPPED; + ns->flags |= NVME_NS_ADDED; return (0); }