FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_conf.c
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/bus.h>
34 #include <sys/bio.h>
35 #include <sys/lock.h>
36 #include <sys/mutex.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/sx.h>
44 #include <sys/ctype.h>
45 #include <sys/ucred.h>
46 #include <sys/taskqueue.h>
47 #include <machine/stdarg.h>
48
49 #include <fs/devfs/devfs_int.h>
50 #include <vm/vm.h>
51
52 static MALLOC_DEFINE(M_DEVT, "cdev", "cdev storage");
53
54 struct mtx devmtx;
55 static void destroy_devl(struct cdev *dev);
56 static int destroy_dev_sched_cbl(struct cdev *dev,
57 void (*cb)(void *), void *arg);
58 static void destroy_dev_tq(void *ctx, int pending);
59 static int make_dev_credv(int flags, struct cdev **dres, struct cdevsw *devsw,
60 int unit, struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt,
61 va_list ap);
62
63 static struct cdev_priv_list cdevp_free_list =
64 TAILQ_HEAD_INITIALIZER(cdevp_free_list);
65 static SLIST_HEAD(free_cdevsw, cdevsw) cdevsw_gt_post_list =
66 SLIST_HEAD_INITIALIZER(cdevsw_gt_post_list);
67
68 void
69 dev_lock(void)
70 {
71
72 mtx_lock(&devmtx);
73 }
74
75 /*
76 * Free all the memory collected while the cdev mutex was
77 * locked. Since devmtx is after the system map mutex, free() cannot
78 * be called immediately and is postponed until cdev mutex can be
79 * dropped.
80 */
81 static void
82 dev_unlock_and_free(void)
83 {
84 struct cdev_priv_list cdp_free;
85 struct free_cdevsw csw_free;
86 struct cdev_priv *cdp;
87 struct cdevsw *csw;
88
89 mtx_assert(&devmtx, MA_OWNED);
90
91 /*
92 * Make the local copy of the list heads while the dev_mtx is
93 * held. Free it later.
94 */
95 TAILQ_INIT(&cdp_free);
96 TAILQ_CONCAT(&cdp_free, &cdevp_free_list, cdp_list);
97 csw_free = cdevsw_gt_post_list;
98 SLIST_INIT(&cdevsw_gt_post_list);
99
100 mtx_unlock(&devmtx);
101
102 while ((cdp = TAILQ_FIRST(&cdp_free)) != NULL) {
103 TAILQ_REMOVE(&cdp_free, cdp, cdp_list);
104 devfs_free(&cdp->cdp_c);
105 }
106 while ((csw = SLIST_FIRST(&csw_free)) != NULL) {
107 SLIST_REMOVE_HEAD(&csw_free, d_postfree_list);
108 free(csw, M_DEVT);
109 }
110 }
111
112 static void
113 dev_free_devlocked(struct cdev *cdev)
114 {
115 struct cdev_priv *cdp;
116
117 mtx_assert(&devmtx, MA_OWNED);
118 cdp = cdev2priv(cdev);
119 KASSERT((cdp->cdp_flags & CDP_UNREF_DTR) == 0,
120 ("destroy_dev() was not called after delist_dev(%p)", cdev));
121 TAILQ_INSERT_HEAD(&cdevp_free_list, cdp, cdp_list);
122 }
123
124 static void
125 cdevsw_free_devlocked(struct cdevsw *csw)
126 {
127
128 mtx_assert(&devmtx, MA_OWNED);
129 SLIST_INSERT_HEAD(&cdevsw_gt_post_list, csw, d_postfree_list);
130 }
131
132 void
133 dev_unlock(void)
134 {
135
136 mtx_unlock(&devmtx);
137 }
138
139 void
140 dev_ref(struct cdev *dev)
141 {
142
143 mtx_assert(&devmtx, MA_NOTOWNED);
144 mtx_lock(&devmtx);
145 dev->si_refcount++;
146 mtx_unlock(&devmtx);
147 }
148
149 void
150 dev_refl(struct cdev *dev)
151 {
152
153 mtx_assert(&devmtx, MA_OWNED);
154 dev->si_refcount++;
155 }
156
157 void
158 dev_rel(struct cdev *dev)
159 {
160 int flag = 0;
161
162 mtx_assert(&devmtx, MA_NOTOWNED);
163 dev_lock();
164 dev->si_refcount--;
165 KASSERT(dev->si_refcount >= 0,
166 ("dev_rel(%s) gave negative count", devtoname(dev)));
167 if (dev->si_devsw == NULL && dev->si_refcount == 0) {
168 LIST_REMOVE(dev, si_list);
169 flag = 1;
170 }
171 dev_unlock();
172 if (flag)
173 devfs_free(dev);
174 }
175
176 struct cdevsw *
177 dev_refthread(struct cdev *dev, int *ref)
178 {
179 struct cdevsw *csw;
180 struct cdev_priv *cdp;
181
182 mtx_assert(&devmtx, MA_NOTOWNED);
183 if ((dev->si_flags & SI_ETERNAL) != 0) {
184 *ref = 0;
185 return (dev->si_devsw);
186 }
187 dev_lock();
188 csw = dev->si_devsw;
189 if (csw != NULL) {
190 cdp = cdev2priv(dev);
191 if ((cdp->cdp_flags & CDP_SCHED_DTR) == 0)
192 atomic_add_long(&dev->si_threadcount, 1);
193 else
194 csw = NULL;
195 }
196 dev_unlock();
197 *ref = 1;
198 return (csw);
199 }
200
201 struct cdevsw *
202 devvn_refthread(struct vnode *vp, struct cdev **devp, int *ref)
203 {
204 struct cdevsw *csw;
205 struct cdev_priv *cdp;
206 struct cdev *dev;
207
208 mtx_assert(&devmtx, MA_NOTOWNED);
209 if ((vp->v_vflag & VV_ETERNALDEV) != 0) {
210 dev = vp->v_rdev;
211 if (dev == NULL)
212 return (NULL);
213 KASSERT((dev->si_flags & SI_ETERNAL) != 0,
214 ("Not eternal cdev"));
215 *ref = 0;
216 csw = dev->si_devsw;
217 KASSERT(csw != NULL, ("Eternal cdev is destroyed"));
218 *devp = dev;
219 return (csw);
220 }
221
222 csw = NULL;
223 dev_lock();
224 dev = vp->v_rdev;
225 if (dev == NULL) {
226 dev_unlock();
227 return (NULL);
228 }
229 cdp = cdev2priv(dev);
230 if ((cdp->cdp_flags & CDP_SCHED_DTR) == 0) {
231 csw = dev->si_devsw;
232 if (csw != NULL)
233 atomic_add_long(&dev->si_threadcount, 1);
234 }
235 dev_unlock();
236 if (csw != NULL) {
237 *devp = dev;
238 *ref = 1;
239 }
240 return (csw);
241 }
242
243 void
244 dev_relthread(struct cdev *dev, int ref)
245 {
246
247 mtx_assert(&devmtx, MA_NOTOWNED);
248 if (!ref)
249 return;
250 KASSERT(dev->si_threadcount > 0,
251 ("%s threadcount is wrong", dev->si_name));
252 atomic_subtract_rel_long(&dev->si_threadcount, 1);
253 }
254
255 int
256 nullop(void)
257 {
258
259 return (0);
260 }
261
262 int
263 eopnotsupp(void)
264 {
265
266 return (EOPNOTSUPP);
267 }
268
269 static int
270 enxio(void)
271 {
272 return (ENXIO);
273 }
274
275 static int
276 enodev(void)
277 {
278 return (ENODEV);
279 }
280
281 /* Define a dead_cdevsw for use when devices leave unexpectedly. */
282
283 #define dead_open (d_open_t *)enxio
284 #define dead_close (d_close_t *)enxio
285 #define dead_read (d_read_t *)enxio
286 #define dead_write (d_write_t *)enxio
287 #define dead_ioctl (d_ioctl_t *)enxio
288 #define dead_poll (d_poll_t *)enodev
289 #define dead_mmap (d_mmap_t *)enodev
290
291 static void
292 dead_strategy(struct bio *bp)
293 {
294
295 biofinish(bp, NULL, ENXIO);
296 }
297
298 #define dead_dump (dumper_t *)enxio
299 #define dead_kqfilter (d_kqfilter_t *)enxio
300 #define dead_mmap_single (d_mmap_single_t *)enodev
301
302 static struct cdevsw dead_cdevsw = {
303 .d_version = D_VERSION,
304 .d_open = dead_open,
305 .d_close = dead_close,
306 .d_read = dead_read,
307 .d_write = dead_write,
308 .d_ioctl = dead_ioctl,
309 .d_poll = dead_poll,
310 .d_mmap = dead_mmap,
311 .d_strategy = dead_strategy,
312 .d_name = "dead",
313 .d_dump = dead_dump,
314 .d_kqfilter = dead_kqfilter,
315 .d_mmap_single = dead_mmap_single
316 };
317
318 /* Default methods if driver does not specify method */
319
320 #define null_open (d_open_t *)nullop
321 #define null_close (d_close_t *)nullop
322 #define no_read (d_read_t *)enodev
323 #define no_write (d_write_t *)enodev
324 #define no_ioctl (d_ioctl_t *)enodev
325 #define no_mmap (d_mmap_t *)enodev
326 #define no_kqfilter (d_kqfilter_t *)enodev
327 #define no_mmap_single (d_mmap_single_t *)enodev
328
329 static void
330 no_strategy(struct bio *bp)
331 {
332
333 biofinish(bp, NULL, ENODEV);
334 }
335
336 static int
337 no_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
338 {
339
340 return (poll_no_poll(events));
341 }
342
343 #define no_dump (dumper_t *)enodev
344
345 static int
346 giant_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
347 {
348 struct cdevsw *dsw;
349 int ref, retval;
350
351 dsw = dev_refthread(dev, &ref);
352 if (dsw == NULL)
353 return (ENXIO);
354 mtx_lock(&Giant);
355 retval = dsw->d_gianttrick->d_open(dev, oflags, devtype, td);
356 mtx_unlock(&Giant);
357 dev_relthread(dev, ref);
358 return (retval);
359 }
360
361 static int
362 giant_fdopen(struct cdev *dev, int oflags, struct thread *td, struct file *fp)
363 {
364 struct cdevsw *dsw;
365 int ref, retval;
366
367 dsw = dev_refthread(dev, &ref);
368 if (dsw == NULL)
369 return (ENXIO);
370 mtx_lock(&Giant);
371 retval = dsw->d_gianttrick->d_fdopen(dev, oflags, td, fp);
372 mtx_unlock(&Giant);
373 dev_relthread(dev, ref);
374 return (retval);
375 }
376
377 static int
378 giant_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
379 {
380 struct cdevsw *dsw;
381 int ref, retval;
382
383 dsw = dev_refthread(dev, &ref);
384 if (dsw == NULL)
385 return (ENXIO);
386 mtx_lock(&Giant);
387 retval = dsw->d_gianttrick->d_close(dev, fflag, devtype, td);
388 mtx_unlock(&Giant);
389 dev_relthread(dev, ref);
390 return (retval);
391 }
392
393 static void
394 giant_strategy(struct bio *bp)
395 {
396 struct cdevsw *dsw;
397 struct cdev *dev;
398 int ref;
399
400 dev = bp->bio_dev;
401 dsw = dev_refthread(dev, &ref);
402 if (dsw == NULL) {
403 biofinish(bp, NULL, ENXIO);
404 return;
405 }
406 mtx_lock(&Giant);
407 dsw->d_gianttrick->d_strategy(bp);
408 mtx_unlock(&Giant);
409 dev_relthread(dev, ref);
410 }
411
412 static int
413 giant_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
414 {
415 struct cdevsw *dsw;
416 int ref, retval;
417
418 dsw = dev_refthread(dev, &ref);
419 if (dsw == NULL)
420 return (ENXIO);
421 mtx_lock(&Giant);
422 retval = dsw->d_gianttrick->d_ioctl(dev, cmd, data, fflag, td);
423 mtx_unlock(&Giant);
424 dev_relthread(dev, ref);
425 return (retval);
426 }
427
428 static int
429 giant_read(struct cdev *dev, struct uio *uio, int ioflag)
430 {
431 struct cdevsw *dsw;
432 int ref, retval;
433
434 dsw = dev_refthread(dev, &ref);
435 if (dsw == NULL)
436 return (ENXIO);
437 mtx_lock(&Giant);
438 retval = dsw->d_gianttrick->d_read(dev, uio, ioflag);
439 mtx_unlock(&Giant);
440 dev_relthread(dev, ref);
441 return (retval);
442 }
443
444 static int
445 giant_write(struct cdev *dev, struct uio *uio, int ioflag)
446 {
447 struct cdevsw *dsw;
448 int ref, retval;
449
450 dsw = dev_refthread(dev, &ref);
451 if (dsw == NULL)
452 return (ENXIO);
453 mtx_lock(&Giant);
454 retval = dsw->d_gianttrick->d_write(dev, uio, ioflag);
455 mtx_unlock(&Giant);
456 dev_relthread(dev, ref);
457 return (retval);
458 }
459
460 static int
461 giant_poll(struct cdev *dev, int events, struct thread *td)
462 {
463 struct cdevsw *dsw;
464 int ref, retval;
465
466 dsw = dev_refthread(dev, &ref);
467 if (dsw == NULL)
468 return (ENXIO);
469 mtx_lock(&Giant);
470 retval = dsw->d_gianttrick->d_poll(dev, events, td);
471 mtx_unlock(&Giant);
472 dev_relthread(dev, ref);
473 return (retval);
474 }
475
476 static int
477 giant_kqfilter(struct cdev *dev, struct knote *kn)
478 {
479 struct cdevsw *dsw;
480 int ref, retval;
481
482 dsw = dev_refthread(dev, &ref);
483 if (dsw == NULL)
484 return (ENXIO);
485 mtx_lock(&Giant);
486 retval = dsw->d_gianttrick->d_kqfilter(dev, kn);
487 mtx_unlock(&Giant);
488 dev_relthread(dev, ref);
489 return (retval);
490 }
491
492 static int
493 giant_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot,
494 vm_memattr_t *memattr)
495 {
496 struct cdevsw *dsw;
497 int ref, retval;
498
499 dsw = dev_refthread(dev, &ref);
500 if (dsw == NULL)
501 return (ENXIO);
502 mtx_lock(&Giant);
503 retval = dsw->d_gianttrick->d_mmap(dev, offset, paddr, nprot,
504 memattr);
505 mtx_unlock(&Giant);
506 dev_relthread(dev, ref);
507 return (retval);
508 }
509
510 static int
511 giant_mmap_single(struct cdev *dev, vm_ooffset_t *offset, vm_size_t size,
512 vm_object_t *object, int nprot)
513 {
514 struct cdevsw *dsw;
515 int ref, retval;
516
517 dsw = dev_refthread(dev, &ref);
518 if (dsw == NULL)
519 return (ENXIO);
520 mtx_lock(&Giant);
521 retval = dsw->d_gianttrick->d_mmap_single(dev, offset, size, object,
522 nprot);
523 mtx_unlock(&Giant);
524 dev_relthread(dev, ref);
525 return (retval);
526 }
527
528 static void
529 notify(struct cdev *dev, const char *ev, int flags)
530 {
531 static const char prefix[] = "cdev=";
532 char *data;
533 int namelen, mflags;
534
535 if (cold)
536 return;
537 mflags = (flags & MAKEDEV_NOWAIT) ? M_NOWAIT : M_WAITOK;
538 namelen = strlen(dev->si_name);
539 data = malloc(namelen + sizeof(prefix), M_TEMP, mflags);
540 if (data == NULL)
541 return;
542 memcpy(data, prefix, sizeof(prefix) - 1);
543 memcpy(data + sizeof(prefix) - 1, dev->si_name, namelen + 1);
544 devctl_notify_f("DEVFS", "CDEV", ev, data, mflags);
545 free(data, M_TEMP);
546 }
547
548 static void
549 notify_create(struct cdev *dev, int flags)
550 {
551
552 notify(dev, "CREATE", flags);
553 }
554
555 static void
556 notify_destroy(struct cdev *dev)
557 {
558
559 notify(dev, "DESTROY", MAKEDEV_WAITOK);
560 }
561
562 static struct cdev *
563 newdev(struct make_dev_args *args, struct cdev *si)
564 {
565 struct cdev *si2;
566 struct cdevsw *csw;
567
568 mtx_assert(&devmtx, MA_OWNED);
569 csw = args->mda_devsw;
570 si2 = NULL;
571 if (csw->d_flags & D_NEEDMINOR) {
572 /* We may want to return an existing device */
573 LIST_FOREACH(si2, &csw->d_devs, si_list) {
574 if (dev2unit(si2) == args->mda_unit) {
575 dev_free_devlocked(si);
576 si = si2;
577 break;
578 }
579 }
580
581 /*
582 * If we're returning an existing device, we should make sure
583 * it isn't already initialized. This would have been caught
584 * in consumers anyways, but it's good to catch such a case
585 * early. We still need to complete initialization of the
586 * device, and we'll use whatever make_dev_args were passed in
587 * to do so.
588 */
589 KASSERT(si2 == NULL || (si2->si_flags & SI_NAMED) == 0,
590 ("make_dev() by driver %s on pre-existing device (min=%x, name=%s)",
591 args->mda_devsw->d_name, dev2unit(si2), devtoname(si2)));
592 }
593 si->si_drv0 = args->mda_unit;
594 si->si_drv1 = args->mda_si_drv1;
595 si->si_drv2 = args->mda_si_drv2;
596 /* Only push to csw->d_devs if it's not a cloned device. */
597 if (si2 == NULL) {
598 si->si_devsw = csw;
599 LIST_INSERT_HEAD(&csw->d_devs, si, si_list);
600 } else {
601 KASSERT(si->si_devsw == csw,
602 ("%s: inconsistent devsw between clone_create() and make_dev()",
603 __func__));
604 }
605 return (si);
606 }
607
608 static void
609 fini_cdevsw(struct cdevsw *devsw)
610 {
611 struct cdevsw *gt;
612
613 if (devsw->d_gianttrick != NULL) {
614 gt = devsw->d_gianttrick;
615 memcpy(devsw, gt, sizeof *devsw);
616 cdevsw_free_devlocked(gt);
617 devsw->d_gianttrick = NULL;
618 }
619 devsw->d_flags &= ~D_INIT;
620 }
621
622 static int
623 prep_cdevsw(struct cdevsw *devsw, int flags)
624 {
625 struct cdevsw *dsw2;
626
627 mtx_assert(&devmtx, MA_OWNED);
628 if (devsw->d_flags & D_INIT)
629 return (0);
630 if (devsw->d_flags & D_NEEDGIANT) {
631 dev_unlock();
632 dsw2 = malloc(sizeof *dsw2, M_DEVT,
633 (flags & MAKEDEV_NOWAIT) ? M_NOWAIT : M_WAITOK);
634 dev_lock();
635 if (dsw2 == NULL && !(devsw->d_flags & D_INIT))
636 return (ENOMEM);
637 } else
638 dsw2 = NULL;
639 if (devsw->d_flags & D_INIT) {
640 if (dsw2 != NULL)
641 cdevsw_free_devlocked(dsw2);
642 return (0);
643 }
644
645 if (devsw->d_version != D_VERSION_03) {
646 printf(
647 "WARNING: Device driver \"%s\" has wrong version %s\n",
648 devsw->d_name == NULL ? "???" : devsw->d_name,
649 "and is disabled. Recompile KLD module.");
650 devsw->d_open = dead_open;
651 devsw->d_close = dead_close;
652 devsw->d_read = dead_read;
653 devsw->d_write = dead_write;
654 devsw->d_ioctl = dead_ioctl;
655 devsw->d_poll = dead_poll;
656 devsw->d_mmap = dead_mmap;
657 devsw->d_mmap_single = dead_mmap_single;
658 devsw->d_strategy = dead_strategy;
659 devsw->d_dump = dead_dump;
660 devsw->d_kqfilter = dead_kqfilter;
661 }
662
663 if (devsw->d_flags & D_NEEDGIANT) {
664 if (devsw->d_gianttrick == NULL) {
665 memcpy(dsw2, devsw, sizeof *dsw2);
666 devsw->d_gianttrick = dsw2;
667 dsw2 = NULL;
668 }
669 }
670
671 #define FIXUP(member, noop, giant) \
672 do { \
673 if (devsw->member == NULL) { \
674 devsw->member = noop; \
675 } else if (devsw->d_flags & D_NEEDGIANT) \
676 devsw->member = giant; \
677 } \
678 while (0)
679
680 FIXUP(d_open, null_open, giant_open);
681 FIXUP(d_fdopen, NULL, giant_fdopen);
682 FIXUP(d_close, null_close, giant_close);
683 FIXUP(d_read, no_read, giant_read);
684 FIXUP(d_write, no_write, giant_write);
685 FIXUP(d_ioctl, no_ioctl, giant_ioctl);
686 FIXUP(d_poll, no_poll, giant_poll);
687 FIXUP(d_mmap, no_mmap, giant_mmap);
688 FIXUP(d_strategy, no_strategy, giant_strategy);
689 FIXUP(d_kqfilter, no_kqfilter, giant_kqfilter);
690 FIXUP(d_mmap_single, no_mmap_single, giant_mmap_single);
691
692 if (devsw->d_dump == NULL) devsw->d_dump = no_dump;
693
694 LIST_INIT(&devsw->d_devs);
695
696 devsw->d_flags |= D_INIT;
697
698 if (dsw2 != NULL)
699 cdevsw_free_devlocked(dsw2);
700 return (0);
701 }
702
703 static int
704 prep_devname(struct cdev *dev, const char *fmt, va_list ap)
705 {
706 int len;
707 char *from, *q, *s, *to;
708
709 mtx_assert(&devmtx, MA_OWNED);
710
711 len = vsnrprintf(dev->si_name, sizeof(dev->si_name), 32, fmt, ap);
712 if (len > sizeof(dev->si_name) - 1)
713 return (ENAMETOOLONG);
714
715 /* Strip leading slashes. */
716 for (from = dev->si_name; *from == '/'; from++)
717 ;
718
719 for (to = dev->si_name; *from != '\0'; from++, to++) {
720 /*
721 * Spaces and double quotation marks cause
722 * problems for the devctl(4) protocol.
723 * Reject names containing those characters.
724 */
725 if (isspace(*from) || *from == '"')
726 return (EINVAL);
727 /* Treat multiple sequential slashes as single. */
728 while (from[0] == '/' && from[1] == '/')
729 from++;
730 /* Trailing slash is considered invalid. */
731 if (from[0] == '/' && from[1] == '\0')
732 return (EINVAL);
733 *to = *from;
734 }
735 *to = '\0';
736
737 if (dev->si_name[0] == '\0')
738 return (EINVAL);
739
740 /* Disallow "." and ".." components. */
741 for (s = dev->si_name;;) {
742 for (q = s; *q != '/' && *q != '\0'; q++)
743 ;
744 if (q - s == 1 && s[0] == '.')
745 return (EINVAL);
746 if (q - s == 2 && s[0] == '.' && s[1] == '.')
747 return (EINVAL);
748 if (*q != '/')
749 break;
750 s = q + 1;
751 }
752
753 if (devfs_dev_exists(dev->si_name) != 0)
754 return (EEXIST);
755
756 return (0);
757 }
758
759 void
760 make_dev_args_init_impl(struct make_dev_args *args, size_t sz)
761 {
762
763 bzero(args, sz);
764 args->mda_size = sz;
765 }
766
767 static int
768 make_dev_sv(struct make_dev_args *args1, struct cdev **dres,
769 const char *fmt, va_list ap)
770 {
771 struct cdev *dev, *dev_new;
772 struct make_dev_args args;
773 int res;
774
775 bzero(&args, sizeof(args));
776 if (sizeof(args) < args1->mda_size)
777 return (EINVAL);
778 bcopy(args1, &args, args1->mda_size);
779 KASSERT((args.mda_flags & MAKEDEV_WAITOK) == 0 ||
780 (args.mda_flags & MAKEDEV_NOWAIT) == 0,
781 ("make_dev_sv: both WAITOK and NOWAIT specified"));
782 dev_new = devfs_alloc(args.mda_flags);
783 if (dev_new == NULL)
784 return (ENOMEM);
785 dev_lock();
786 res = prep_cdevsw(args.mda_devsw, args.mda_flags);
787 if (res != 0) {
788 dev_unlock();
789 devfs_free(dev_new);
790 return (res);
791 }
792 dev = newdev(&args, dev_new);
793 if ((dev->si_flags & SI_NAMED) == 0) {
794 res = prep_devname(dev, fmt, ap);
795 if (res != 0) {
796 if ((args.mda_flags & MAKEDEV_CHECKNAME) == 0) {
797 panic(
798 "make_dev_sv: bad si_name (error=%d, si_name=%s)",
799 res, dev->si_name);
800 }
801 if (dev == dev_new) {
802 LIST_REMOVE(dev, si_list);
803 dev_unlock();
804 devfs_free(dev);
805 } else
806 dev_unlock();
807 return (res);
808 }
809 }
810 if ((args.mda_flags & MAKEDEV_REF) != 0)
811 dev_refl(dev);
812 if ((args.mda_flags & MAKEDEV_ETERNAL) != 0)
813 dev->si_flags |= SI_ETERNAL;
814 KASSERT(!(dev->si_flags & SI_NAMED),
815 ("make_dev() by driver %s on pre-existing device (min=%x, name=%s)",
816 args.mda_devsw->d_name, dev2unit(dev), devtoname(dev)));
817 dev->si_flags |= SI_NAMED;
818 if (args.mda_cr != NULL)
819 dev->si_cred = crhold(args.mda_cr);
820 dev->si_uid = args.mda_uid;
821 dev->si_gid = args.mda_gid;
822 dev->si_mode = args.mda_mode;
823
824 devfs_create(dev);
825 clean_unrhdrl(devfs_inos);
826 dev_unlock_and_free();
827
828 notify_create(dev, args.mda_flags);
829
830 *dres = dev;
831 return (0);
832 }
833
834 int
835 make_dev_s(struct make_dev_args *args, struct cdev **dres,
836 const char *fmt, ...)
837 {
838 va_list ap;
839 int res;
840
841 va_start(ap, fmt);
842 res = make_dev_sv(args, dres, fmt, ap);
843 va_end(ap);
844 return (res);
845 }
846
847 static int
848 make_dev_credv(int flags, struct cdev **dres, struct cdevsw *devsw, int unit,
849 struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt,
850 va_list ap)
851 {
852 struct make_dev_args args;
853
854 make_dev_args_init(&args);
855 args.mda_flags = flags;
856 args.mda_devsw = devsw;
857 args.mda_cr = cr;
858 args.mda_uid = uid;
859 args.mda_gid = gid;
860 args.mda_mode = mode;
861 args.mda_unit = unit;
862 return (make_dev_sv(&args, dres, fmt, ap));
863 }
864
865 struct cdev *
866 make_dev(struct cdevsw *devsw, int unit, uid_t uid, gid_t gid, int mode,
867 const char *fmt, ...)
868 {
869 struct cdev *dev;
870 va_list ap;
871 int res;
872
873 va_start(ap, fmt);
874 res = make_dev_credv(0, &dev, devsw, unit, NULL, uid, gid, mode, fmt,
875 ap);
876 va_end(ap);
877 KASSERT(res == 0 && dev != NULL,
878 ("make_dev: failed make_dev_credv (error=%d)", res));
879 return (dev);
880 }
881
882 struct cdev *
883 make_dev_cred(struct cdevsw *devsw, int unit, struct ucred *cr, uid_t uid,
884 gid_t gid, int mode, const char *fmt, ...)
885 {
886 struct cdev *dev;
887 va_list ap;
888 int res;
889
890 va_start(ap, fmt);
891 res = make_dev_credv(0, &dev, devsw, unit, cr, uid, gid, mode, fmt, ap);
892 va_end(ap);
893
894 KASSERT(res == 0 && dev != NULL,
895 ("make_dev_cred: failed make_dev_credv (error=%d)", res));
896 return (dev);
897 }
898
899 struct cdev *
900 make_dev_credf(int flags, struct cdevsw *devsw, int unit, struct ucred *cr,
901 uid_t uid, gid_t gid, int mode, const char *fmt, ...)
902 {
903 struct cdev *dev;
904 va_list ap;
905 int res;
906
907 va_start(ap, fmt);
908 res = make_dev_credv(flags, &dev, devsw, unit, cr, uid, gid, mode,
909 fmt, ap);
910 va_end(ap);
911
912 KASSERT(((flags & MAKEDEV_NOWAIT) != 0 && res == ENOMEM) ||
913 ((flags & MAKEDEV_CHECKNAME) != 0 && res != ENOMEM) || res == 0,
914 ("make_dev_credf: failed make_dev_credv (error=%d)", res));
915 return (res == 0 ? dev : NULL);
916 }
917
918 int
919 make_dev_p(int flags, struct cdev **cdev, struct cdevsw *devsw,
920 struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt, ...)
921 {
922 va_list ap;
923 int res;
924
925 va_start(ap, fmt);
926 res = make_dev_credv(flags, cdev, devsw, 0, cr, uid, gid, mode,
927 fmt, ap);
928 va_end(ap);
929
930 KASSERT(((flags & MAKEDEV_NOWAIT) != 0 && res == ENOMEM) ||
931 ((flags & MAKEDEV_CHECKNAME) != 0 && res != ENOMEM) || res == 0,
932 ("make_dev_p: failed make_dev_credv (error=%d)", res));
933 return (res);
934 }
935
936 static void
937 dev_dependsl(struct cdev *pdev, struct cdev *cdev)
938 {
939
940 cdev->si_parent = pdev;
941 cdev->si_flags |= SI_CHILD;
942 LIST_INSERT_HEAD(&pdev->si_children, cdev, si_siblings);
943 }
944
945
946 void
947 dev_depends(struct cdev *pdev, struct cdev *cdev)
948 {
949
950 dev_lock();
951 dev_dependsl(pdev, cdev);
952 dev_unlock();
953 }
954
955 static int
956 make_dev_alias_v(int flags, struct cdev **cdev, struct cdev *pdev,
957 const char *fmt, va_list ap)
958 {
959 struct cdev *dev;
960 int error;
961
962 KASSERT(pdev != NULL, ("make_dev_alias_v: pdev is NULL"));
963 KASSERT((flags & MAKEDEV_WAITOK) == 0 || (flags & MAKEDEV_NOWAIT) == 0,
964 ("make_dev_alias_v: both WAITOK and NOWAIT specified"));
965 KASSERT((flags & ~(MAKEDEV_WAITOK | MAKEDEV_NOWAIT |
966 MAKEDEV_CHECKNAME)) == 0,
967 ("make_dev_alias_v: invalid flags specified (flags=%02x)", flags));
968
969 dev = devfs_alloc(flags);
970 if (dev == NULL)
971 return (ENOMEM);
972 dev_lock();
973 dev->si_flags |= SI_ALIAS;
974 error = prep_devname(dev, fmt, ap);
975 if (error != 0) {
976 if ((flags & MAKEDEV_CHECKNAME) == 0) {
977 panic("make_dev_alias_v: bad si_name "
978 "(error=%d, si_name=%s)", error, dev->si_name);
979 }
980 dev_unlock();
981 devfs_free(dev);
982 return (error);
983 }
984 dev->si_flags |= SI_NAMED;
985 devfs_create(dev);
986 dev_dependsl(pdev, dev);
987 clean_unrhdrl(devfs_inos);
988 dev_unlock();
989
990 notify_create(dev, flags);
991 *cdev = dev;
992
993 return (0);
994 }
995
996 struct cdev *
997 make_dev_alias(struct cdev *pdev, const char *fmt, ...)
998 {
999 struct cdev *dev;
1000 va_list ap;
1001 int res;
1002
1003 va_start(ap, fmt);
1004 res = make_dev_alias_v(MAKEDEV_WAITOK, &dev, pdev, fmt, ap);
1005 va_end(ap);
1006
1007 KASSERT(res == 0 && dev != NULL,
1008 ("make_dev_alias: failed make_dev_alias_v (error=%d)", res));
1009 return (dev);
1010 }
1011
1012 int
1013 make_dev_alias_p(int flags, struct cdev **cdev, struct cdev *pdev,
1014 const char *fmt, ...)
1015 {
1016 va_list ap;
1017 int res;
1018
1019 va_start(ap, fmt);
1020 res = make_dev_alias_v(flags, cdev, pdev, fmt, ap);
1021 va_end(ap);
1022 return (res);
1023 }
1024
1025 int
1026 make_dev_physpath_alias(int flags, struct cdev **cdev, struct cdev *pdev,
1027 struct cdev *old_alias, const char *physpath)
1028 {
1029 char *devfspath;
1030 int physpath_len;
1031 int max_parentpath_len;
1032 int parentpath_len;
1033 int devfspathbuf_len;
1034 int mflags;
1035 int ret;
1036
1037 *cdev = NULL;
1038 devfspath = NULL;
1039 physpath_len = strlen(physpath);
1040 ret = EINVAL;
1041 if (physpath_len == 0)
1042 goto out;
1043
1044 if (strncmp("id1,", physpath, 4) == 0) {
1045 physpath += 4;
1046 physpath_len -= 4;
1047 if (physpath_len == 0)
1048 goto out;
1049 }
1050
1051 max_parentpath_len = SPECNAMELEN - physpath_len - /*/*/1;
1052 parentpath_len = strlen(pdev->si_name);
1053 if (max_parentpath_len < parentpath_len) {
1054 if (bootverbose)
1055 printf("WARNING: Unable to alias %s "
1056 "to %s/%s - path too long\n",
1057 pdev->si_name, physpath, pdev->si_name);
1058 ret = ENAMETOOLONG;
1059 goto out;
1060 }
1061
1062 mflags = (flags & MAKEDEV_NOWAIT) ? M_NOWAIT : M_WAITOK;
1063 devfspathbuf_len = physpath_len + /*/*/1 + parentpath_len + /*NUL*/1;
1064 devfspath = malloc(devfspathbuf_len, M_DEVBUF, mflags);
1065 if (devfspath == NULL) {
1066 ret = ENOMEM;
1067 goto out;
1068 }
1069
1070 sprintf(devfspath, "%s/%s", physpath, pdev->si_name);
1071 if (old_alias != NULL && strcmp(old_alias->si_name, devfspath) == 0) {
1072 /* Retain the existing alias. */
1073 *cdev = old_alias;
1074 old_alias = NULL;
1075 ret = 0;
1076 } else {
1077 ret = make_dev_alias_p(flags, cdev, pdev, "%s", devfspath);
1078 }
1079 out:
1080 if (old_alias != NULL)
1081 destroy_dev(old_alias);
1082 if (devfspath != NULL)
1083 free(devfspath, M_DEVBUF);
1084 return (ret);
1085 }
1086
1087 static void
1088 destroy_devl(struct cdev *dev)
1089 {
1090 struct cdevsw *csw;
1091 struct cdev_privdata *p;
1092 struct cdev_priv *cdp;
1093
1094 mtx_assert(&devmtx, MA_OWNED);
1095 KASSERT(dev->si_flags & SI_NAMED,
1096 ("WARNING: Driver mistake: destroy_dev on %d\n", dev2unit(dev)));
1097 KASSERT((dev->si_flags & SI_ETERNAL) == 0,
1098 ("WARNING: Driver mistake: destroy_dev on eternal %d\n",
1099 dev2unit(dev)));
1100
1101 cdp = cdev2priv(dev);
1102 if ((cdp->cdp_flags & CDP_UNREF_DTR) == 0) {
1103 /*
1104 * Avoid race with dev_rel(), e.g. from the populate
1105 * loop. If CDP_UNREF_DTR flag is set, the reference
1106 * to be dropped at the end of destroy_devl() was
1107 * already taken by delist_dev_locked().
1108 */
1109 dev_refl(dev);
1110
1111 devfs_destroy(dev);
1112 }
1113
1114 /* Remove name marking */
1115 dev->si_flags &= ~SI_NAMED;
1116
1117 /* If we are a child, remove us from the parents list */
1118 if (dev->si_flags & SI_CHILD) {
1119 LIST_REMOVE(dev, si_siblings);
1120 dev->si_flags &= ~SI_CHILD;
1121 }
1122
1123 /* Kill our children */
1124 while (!LIST_EMPTY(&dev->si_children))
1125 destroy_devl(LIST_FIRST(&dev->si_children));
1126
1127 /* Remove from clone list */
1128 if (dev->si_flags & SI_CLONELIST) {
1129 LIST_REMOVE(dev, si_clone);
1130 dev->si_flags &= ~SI_CLONELIST;
1131 }
1132
1133 csw = dev->si_devsw;
1134 dev->si_devsw = NULL; /* already NULL for SI_ALIAS */
1135 while (csw != NULL && csw->d_purge != NULL && dev->si_threadcount) {
1136 csw->d_purge(dev);
1137 msleep(csw, &devmtx, PRIBIO, "devprg", hz/10);
1138 if (dev->si_threadcount)
1139 printf("Still %lu threads in %s\n",
1140 dev->si_threadcount, devtoname(dev));
1141 }
1142 while (dev->si_threadcount != 0) {
1143 /* Use unique dummy wait ident */
1144 msleep(&csw, &devmtx, PRIBIO, "devdrn", hz / 10);
1145 }
1146
1147 dev_unlock();
1148 if ((cdp->cdp_flags & CDP_UNREF_DTR) == 0) {
1149 /* avoid out of order notify events */
1150 notify_destroy(dev);
1151 }
1152 mtx_lock(&cdevpriv_mtx);
1153 while ((p = LIST_FIRST(&cdp->cdp_fdpriv)) != NULL) {
1154 devfs_destroy_cdevpriv(p);
1155 mtx_lock(&cdevpriv_mtx);
1156 }
1157 mtx_unlock(&cdevpriv_mtx);
1158 dev_lock();
1159
1160 dev->si_drv1 = 0;
1161 dev->si_drv2 = 0;
1162 bzero(&dev->__si_u, sizeof(dev->__si_u));
1163
1164 if (!(dev->si_flags & SI_ALIAS)) {
1165 /* Remove from cdevsw list */
1166 LIST_REMOVE(dev, si_list);
1167
1168 /* If cdevsw has no more struct cdev *'s, clean it */
1169 if (LIST_EMPTY(&csw->d_devs)) {
1170 fini_cdevsw(csw);
1171 wakeup(&csw->d_devs);
1172 }
1173 }
1174 dev->si_flags &= ~SI_ALIAS;
1175 cdp->cdp_flags &= ~CDP_UNREF_DTR;
1176 dev->si_refcount--;
1177
1178 if (dev->si_refcount > 0)
1179 LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list);
1180 else
1181 dev_free_devlocked(dev);
1182 }
1183
1184 static void
1185 delist_dev_locked(struct cdev *dev)
1186 {
1187 struct cdev_priv *cdp;
1188 struct cdev *child;
1189
1190 mtx_assert(&devmtx, MA_OWNED);
1191 cdp = cdev2priv(dev);
1192 if ((cdp->cdp_flags & CDP_UNREF_DTR) != 0)
1193 return;
1194 cdp->cdp_flags |= CDP_UNREF_DTR;
1195 dev_refl(dev);
1196 devfs_destroy(dev);
1197 LIST_FOREACH(child, &dev->si_children, si_siblings)
1198 delist_dev_locked(child);
1199 dev_unlock();
1200 /* ensure the destroy event is queued in order */
1201 notify_destroy(dev);
1202 dev_lock();
1203 }
1204
1205 /*
1206 * This function will delist a character device and its children from
1207 * the directory listing and create a destroy event without waiting
1208 * for all character device references to go away. At some later point
1209 * destroy_dev() must be called to complete the character device
1210 * destruction. After calling this function the character device name
1211 * can instantly be re-used.
1212 */
1213 void
1214 delist_dev(struct cdev *dev)
1215 {
1216
1217 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "delist_dev");
1218 dev_lock();
1219 delist_dev_locked(dev);
1220 dev_unlock();
1221 }
1222
1223 void
1224 destroy_dev(struct cdev *dev)
1225 {
1226
1227 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "destroy_dev");
1228 dev_lock();
1229 destroy_devl(dev);
1230 dev_unlock_and_free();
1231 }
1232
1233 const char *
1234 devtoname(struct cdev *dev)
1235 {
1236
1237 return (dev->si_name);
1238 }
1239
1240 int
1241 dev_stdclone(char *name, char **namep, const char *stem, int *unit)
1242 {
1243 int u, i;
1244
1245 i = strlen(stem);
1246 if (bcmp(stem, name, i) != 0)
1247 return (0);
1248 if (!isdigit(name[i]))
1249 return (0);
1250 u = 0;
1251 if (name[i] == '' && isdigit(name[i+1]))
1252 return (0);
1253 while (isdigit(name[i])) {
1254 u *= 10;
1255 u += name[i++] - '';
1256 }
1257 if (u > 0xffffff)
1258 return (0);
1259 *unit = u;
1260 if (namep)
1261 *namep = &name[i];
1262 if (name[i])
1263 return (2);
1264 return (1);
1265 }
1266
1267 /*
1268 * Helper functions for cloning device drivers.
1269 *
1270 * The objective here is to make it unnecessary for the device drivers to
1271 * use rman or similar to manage their unit number space. Due to the way
1272 * we do "on-demand" devices, using rman or other "private" methods
1273 * will be very tricky to lock down properly once we lock down this file.
1274 *
1275 * Instead we give the drivers these routines which puts the struct cdev *'s
1276 * that are to be managed on their own list, and gives the driver the ability
1277 * to ask for the first free unit number or a given specified unit number.
1278 *
1279 * In addition these routines support paired devices (pty, nmdm and similar)
1280 * by respecting a number of "flag" bits in the minor number.
1281 *
1282 */
1283
1284 struct clonedevs {
1285 LIST_HEAD(,cdev) head;
1286 };
1287
1288 void
1289 clone_setup(struct clonedevs **cdp)
1290 {
1291
1292 *cdp = malloc(sizeof **cdp, M_DEVBUF, M_WAITOK | M_ZERO);
1293 LIST_INIT(&(*cdp)->head);
1294 }
1295
1296 int
1297 clone_create(struct clonedevs **cdp, struct cdevsw *csw, int *up,
1298 struct cdev **dp, int extra)
1299 {
1300 struct clonedevs *cd;
1301 struct cdev *dev, *ndev, *dl, *de;
1302 struct make_dev_args args;
1303 int unit, low, u;
1304
1305 KASSERT(*cdp != NULL,
1306 ("clone_setup() not called in driver \"%s\"", csw->d_name));
1307 KASSERT(!(extra & CLONE_UNITMASK),
1308 ("Illegal extra bits (0x%x) in clone_create", extra));
1309 KASSERT(*up <= CLONE_UNITMASK,
1310 ("Too high unit (0x%x) in clone_create", *up));
1311 KASSERT(csw->d_flags & D_NEEDMINOR,
1312 ("clone_create() on cdevsw without minor numbers"));
1313
1314
1315 /*
1316 * Search the list for a lot of things in one go:
1317 * A preexisting match is returned immediately.
1318 * The lowest free unit number if we are passed -1, and the place
1319 * in the list where we should insert that new element.
1320 * The place to insert a specified unit number, if applicable
1321 * the end of the list.
1322 */
1323 unit = *up;
1324 ndev = devfs_alloc(MAKEDEV_WAITOK);
1325 dev_lock();
1326 prep_cdevsw(csw, MAKEDEV_WAITOK);
1327 low = extra;
1328 de = dl = NULL;
1329 cd = *cdp;
1330 LIST_FOREACH(dev, &cd->head, si_clone) {
1331 KASSERT(dev->si_flags & SI_CLONELIST,
1332 ("Dev %p(%s) should be on clonelist", dev, dev->si_name));
1333 u = dev2unit(dev);
1334 if (u == (unit | extra)) {
1335 *dp = dev;
1336 dev_unlock();
1337 devfs_free(ndev);
1338 return (0);
1339 }
1340 if (unit == -1 && u == low) {
1341 low++;
1342 de = dev;
1343 continue;
1344 } else if (u < (unit | extra)) {
1345 de = dev;
1346 continue;
1347 } else if (u > (unit | extra)) {
1348 dl = dev;
1349 break;
1350 }
1351 }
1352 if (unit == -1)
1353 unit = low & CLONE_UNITMASK;
1354 make_dev_args_init(&args);
1355 args.mda_unit = unit | extra;
1356 args.mda_devsw = csw;
1357 dev = newdev(&args, ndev);
1358 if (dev->si_flags & SI_CLONELIST) {
1359 printf("dev %p (%s) is on clonelist\n", dev, dev->si_name);
1360 printf("unit=%d, low=%d, extra=0x%x\n", unit, low, extra);
1361 LIST_FOREACH(dev, &cd->head, si_clone) {
1362 printf("\t%p %s\n", dev, dev->si_name);
1363 }
1364 panic("foo");
1365 }
1366 KASSERT(!(dev->si_flags & SI_CLONELIST),
1367 ("Dev %p(%s) should not be on clonelist", dev, dev->si_name));
1368 if (dl != NULL)
1369 LIST_INSERT_BEFORE(dl, dev, si_clone);
1370 else if (de != NULL)
1371 LIST_INSERT_AFTER(de, dev, si_clone);
1372 else
1373 LIST_INSERT_HEAD(&cd->head, dev, si_clone);
1374 dev->si_flags |= SI_CLONELIST;
1375 *up = unit;
1376 dev_unlock_and_free();
1377 return (1);
1378 }
1379
1380 /*
1381 * Kill everything still on the list. The driver should already have
1382 * disposed of any softc hung of the struct cdev *'s at this time.
1383 */
1384 void
1385 clone_cleanup(struct clonedevs **cdp)
1386 {
1387 struct cdev *dev;
1388 struct cdev_priv *cp;
1389 struct clonedevs *cd;
1390
1391 cd = *cdp;
1392 if (cd == NULL)
1393 return;
1394 dev_lock();
1395 while (!LIST_EMPTY(&cd->head)) {
1396 dev = LIST_FIRST(&cd->head);
1397 LIST_REMOVE(dev, si_clone);
1398 KASSERT(dev->si_flags & SI_CLONELIST,
1399 ("Dev %p(%s) should be on clonelist", dev, dev->si_name));
1400 dev->si_flags &= ~SI_CLONELIST;
1401 cp = cdev2priv(dev);
1402 if (!(cp->cdp_flags & CDP_SCHED_DTR)) {
1403 cp->cdp_flags |= CDP_SCHED_DTR;
1404 KASSERT(dev->si_flags & SI_NAMED,
1405 ("Driver has goofed in cloning underways udev %jx unit %x",
1406 (uintmax_t)dev2udev(dev), dev2unit(dev)));
1407 destroy_devl(dev);
1408 }
1409 }
1410 dev_unlock_and_free();
1411 free(cd, M_DEVBUF);
1412 *cdp = NULL;
1413 }
1414
1415 static TAILQ_HEAD(, cdev_priv) dev_ddtr =
1416 TAILQ_HEAD_INITIALIZER(dev_ddtr);
1417 static struct task dev_dtr_task = TASK_INITIALIZER(0, destroy_dev_tq, NULL);
1418
1419 static void
1420 destroy_dev_tq(void *ctx, int pending)
1421 {
1422 struct cdev_priv *cp;
1423 struct cdev *dev;
1424 void (*cb)(void *);
1425 void *cb_arg;
1426
1427 dev_lock();
1428 while (!TAILQ_EMPTY(&dev_ddtr)) {
1429 cp = TAILQ_FIRST(&dev_ddtr);
1430 dev = &cp->cdp_c;
1431 KASSERT(cp->cdp_flags & CDP_SCHED_DTR,
1432 ("cdev %p in dev_destroy_tq without CDP_SCHED_DTR", cp));
1433 TAILQ_REMOVE(&dev_ddtr, cp, cdp_dtr_list);
1434 cb = cp->cdp_dtr_cb;
1435 cb_arg = cp->cdp_dtr_cb_arg;
1436 destroy_devl(dev);
1437 dev_unlock_and_free();
1438 dev_rel(dev);
1439 if (cb != NULL)
1440 cb(cb_arg);
1441 dev_lock();
1442 }
1443 dev_unlock();
1444 }
1445
1446 /*
1447 * devmtx shall be locked on entry. devmtx will be unlocked after
1448 * function return.
1449 */
1450 static int
1451 destroy_dev_sched_cbl(struct cdev *dev, void (*cb)(void *), void *arg)
1452 {
1453 struct cdev_priv *cp;
1454
1455 mtx_assert(&devmtx, MA_OWNED);
1456 cp = cdev2priv(dev);
1457 if (cp->cdp_flags & CDP_SCHED_DTR) {
1458 dev_unlock();
1459 return (0);
1460 }
1461 dev_refl(dev);
1462 cp->cdp_flags |= CDP_SCHED_DTR;
1463 cp->cdp_dtr_cb = cb;
1464 cp->cdp_dtr_cb_arg = arg;
1465 TAILQ_INSERT_TAIL(&dev_ddtr, cp, cdp_dtr_list);
1466 dev_unlock();
1467 taskqueue_enqueue(taskqueue_swi_giant, &dev_dtr_task);
1468 return (1);
1469 }
1470
1471 int
1472 destroy_dev_sched_cb(struct cdev *dev, void (*cb)(void *), void *arg)
1473 {
1474
1475 dev_lock();
1476 return (destroy_dev_sched_cbl(dev, cb, arg));
1477 }
1478
1479 int
1480 destroy_dev_sched(struct cdev *dev)
1481 {
1482
1483 return (destroy_dev_sched_cb(dev, NULL, NULL));
1484 }
1485
1486 void
1487 destroy_dev_drain(struct cdevsw *csw)
1488 {
1489
1490 dev_lock();
1491 while (!LIST_EMPTY(&csw->d_devs)) {
1492 msleep(&csw->d_devs, &devmtx, PRIBIO, "devscd", hz/10);
1493 }
1494 dev_unlock();
1495 }
1496
1497 void
1498 drain_dev_clone_events(void)
1499 {
1500
1501 sx_xlock(&clone_drain_lock);
1502 sx_xunlock(&clone_drain_lock);
1503 }
1504
1505 #include "opt_ddb.h"
1506 #ifdef DDB
1507 #include <sys/kernel.h>
1508
1509 #include <ddb/ddb.h>
1510
1511 DB_SHOW_COMMAND(cdev, db_show_cdev)
1512 {
1513 struct cdev_priv *cdp;
1514 struct cdev *dev;
1515 u_int flags;
1516 char buf[512];
1517
1518 if (!have_addr) {
1519 TAILQ_FOREACH(cdp, &cdevp_list, cdp_list) {
1520 dev = &cdp->cdp_c;
1521 db_printf("%s %p\n", dev->si_name, dev);
1522 if (db_pager_quit)
1523 break;
1524 }
1525 return;
1526 }
1527
1528 dev = (struct cdev *)addr;
1529 cdp = cdev2priv(dev);
1530 db_printf("dev %s ref %d use %ld thr %ld inuse %u fdpriv %p\n",
1531 dev->si_name, dev->si_refcount, dev->si_usecount,
1532 dev->si_threadcount, cdp->cdp_inuse, cdp->cdp_fdpriv.lh_first);
1533 db_printf("devsw %p si_drv0 %d si_drv1 %p si_drv2 %p\n",
1534 dev->si_devsw, dev->si_drv0, dev->si_drv1, dev->si_drv2);
1535 flags = dev->si_flags;
1536 #define SI_FLAG(flag) do { \
1537 if (flags & (flag)) { \
1538 if (buf[0] != '\0') \
1539 strlcat(buf, ", ", sizeof(buf)); \
1540 strlcat(buf, (#flag) + 3, sizeof(buf)); \
1541 flags &= ~(flag); \
1542 } \
1543 } while (0)
1544 buf[0] = '\0';
1545 SI_FLAG(SI_ETERNAL);
1546 SI_FLAG(SI_ALIAS);
1547 SI_FLAG(SI_NAMED);
1548 SI_FLAG(SI_CHILD);
1549 SI_FLAG(SI_DUMPDEV);
1550 SI_FLAG(SI_CLONELIST);
1551 db_printf("si_flags %s\n", buf);
1552
1553 flags = cdp->cdp_flags;
1554 #define CDP_FLAG(flag) do { \
1555 if (flags & (flag)) { \
1556 if (buf[0] != '\0') \
1557 strlcat(buf, ", ", sizeof(buf)); \
1558 strlcat(buf, (#flag) + 4, sizeof(buf)); \
1559 flags &= ~(flag); \
1560 } \
1561 } while (0)
1562 buf[0] = '\0';
1563 CDP_FLAG(CDP_ACTIVE);
1564 CDP_FLAG(CDP_SCHED_DTR);
1565 db_printf("cdp_flags %s\n", buf);
1566 }
1567 #endif
Cache object: 5bf8d1d5f09825fd6ae41716d1f27f83
|