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);
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to