The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_conf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: ea8a9ca57c84c7dff6b7d780d8ffe3af


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.