git: e65ccec8c0e3 - main - nvme: Notify namespaces on reset sometimes

From: Warner Losh <imp_at_FreeBSD.org>
Date: Mon, 19 Oct 2026 06:24:39 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=e65ccec8c0e359f584b2948c100ee3012e43c6e7

commit e65ccec8c0e359f584b2948c100ee3012e43c6e7
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2026-10-19 04:41:00 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-10-19 06:22:51 +0000

    nvme: Notify namespaces on reset sometimes
    
    When we're resetting after a controller failure, and we fix the failure,
    and we've not resetting as part of initialization, notify the all the
    children devices of new namespaces. When we failed the controller
    before, we removed all the namespaces.
    
    Reviewed by:            seuros
    Differential Revision:  https://reviews.freebsd.org/D59832
---
 sys/dev/nvme/nvme_ctrlr.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index f27653536c66..354ca7a78e51 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -673,6 +673,24 @@ nvme_ctrlr_notify_ns_added(struct nvme_controller *ctrlr, device_t child)
 	}
 }
 
+static void
+nvme_ctrlr_notify_ns_recovered(struct nvme_controller *ctrlr)
+{
+	device_t *children;
+	int n_children;
+
+	if (device_get_children(ctrlr->dev, &children, &n_children) != 0)
+		return;
+
+	/*
+	 * A controller failure was reported to every child, so notify every
+	 * child when its namespaces become available again.
+	 */
+	for (int i = 0; i < n_children; i++)
+		nvme_ctrlr_notify_ns_added(ctrlr, children[i]);
+	free(children, M_TEMP);
+}
+
 static bool
 is_log_page_id_valid(uint8_t page_id)
 {
@@ -1278,13 +1296,19 @@ static void
 nvme_ctrlr_reset_task(void *arg, int pending)
 {
 	struct nvme_controller	*ctrlr = arg;
+	bool			recovering;
 	int			status;
 
+	recovering = ctrlr->is_initialized && ctrlr->is_failed;
 	nvme_ctrlr_devctl_log(ctrlr, "RESET", "event=\"start\"");
 	status = nvme_ctrlr_hw_reset(ctrlr);
 	if (status == 0) {
 		nvme_ctrlr_devctl_log(ctrlr, "RESET", "event=\"success\"");
+		if (recovering)
+			ctrlr->is_failed = false;
 		nvme_ctrlr_start(ctrlr, true);
+		if (recovering && !ctrlr->is_failed)
+			nvme_ctrlr_notify_ns_recovered(ctrlr);
 	} else {
 		nvme_ctrlr_devctl_log(ctrlr, "RESET", "event=\"timed_out\"");
 		nvme_ctrlr_fail(ctrlr, true);