Index: sys/dev/nvme/nvme.c
===================================================================
--- sys/dev/nvme/nvme.c
+++ sys/dev/nvme/nvme.c
@@ -294,12 +294,14 @@
 		return;
 
 	ns = &ctrlr->ns[nsid - 1];
+	nvme_ns_construct(ns, nsid, ctrlr, NVME_REASON_FLAGGED);
 	for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
 		cons = &nvme_consumer[i];
 		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);
 	}
+	ns->flags &= ~NVME_NS_FLAG_CHANGED;
 }
 
 struct nvme_consumer *
Index: sys/dev/nvme/nvme_ctrlr.c
===================================================================
--- sys/dev/nvme/nvme_ctrlr.c
+++ sys/dev/nvme/nvme_ctrlr.c
@@ -586,7 +586,7 @@
 
 	for (i = 0; i < min(ctrlr->cdata.nn, NVME_MAX_NAMESPACES); i++) {
 		ns = &ctrlr->ns[i];
-		nvme_ns_construct(ns, i+1, ctrlr);
+		nvme_ns_construct(ns, i+1, ctrlr, NVME_REASON_RESET);
 	}
 
 	return (0);
Index: sys/dev/nvme/nvme_ns.c
===================================================================
--- sys/dev/nvme/nvme_ns.c
+++ sys/dev/nvme/nvme_ns.c
@@ -510,7 +510,7 @@
 
 int
 nvme_ns_construct(struct nvme_namespace *ns, uint32_t id,
-    struct nvme_controller *ctrlr)
+    struct nvme_controller *ctrlr, enum nvme_ctor_reason why)
 {
 	struct make_dev_args                    md_args;
 	struct nvme_completion_poll_status	status;
@@ -549,10 +549,13 @@
 	 * If the size of is zero, chances are this isn't a valid
 	 * namespace (eg one that's not been configured yet). The
 	 * standard says the entire id will be zeros, so this is a
-	 * cheap way to test for that.
+	 * cheap way to test for that. If we previously added this
+	 * device, then it's now gone.
 	 */
-	if (ns->data.nsze == 0)
-		return (ENXIO);
+	if (ns->data.nsze == 0) {
+		ns->flags |= NVME_NS_FLAG_GONE;
+		return ((ns->flags & NVME_NS_FLAG_ADDED) ? 0 : ENXIO);
+	}
 
 	flbas_fmt = (ns->data.flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
 		NVME_NS_DATA_FLBAS_FORMAT_MASK;
@@ -597,10 +600,14 @@
 
 	/*
 	 * cdev may have already been created, if we are reconstructing the
-	 *  namespace after a controller-level reset.
+	 * namespace after a controller-level reset. If not, then flag this
+	 * ns as changed for notification.
 	 */
-	if (ns->cdev != NULL)
+	if (ns->cdev != NULL) {
+		if (why != NVME_REASON_RESET)
+			ns->flags |= NVME_NS_FLAG_CHANGED;
 		return (0);
+	}
 
 	/*
 	 * Namespace IDs start at 1, so we need to subtract 1 to create a
@@ -619,6 +626,7 @@
 		return (ENXIO);
 
 	ns->cdev->si_flags |= SI_UNMAPPED;
+	ns->flags |= NVME_NS_FLAG_ADDED;
 
 	return (0);
 }
Index: sys/dev/nvme/nvme_private.h
===================================================================
--- sys/dev/nvme/nvme_private.h
+++ sys/dev/nvme/nvme_private.h
@@ -222,6 +222,9 @@
 	struct nvme_namespace_data	data;
 	uint32_t			id;
 	uint32_t			flags;
+#define NVME_NS_FLAG_ADDED			0x1
+#define NVME_NS_FLAG_CHANGED			0x2
+#define NVME_NS_FLAG_GONE			0x4
 	struct cdev			*cdev;
 	void				*cons_cookie[NVME_MAX_CONSUMERS];
 	uint32_t			boundary;
@@ -333,6 +336,11 @@
 	uint64_t			hmb_desc_paddr;
 };
 
+enum nvme_ctor_reason {
+	NVME_REASON_RESET,		/* Controller was reset, rebuilding */
+	NVME_REASON_FLAGGED,		/* NS was flagged as changed somehow */
+};
+
 #define nvme_mmio_offsetof(reg)						       \
 	offsetof(struct nvme_registers, reg)
 
@@ -442,7 +450,7 @@
 void	nvme_io_qpair_destroy(struct nvme_qpair *qpair);
 
 int	nvme_ns_construct(struct nvme_namespace *ns, uint32_t id,
-			  struct nvme_controller *ctrlr);
+	    struct nvme_controller *ctrlr, enum nvme_ctor_reason why);
 void	nvme_ns_destruct(struct nvme_namespace *ns);
 
 void	nvme_sysctl_initialize_ctrlr(struct nvme_controller *ctrlr);
Index: sys/dev/nvme/nvme_sim.c
===================================================================
--- sys/dev/nvme/nvme_sim.c
+++ sys/dev/nvme/nvme_sim.c
@@ -326,25 +326,37 @@
 nvme_sim_ns_change(struct nvme_namespace *ns, void *sc_arg)
 {
 	struct nvme_sim_softc *sc = sc_arg;
+	struct cam_path *tmppath;
 	union ccb *ccb;
 
+	if (xpt_create_path(&tmppath, /*periph*/NULL,
+	    cam_sim_path(sc->s_sim), 0, ns->id) != CAM_REQ_CMP) {
+		printf("unable to create path for rescan\n");
+		return (NULL);
+	}
+	/*
+	 * If it's gone, then signal that and leave.
+	 */
+	if (ns->flags & NVME_NS_FLAG_GONE) {
+		xpt_async(AC_LOST_DEVICE, tmppath, NULL);
+		xpt_free_path(tmppath);
+		return (sc_arg);
+	}
+
 	ccb = xpt_alloc_ccb_nowait();
 	if (ccb == NULL) {
 		printf("unable to alloc CCB for rescan\n");
 		return (NULL);
 	}
+	ccb->ccb_h.path = tmppath;
 
 	/*
 	 * We map the NVMe namespace idea onto the CAM unit LUN. For
 	 * each new namespace, we create a new CAM path for it. We then
 	 * rescan the path to get it to enumerate.
+	 *
+	 * At the end of the scan, the path is freed, I think...
 	 */
-	if (xpt_create_path(&ccb->ccb_h.path, /*periph*/NULL,
-	    cam_sim_path(sc->s_sim), 0, ns->id) != CAM_REQ_CMP) {
-		printf("unable to create path for rescan\n");
-		xpt_free_ccb(ccb);
-		return (NULL);
-	}
 	xpt_rescan(ccb);
 
 	return (sc_arg);