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
This commit is contained in:
Kyle Evans 2019-10-05 21:44:18 +00:00
parent b07934b7c0
commit d42fecb5c1

View File

@ -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;
/* 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);
}