Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Aug 2019 02:17:39 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r351320 - head/sys/dev/nvme
Message-ID:  <201908210217.x7L2Hdjm090377@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Wed Aug 21 02:17:39 2019
New Revision: 351320
URL: https://svnweb.freebsd.org/changeset/base/351320

Log:
  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

Modified:
  head/sys/dev/nvme/nvme.c

Modified: head/sys/dev/nvme/nvme.c
==============================================================================
--- head/sys/dev/nvme/nvme.c	Wed Aug 21 01:45:29 2019	(r351319)
+++ head/sys/dev/nvme/nvme.c	Wed Aug 21 02:17:39 2019	(r351320)
@@ -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 *ct
 			    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 *ctr
 
 	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);
 	}
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201908210217.x7L2Hdjm090377>