xref: /freebsd/sys/kern/kern_conf.c (revision 7afc53b8dfcc7d5897920ce6cc7e842fbb4ab813)
1 /*-
2  * Copyright (c) 1999-2002 Poul-Henning Kamp
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 #include <sys/kernel.h>
32 #include <sys/systm.h>
33 #include <sys/bio.h>
34 #include <sys/lock.h>
35 #include <sys/mutex.h>
36 #include <sys/sysctl.h>
37 #include <sys/module.h>
38 #include <sys/malloc.h>
39 #include <sys/conf.h>
40 #include <sys/vnode.h>
41 #include <sys/queue.h>
42 #include <sys/poll.h>
43 #include <sys/ctype.h>
44 #include <sys/tty.h>
45 #include <machine/stdarg.h>
46 
47 static MALLOC_DEFINE(M_DEVT, "cdev", "cdev storage");
48 
49 /* Built at compile time from sys/conf/majors */
50 
51 static struct mtx devmtx;
52 static void freedev(struct cdev *dev);
53 static void destroy_devl(struct cdev *dev);
54 
55 void
56 dev_lock(void)
57 {
58 	if (!mtx_initialized(&devmtx))
59 		mtx_init(&devmtx, "cdev", NULL, MTX_DEF);
60 	mtx_lock(&devmtx);
61 }
62 
63 void
64 dev_unlock(void)
65 {
66 
67 	mtx_unlock(&devmtx);
68 }
69 
70 void
71 dev_ref(struct cdev *dev)
72 {
73 
74 	mtx_assert(&devmtx, MA_NOTOWNED);
75 	mtx_lock(&devmtx);
76 	dev->si_refcount++;
77 	mtx_unlock(&devmtx);
78 }
79 
80 void
81 dev_refl(struct cdev *dev)
82 {
83 
84 	mtx_assert(&devmtx, MA_OWNED);
85 	dev->si_refcount++;
86 }
87 
88 void
89 dev_rel(struct cdev *dev)
90 {
91 	int flag = 0;
92 
93 	mtx_assert(&devmtx, MA_NOTOWNED);
94 	dev_lock();
95 	dev->si_refcount--;
96 	KASSERT(dev->si_refcount >= 0,
97 	    ("dev_rel(%s) gave negative count", devtoname(dev)));
98 	if (dev->si_usecount == 0 &&
99 	    (dev->si_flags & SI_CHEAPCLONE) && (dev->si_flags & SI_NAMED))
100 	if (dev->si_devsw == NULL && dev->si_refcount == 0) {
101 		LIST_REMOVE(dev, si_list);
102 		flag = 1;
103 	}
104 	dev_unlock();
105 	if (flag)
106 		freedev(dev);
107 }
108 
109 struct cdevsw *
110 dev_refthread(struct cdev *dev)
111 {
112 	struct cdevsw *csw;
113 
114 	mtx_assert(&devmtx, MA_NOTOWNED);
115 	dev_lock();
116 	csw = dev->si_devsw;
117 	if (csw != NULL)
118 		dev->si_threadcount++;
119 	dev_unlock();
120 	return (csw);
121 }
122 
123 void
124 dev_relthread(struct cdev *dev)
125 {
126 
127 	mtx_assert(&devmtx, MA_NOTOWNED);
128 	dev_lock();
129 	dev->si_threadcount--;
130 	dev_unlock();
131 }
132 
133 int
134 nullop(void)
135 {
136 
137 	return (0);
138 }
139 
140 int
141 eopnotsupp(void)
142 {
143 
144 	return (EOPNOTSUPP);
145 }
146 
147 static int
148 enxio(void)
149 {
150 	return (ENXIO);
151 }
152 
153 static int
154 enodev(void)
155 {
156 	return (ENODEV);
157 }
158 
159 /* Define a dead_cdevsw for use when devices leave unexpectedly. */
160 
161 #define dead_open	(d_open_t *)enxio
162 #define dead_close	(d_close_t *)enxio
163 #define dead_read	(d_read_t *)enxio
164 #define dead_write	(d_write_t *)enxio
165 #define dead_ioctl	(d_ioctl_t *)enxio
166 #define dead_poll	(d_poll_t *)enodev
167 #define dead_mmap	(d_mmap_t *)enodev
168 
169 static void
170 dead_strategy(struct bio *bp)
171 {
172 
173 	biofinish(bp, NULL, ENXIO);
174 }
175 
176 #define dead_dump	(dumper_t *)enxio
177 #define dead_kqfilter	(d_kqfilter_t *)enxio
178 
179 static struct cdevsw dead_cdevsw = {
180 	.d_version =	D_VERSION,
181 	.d_flags =	D_NEEDGIANT, /* XXX: does dead_strategy need this ? */
182 	.d_open =	dead_open,
183 	.d_close =	dead_close,
184 	.d_read =	dead_read,
185 	.d_write =	dead_write,
186 	.d_ioctl =	dead_ioctl,
187 	.d_poll =	dead_poll,
188 	.d_mmap =	dead_mmap,
189 	.d_strategy =	dead_strategy,
190 	.d_name =	"dead",
191 	.d_dump =	dead_dump,
192 	.d_kqfilter =	dead_kqfilter
193 };
194 
195 /* Default methods if driver does not specify method */
196 
197 #define null_open	(d_open_t *)nullop
198 #define null_close	(d_close_t *)nullop
199 #define no_read		(d_read_t *)enodev
200 #define no_write	(d_write_t *)enodev
201 #define no_ioctl	(d_ioctl_t *)enodev
202 #define no_mmap		(d_mmap_t *)enodev
203 #define no_kqfilter	(d_kqfilter_t *)enodev
204 
205 static void
206 no_strategy(struct bio *bp)
207 {
208 
209 	biofinish(bp, NULL, ENODEV);
210 }
211 
212 static int
213 no_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
214 {
215 	/*
216 	 * Return true for read/write.  If the user asked for something
217 	 * special, return POLLNVAL, so that clients have a way of
218 	 * determining reliably whether or not the extended
219 	 * functionality is present without hard-coding knowledge
220 	 * of specific filesystem implementations.
221 	 * Stay in sync with vop_nopoll().
222 	 */
223 	if (events & ~POLLSTANDARD)
224 		return (POLLNVAL);
225 
226 	return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
227 }
228 
229 #define no_dump		(dumper_t *)enodev
230 
231 /*
232  * struct cdev * and u_dev_t primitives
233  */
234 
235 int
236 minor(struct cdev *x)
237 {
238 	if (x == NULL)
239 		return NODEV;
240 	return(x->si_drv0 & MAXMINOR);
241 }
242 
243 int
244 dev2unit(struct cdev *x)
245 {
246 
247 	if (x == NULL)
248 		return NODEV;
249 	return (minor2unit(minor(x)));
250 }
251 
252 u_int
253 minor2unit(u_int _minor)
254 {
255 
256 	KASSERT((_minor & ~MAXMINOR) == 0, ("Illegal minor %x", _minor));
257 	return ((_minor & 0xff) | ((_minor >> 8) & 0xffff00));
258 }
259 
260 int
261 unit2minor(int unit)
262 {
263 
264 	KASSERT(unit <= 0xffffff, ("Invalid unit (%d) in unit2minor", unit));
265 	return ((unit & 0xff) | ((unit << 8) & ~0xffff));
266 }
267 
268 static struct cdev *
269 allocdev(void)
270 {
271 	struct cdev *si;
272 
273 	si = malloc(sizeof *si, M_DEVT, M_USE_RESERVE | M_ZERO | M_WAITOK);
274 	si->si_name = si->__si_namebuf;
275 	LIST_INIT(&si->si_children);
276 	LIST_INIT(&si->si_alist);
277 	return (si);
278 }
279 
280 static struct cdev *
281 newdev(struct cdevsw *csw, int y, struct cdev *si)
282 {
283 	struct cdev *si2;
284 	dev_t	udev;
285 
286 	mtx_assert(&devmtx, MA_OWNED);
287 	udev = y;
288 	LIST_FOREACH(si2, &csw->d_devs, si_list) {
289 		if (si2->si_drv0 == udev) {
290 			freedev(si);
291 			return (si2);
292 		}
293 	}
294 	si->si_drv0 = udev;
295 	LIST_INSERT_HEAD(&csw->d_devs, si, si_list);
296 	return (si);
297 }
298 
299 static void
300 freedev(struct cdev *dev)
301 {
302 
303 	free(dev, M_DEVT);
304 }
305 
306 int
307 uminor(dev_t dev)
308 {
309 	return (dev & MAXMINOR);
310 }
311 
312 int
313 umajor(dev_t dev)
314 {
315 	return ((dev & ~MAXMINOR) >> 8);
316 }
317 
318 static void
319 fini_cdevsw(struct cdevsw *devsw)
320 {
321 
322 	devsw->d_flags &= ~D_INIT;
323 }
324 
325 static void
326 prep_cdevsw(struct cdevsw *devsw)
327 {
328 
329 	dev_lock();
330 
331 	if (devsw->d_version != D_VERSION_01) {
332 		printf(
333 		    "WARNING: Device driver \"%s\" has wrong version %s\n",
334 		    devsw->d_name, "and is disabled.  Recompile KLD module.");
335 		devsw->d_open = dead_open;
336 		devsw->d_close = dead_close;
337 		devsw->d_read = dead_read;
338 		devsw->d_write = dead_write;
339 		devsw->d_ioctl = dead_ioctl;
340 		devsw->d_poll = dead_poll;
341 		devsw->d_mmap = dead_mmap;
342 		devsw->d_strategy = dead_strategy;
343 		devsw->d_dump = dead_dump;
344 		devsw->d_kqfilter = dead_kqfilter;
345 	}
346 
347 	if (devsw->d_flags & D_TTY) {
348 		if (devsw->d_ioctl == NULL)	devsw->d_ioctl = ttyioctl;
349 		if (devsw->d_read == NULL)	devsw->d_read = ttyread;
350 		if (devsw->d_write == NULL)	devsw->d_write = ttywrite;
351 		if (devsw->d_kqfilter == NULL)	devsw->d_kqfilter = ttykqfilter;
352 		if (devsw->d_poll == NULL)	devsw->d_poll = ttypoll;
353 	}
354 
355 	if (devsw->d_open == NULL)	devsw->d_open = null_open;
356 	if (devsw->d_close == NULL)	devsw->d_close = null_close;
357 	if (devsw->d_read == NULL)	devsw->d_read = no_read;
358 	if (devsw->d_write == NULL)	devsw->d_write = no_write;
359 	if (devsw->d_ioctl == NULL)	devsw->d_ioctl = no_ioctl;
360 	if (devsw->d_poll == NULL)	devsw->d_poll = no_poll;
361 	if (devsw->d_mmap == NULL)	devsw->d_mmap = no_mmap;
362 	if (devsw->d_strategy == NULL)	devsw->d_strategy = no_strategy;
363 	if (devsw->d_dump == NULL)	devsw->d_dump = no_dump;
364 	if (devsw->d_kqfilter == NULL)	devsw->d_kqfilter = no_kqfilter;
365 
366 	LIST_INIT(&devsw->d_devs);
367 
368 	devsw->d_flags |= D_INIT;
369 
370 	dev_unlock();
371 }
372 
373 struct cdev *
374 make_dev(struct cdevsw *devsw, int minornr, uid_t uid, gid_t gid, int mode, const char *fmt, ...)
375 {
376 	struct cdev *dev;
377 	va_list ap;
378 	int i;
379 
380 	KASSERT((minornr & ~MAXMINOR) == 0,
381 	    ("Invalid minor (0x%x) in make_dev", minornr));
382 
383 	if (!(devsw->d_flags & D_INIT))
384 		prep_cdevsw(devsw);
385 	dev = allocdev();
386 	dev_lock();
387 	dev = newdev(devsw, minornr, dev);
388 	if (dev->si_flags & SI_CHEAPCLONE &&
389 	    dev->si_flags & SI_NAMED &&
390 	    dev->si_devsw == devsw) {
391 		/*
392 		 * This is allowed as it removes races and generally
393 		 * simplifies cloning devices.
394 		 * XXX: still ??
395 		 */
396 		dev_unlock();
397 		return (dev);
398 	}
399 	KASSERT(!(dev->si_flags & SI_NAMED),
400 	    ("make_dev() by driver %s on pre-existing device (min=%x, name=%s)",
401 	    devsw->d_name, minor(dev), devtoname(dev)));
402 
403 	va_start(ap, fmt);
404 	i = vsnrprintf(dev->__si_namebuf, sizeof dev->__si_namebuf, 32, fmt, ap);
405 	if (i > (sizeof dev->__si_namebuf - 1)) {
406 		printf("WARNING: Device name truncated! (%s)\n",
407 		    dev->__si_namebuf);
408 	}
409 	va_end(ap);
410 
411 	dev->si_devsw = devsw;
412 	dev->si_flags |= SI_NAMED;
413 	dev->si_uid = uid;
414 	dev->si_gid = gid;
415 	dev->si_mode = mode;
416 
417 	devfs_create(dev);
418 	dev_unlock();
419 	return (dev);
420 }
421 
422 int
423 dev_named(struct cdev *pdev, const char *name)
424 {
425 	struct cdev *cdev;
426 
427 	if (strcmp(devtoname(pdev), name) == 0)
428 		return (1);
429 	LIST_FOREACH(cdev, &pdev->si_children, si_siblings)
430 		if (strcmp(devtoname(cdev), name) == 0)
431 			return (1);
432 	return (0);
433 }
434 
435 void
436 dev_depends(struct cdev *pdev, struct cdev *cdev)
437 {
438 
439 	dev_lock();
440 	cdev->si_parent = pdev;
441 	cdev->si_flags |= SI_CHILD;
442 	LIST_INSERT_HEAD(&pdev->si_children, cdev, si_siblings);
443 	dev_unlock();
444 }
445 
446 struct cdev *
447 make_dev_alias(struct cdev *pdev, const char *fmt, ...)
448 {
449 	struct cdev *dev;
450 	va_list ap;
451 	int i;
452 
453 	dev = allocdev();
454 	dev_lock();
455 	dev->si_flags |= SI_ALIAS;
456 	dev->si_flags |= SI_NAMED;
457 	va_start(ap, fmt);
458 	i = vsnrprintf(dev->__si_namebuf, sizeof dev->__si_namebuf, 32, fmt, ap);
459 	if (i > (sizeof dev->__si_namebuf - 1)) {
460 		printf("WARNING: Device name truncated! (%s)\n",
461 		    dev->__si_namebuf);
462 	}
463 	va_end(ap);
464 
465 	devfs_create(dev);
466 	dev_unlock();
467 	dev_depends(pdev, dev);
468 	return (dev);
469 }
470 
471 static void
472 destroy_devl(struct cdev *dev)
473 {
474 	struct cdevsw *csw;
475 
476 	mtx_assert(&devmtx, MA_OWNED);
477 	KASSERT(dev->si_flags & SI_NAMED,
478 	    ("WARNING: Driver mistake: destroy_dev on %d\n", minor(dev)));
479 
480 	devfs_destroy(dev);
481 
482 	/* Remove name marking */
483 	dev->si_flags &= ~SI_NAMED;
484 
485 	/* If we are a child, remove us from the parents list */
486 	if (dev->si_flags & SI_CHILD) {
487 		LIST_REMOVE(dev, si_siblings);
488 		dev->si_flags &= ~SI_CHILD;
489 	}
490 
491 	/* Kill our children */
492 	while (!LIST_EMPTY(&dev->si_children))
493 		destroy_devl(LIST_FIRST(&dev->si_children));
494 
495 	/* Remove from clone list */
496 	if (dev->si_flags & SI_CLONELIST) {
497 		LIST_REMOVE(dev, si_clone);
498 		dev->si_flags &= ~SI_CLONELIST;
499 	}
500 
501 	csw = dev->si_devsw;
502 	dev->si_devsw = NULL;	/* already NULL for SI_ALIAS */
503 	while (csw != NULL && csw->d_purge != NULL && dev->si_threadcount) {
504 		printf("Purging %lu threads from %s\n",
505 		    dev->si_threadcount, devtoname(dev));
506 		csw->d_purge(dev);
507 		msleep(csw, &devmtx, PRIBIO, "devprg", hz/10);
508 	}
509 	if (csw != NULL && csw->d_purge != NULL)
510 		printf("All threads purged from %s\n", devtoname(dev));
511 
512 	dev->si_drv1 = 0;
513 	dev->si_drv2 = 0;
514 	bzero(&dev->__si_u, sizeof(dev->__si_u));
515 
516 	if (!(dev->si_flags & SI_ALIAS)) {
517 		/* Remove from cdevsw list */
518 		LIST_REMOVE(dev, si_list);
519 
520 		/* If cdevsw has no struct cdev *'s, clean it */
521 		if (LIST_EMPTY(&csw->d_devs))
522 			fini_cdevsw(csw);
523 	}
524 	dev->si_flags &= ~SI_ALIAS;
525 
526 	if (dev->si_refcount > 0) {
527 		LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list);
528 	} else {
529 		freedev(dev);
530 	}
531 }
532 
533 void
534 destroy_dev(struct cdev *dev)
535 {
536 
537 	dev_lock();
538 	destroy_devl(dev);
539 	dev_unlock();
540 }
541 
542 const char *
543 devtoname(struct cdev *dev)
544 {
545 	char *p;
546 	struct cdevsw *csw;
547 	int mynor;
548 
549 	if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') {
550 		p = dev->si_name;
551 		csw = dev_refthread(dev);
552 		if (csw != NULL) {
553 			sprintf(p, "(%s)", csw->d_name);
554 			dev_relthread(dev);
555 		}
556 		p += strlen(p);
557 		mynor = minor(dev);
558 		if (mynor < 0 || mynor > 255)
559 			sprintf(p, "/%#x", (u_int)mynor);
560 		else
561 			sprintf(p, "/%d", mynor);
562 	}
563 	return (dev->si_name);
564 }
565 
566 int
567 dev_stdclone(char *name, char **namep, const char *stem, int *unit)
568 {
569 	int u, i;
570 
571 	i = strlen(stem);
572 	if (bcmp(stem, name, i) != 0)
573 		return (0);
574 	if (!isdigit(name[i]))
575 		return (0);
576 	u = 0;
577 	if (name[i] == '0' && isdigit(name[i+1]))
578 		return (0);
579 	while (isdigit(name[i])) {
580 		u *= 10;
581 		u += name[i++] - '0';
582 	}
583 	if (u > 0xffffff)
584 		return (0);
585 	*unit = u;
586 	if (namep)
587 		*namep = &name[i];
588 	if (name[i])
589 		return (2);
590 	return (1);
591 }
592 
593 /*
594  * Helper functions for cloning device drivers.
595  *
596  * The objective here is to make it unnecessary for the device drivers to
597  * use rman or similar to manage their unit number space.  Due to the way
598  * we do "on-demand" devices, using rman or other "private" methods
599  * will be very tricky to lock down properly once we lock down this file.
600  *
601  * Instead we give the drivers these routines which puts the struct cdev *'s
602  * that are to be managed on their own list, and gives the driver the ability
603  * to ask for the first free unit number or a given specified unit number.
604  *
605  * In addition these routines support paired devices (pty, nmdm and similar)
606  * by respecting a number of "flag" bits in the minor number.
607  *
608  */
609 
610 struct clonedevs {
611 	LIST_HEAD(,cdev)	head;
612 };
613 
614 void
615 clone_setup(struct clonedevs **cdp)
616 {
617 
618 	*cdp = malloc(sizeof **cdp, M_DEVBUF, M_WAITOK | M_ZERO);
619 	LIST_INIT(&(*cdp)->head);
620 }
621 
622 int
623 clone_create(struct clonedevs **cdp, struct cdevsw *csw, int *up, struct cdev **dp, u_int extra)
624 {
625 	struct clonedevs *cd;
626 	struct cdev *dev, *ndev, *dl, *de;
627 	int unit, low, u;
628 
629 	KASSERT(*cdp != NULL,
630 	    ("clone_setup() not called in driver \"%s\"", csw->d_name));
631 	KASSERT(!(extra & CLONE_UNITMASK),
632 	    ("Illegal extra bits (0x%x) in clone_create", extra));
633 	KASSERT(*up <= CLONE_UNITMASK,
634 	    ("Too high unit (0x%x) in clone_create", *up));
635 
636 	if (!(csw->d_flags & D_INIT))
637 		prep_cdevsw(csw);
638 
639 	/*
640 	 * Search the list for a lot of things in one go:
641 	 *   A preexisting match is returned immediately.
642 	 *   The lowest free unit number if we are passed -1, and the place
643 	 *	 in the list where we should insert that new element.
644 	 *   The place to insert a specified unit number, if applicable
645 	 *       the end of the list.
646 	 */
647 	unit = *up;
648 	ndev = allocdev();
649 	dev_lock();
650 	low = extra;
651 	de = dl = NULL;
652 	cd = *cdp;
653 	LIST_FOREACH(dev, &cd->head, si_clone) {
654 		KASSERT(dev->si_flags & SI_CLONELIST,
655 		    ("Dev %p(%s) should be on clonelist", dev, dev->si_name));
656 		u = dev2unit(dev);
657 		if (u == (unit | extra)) {
658 			*dp = dev;
659 			freedev(ndev);
660 			dev_unlock();
661 			return (0);
662 		}
663 		if (unit == -1 && u == low) {
664 			low++;
665 			de = dev;
666 			continue;
667 		}
668 		if (u > (unit | extra)) {
669 			dl = dev;
670 			break;
671 		}
672 	}
673 	if (unit == -1)
674 		unit = low & CLONE_UNITMASK;
675 	dev = newdev(csw, unit2minor(unit | extra), ndev);
676 	if (dev->si_flags & SI_CLONELIST) {
677 		printf("dev %p (%s) is on clonelist\n", dev, dev->si_name);
678 		printf("unit=%d\n", unit);
679 		LIST_FOREACH(dev, &cd->head, si_clone) {
680 			printf("\t%p %s\n", dev, dev->si_name);
681 		}
682 		panic("foo");
683 	}
684 	KASSERT(!(dev->si_flags & SI_CLONELIST),
685 	    ("Dev %p(%s) should not be on clonelist", dev, dev->si_name));
686 	if (dl != NULL)
687 		LIST_INSERT_BEFORE(dl, dev, si_clone);
688 	else if (de != NULL)
689 		LIST_INSERT_AFTER(de, dev, si_clone);
690 	else
691 		LIST_INSERT_HEAD(&cd->head, dev, si_clone);
692 	dev->si_flags |= SI_CLONELIST;
693 	*up = unit;
694 	dev_unlock();
695 	return (1);
696 }
697 
698 /*
699  * Kill everything still on the list.  The driver should already have
700  * disposed of any softc hung of the struct cdev *'s at this time.
701  */
702 void
703 clone_cleanup(struct clonedevs **cdp)
704 {
705 	struct cdev *dev, *tdev;
706 	struct clonedevs *cd;
707 
708 	cd = *cdp;
709 	if (cd == NULL)
710 		return;
711 	dev_lock();
712 	LIST_FOREACH_SAFE(dev, &cd->head, si_clone, tdev) {
713 		KASSERT(dev->si_flags & SI_CLONELIST,
714 		    ("Dev %p(%s) should be on clonelist", dev, dev->si_name));
715 		KASSERT(dev->si_flags & SI_NAMED,
716 		    ("Driver has goofed in cloning underways udev %x", dev->si_drv0));
717 		destroy_devl(dev);
718 	}
719 	dev_unlock();
720 	free(cd, M_DEVBUF);
721 	*cdp = NULL;
722 }
723