Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Aug 2019 20:58:25 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r351586 - stable/11/sys/dev/nvme
Message-ID:  <201908282058.x7SKwPuG088800@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Wed Aug 28 20:58:24 2019
New Revision: 351586
URL: https://svnweb.freebsd.org/changeset/base/351586

Log:
  MFC r351320: 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.

Modified:
  stable/11/sys/dev/nvme/nvme.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/nvme/nvme.c
==============================================================================
--- stable/11/sys/dev/nvme/nvme.c	Wed Aug 28 20:35:23 2019	(r351585)
+++ stable/11/sys/dev/nvme/nvme.c	Wed Aug 28 20:58:24 2019	(r351586)
@@ -316,16 +316,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);
 		/*
@@ -381,13 +386,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);
+		}
 	}
 }
 
@@ -395,6 +403,7 @@ void
 nvme_notify_fail_consumers(struct nvme_controller *ctrlr)
 {
 	struct nvme_consumer	*cons;
+	void			*ctrlr_cookie;
 	uint32_t		i;
 
 	/*
@@ -408,8 +417,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);
+		}
 	}
 }
 



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