Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Oct 2019 21:44:19 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r353128 - head/sys/kern
Message-ID:  <201910052144.x95LiJLC015972@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Sat Oct  5 21:44:18 2019
New Revision: 353128
URL: https://svnweb.freebsd.org/changeset/base/353128

Log:
  kern_conf: fully initialize cloned devices with make_dev_args, too
  
  Attempting to initialize si_drv{1,2} with mda_si_drv{1,2} does not work if
  you are operating on cloned devices.
  
  clone_create must be called prior to the make_dev* family to create/return
  the device on the clonelist as needed. This device is later returned early
  in newdev(), prior to si_drv{0,1,2} initialization.
  
  This patch simply breaks out of the loop if we've found a device and
  finishes init.
  
  Reviewed by:	kib
  MFC after:	1 week
  Differential Revision:	https://reviews.freebsd.org/D21904

Modified:
  head/sys/kern/kern_conf.c

Modified: head/sys/kern/kern_conf.c
==============================================================================
--- head/sys/kern/kern_conf.c	Sat Oct  5 21:28:46 2019	(r353127)
+++ head/sys/kern/kern_conf.c	Sat Oct  5 21:44:18 2019	(r353128)
@@ -576,20 +576,41 @@ newdev(struct make_dev_args *args, struct cdev *si)
 
 	mtx_assert(&devmtx, MA_OWNED);
 	csw = args->mda_devsw;
+	si2 = NULL;
 	if (csw->d_flags & D_NEEDMINOR) {
 		/* We may want to return an existing device */
 		LIST_FOREACH(si2, &csw->d_devs, si_list) {
 			if (dev2unit(si2) == args->mda_unit) {
 				dev_free_devlocked(si);
-				return (si2);
+				si = si2;
+				break;
 			}
 		}
+
+		/*
+		 * If we're returning an existing device, we should make sure
+		 * it isn't already initialized.  This would have been caught
+		 * in consumers anyways, but it's good to catch such a case
+		 * early.  We still need to complete initialization of the
+		 * device, and we'll use whatever make_dev_args were passed in
+		 * to do so.
+		 */
+		KASSERT(si2 == NULL || (si2->si_flags & SI_NAMED) == 0,
+		    ("make_dev() by driver %s on pre-existing device (min=%x, name=%s)",
+		    args->mda_devsw->d_name, dev2unit(si2), devtoname(si2)));
 	}
 	si->si_drv0 = args->mda_unit;
-	si->si_devsw = csw;
 	si->si_drv1 = args->mda_si_drv1;
 	si->si_drv2 = args->mda_si_drv2;
-	LIST_INSERT_HEAD(&csw->d_devs, si, si_list);
+	/* Only push to csw->d_devs if it's not a cloned device. */
+	if (si2 == NULL) {
+		si->si_devsw = csw;
+		LIST_INSERT_HEAD(&csw->d_devs, si, si_list);
+	} else {
+		KASSERT(si->si_devsw == csw,
+		    ("%s: inconsistent devsw between clone_create() and make_dev()",
+		    __func__));
+	}
 	return (si);
 }
 



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