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_devctl.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
    3  *
    4  * Copyright (c) 2002-2020 M. Warner Losh <imp@FreeBSD.org>
    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 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include "opt_bus.h"
   32 #include "opt_ddb.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/conf.h>
   36 #include <sys/eventhandler.h>
   37 #include <sys/filio.h>
   38 #include <sys/lock.h>
   39 #include <sys/kernel.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mutex.h>
   42 #include <sys/poll.h>
   43 #include <sys/priv.h>
   44 #include <sys/proc.h>
   45 #include <sys/condvar.h>
   46 #include <sys/queue.h>
   47 #include <machine/bus.h>
   48 #include <sys/sbuf.h>
   49 #include <sys/selinfo.h>
   50 #include <sys/smp.h>
   51 #include <sys/sysctl.h>
   52 #include <sys/systm.h>
   53 #include <sys/uio.h>
   54 #include <sys/bus.h>
   55 
   56 #include <machine/cpu.h>
   57 #include <machine/stdarg.h>
   58 
   59 #include <vm/uma.h>
   60 #include <vm/vm.h>
   61 
   62 #include <ddb/ddb.h>
   63 
   64 STAILQ_HEAD(devq, dev_event_info);
   65 
   66 static struct dev_softc {
   67         int             inuse;
   68         int             nonblock;
   69         int             queued;
   70         int             async;
   71         struct mtx      mtx;
   72         struct cv       cv;
   73         struct selinfo  sel;
   74         struct devq     devq;
   75         struct sigio    *sigio;
   76         uma_zone_t      zone;
   77 } devsoftc;
   78 
   79 /*
   80  * This design allows only one reader for /dev/devctl.  This is not desirable
   81  * in the long run, but will get a lot of hair out of this implementation.
   82  * Maybe we should make this device a clonable device.
   83  *
   84  * Also note: we specifically do not attach a device to the device_t tree
   85  * to avoid potential chicken and egg problems.  One could argue that all
   86  * of this belongs to the root node.
   87  */
   88 
   89 #define DEVCTL_DEFAULT_QUEUE_LEN 1000
   90 static int sysctl_devctl_queue(SYSCTL_HANDLER_ARGS);
   91 static int devctl_queue_length = DEVCTL_DEFAULT_QUEUE_LEN;
   92 SYSCTL_PROC(_hw_bus, OID_AUTO, devctl_queue, CTLTYPE_INT | CTLFLAG_RWTUN |
   93     CTLFLAG_MPSAFE, NULL, 0, sysctl_devctl_queue, "I", "devctl queue length");
   94 
   95 static void devctl_attach_handler(void *arg __unused, device_t dev);
   96 static void devctl_detach_handler(void *arg __unused, device_t dev,
   97     enum evhdev_detach state);
   98 static void devctl_nomatch_handler(void *arg __unused, device_t dev);
   99 
  100 static d_open_t         devopen;
  101 static d_close_t        devclose;
  102 static d_read_t         devread;
  103 static d_ioctl_t        devioctl;
  104 static d_poll_t         devpoll;
  105 static d_kqfilter_t     devkqfilter;
  106 
  107 #define DEVCTL_BUFFER (1024 - sizeof(void *))
  108 struct dev_event_info {
  109         STAILQ_ENTRY(dev_event_info) dei_link;
  110         char dei_data[DEVCTL_BUFFER];
  111 };
  112 
  113 
  114 static struct cdevsw dev_cdevsw = {
  115         .d_version =    D_VERSION,
  116         .d_open =       devopen,
  117         .d_close =      devclose,
  118         .d_read =       devread,
  119         .d_ioctl =      devioctl,
  120         .d_poll =       devpoll,
  121         .d_kqfilter =   devkqfilter,
  122         .d_name =       "devctl",
  123 };
  124 
  125 static void     filt_devctl_detach(struct knote *kn);
  126 static int      filt_devctl_read(struct knote *kn, long hint);
  127 
  128 static struct filterops devctl_rfiltops = {
  129         .f_isfd = 1,
  130         .f_detach = filt_devctl_detach,
  131         .f_event = filt_devctl_read,
  132 };
  133 
  134 static struct cdev *devctl_dev;
  135 static void devaddq(const char *type, const char *what, device_t dev);
  136 
  137 static void
  138 devctl_init(void)
  139 {
  140         int reserve;
  141         uma_zone_t z;
  142 
  143         devctl_dev = make_dev_credf(MAKEDEV_ETERNAL, &dev_cdevsw, 0, NULL,
  144             UID_ROOT, GID_WHEEL, 0600, "devctl");
  145         mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF);
  146         cv_init(&devsoftc.cv, "dev cv");
  147         STAILQ_INIT(&devsoftc.devq);
  148         knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx);
  149         if (devctl_queue_length > 0) {
  150                 /*
  151                  * Allocate a zone for the messages. Preallocate 2% of these for
  152                  * a reserve. Allow only devctl_queue_length slabs to cap memory
  153                  * usage.  The reserve usually allows coverage of surges of
  154                  * events during memory shortages. Normally we won't have to
  155                  * re-use events from the queue, but will in extreme shortages.
  156                  */
  157                 z = devsoftc.zone = uma_zcreate("DEVCTL",
  158                     sizeof(struct dev_event_info), NULL, NULL, NULL, NULL,
  159                     UMA_ALIGN_PTR, 0);
  160                 reserve = max(devctl_queue_length / 50, 100);   /* 2% reserve */
  161                 uma_zone_set_max(z, devctl_queue_length);
  162                 uma_zone_set_maxcache(z, 0);
  163                 uma_zone_reserve(z, reserve);
  164                 uma_prealloc(z, reserve);
  165         }
  166         EVENTHANDLER_REGISTER(device_attach, devctl_attach_handler,
  167             NULL, EVENTHANDLER_PRI_LAST);
  168         EVENTHANDLER_REGISTER(device_detach, devctl_detach_handler,
  169             NULL, EVENTHANDLER_PRI_LAST);
  170         EVENTHANDLER_REGISTER(device_nomatch, devctl_nomatch_handler,
  171             NULL, EVENTHANDLER_PRI_LAST);
  172 }
  173 SYSINIT(devctl_init, SI_SUB_DRIVERS, SI_ORDER_SECOND, devctl_init, NULL);
  174 
  175 /*
  176  * A device was added to the tree.  We are called just after it successfully
  177  * attaches (that is, probe and attach success for this device).  No call
  178  * is made if a device is merely parented into the tree.  See devnomatch
  179  * if probe fails.  If attach fails, no notification is sent (but maybe
  180  * we should have a different message for this).
  181  */
  182 static void
  183 devctl_attach_handler(void *arg __unused, device_t dev)
  184 {
  185         devaddq("+", device_get_nameunit(dev), dev);
  186 }
  187 
  188 /*
  189  * A device was removed from the tree.  We are called just before this
  190  * happens.
  191  */
  192 static void
  193 devctl_detach_handler(void *arg __unused, device_t dev, enum evhdev_detach state)
  194 {
  195         if (state == EVHDEV_DETACH_COMPLETE)
  196                 devaddq("-", device_get_nameunit(dev), dev);
  197 }
  198 
  199 /*
  200  * Called when there's no match for this device.  This is only called
  201  * the first time that no match happens, so we don't keep getting this
  202  * message.  Should that prove to be undesirable, we can change it.
  203  * This is called when all drivers that can attach to a given bus
  204  * decline to accept this device.  Other errors may not be detected.
  205  */
  206 static void
  207 devctl_nomatch_handler(void *arg __unused, device_t dev)
  208 {
  209         devaddq("?", "", dev);
  210 }
  211 
  212 static int
  213 devopen(struct cdev *dev, int oflags, int devtype, struct thread *td)
  214 {
  215         mtx_lock(&devsoftc.mtx);
  216         if (devsoftc.inuse) {
  217                 mtx_unlock(&devsoftc.mtx);
  218                 return (EBUSY);
  219         }
  220         /* move to init */
  221         devsoftc.inuse = 1;
  222         mtx_unlock(&devsoftc.mtx);
  223         return (0);
  224 }
  225 
  226 static int
  227 devclose(struct cdev *dev, int fflag, int devtype, struct thread *td)
  228 {
  229         mtx_lock(&devsoftc.mtx);
  230         devsoftc.inuse = 0;
  231         devsoftc.nonblock = 0;
  232         devsoftc.async = 0;
  233         cv_broadcast(&devsoftc.cv);
  234         funsetown(&devsoftc.sigio);
  235         mtx_unlock(&devsoftc.mtx);
  236         return (0);
  237 }
  238 
  239 /*
  240  * The read channel for this device is used to report changes to
  241  * userland in realtime.  We are required to free the data as well as
  242  * the n1 object because we allocate them separately.  Also note that
  243  * we return one record at a time.  If you try to read this device a
  244  * character at a time, you will lose the rest of the data.  Listening
  245  * programs are expected to cope.
  246  */
  247 static int
  248 devread(struct cdev *dev, struct uio *uio, int ioflag)
  249 {
  250         struct dev_event_info *n1;
  251         int rv;
  252 
  253         mtx_lock(&devsoftc.mtx);
  254         while (STAILQ_EMPTY(&devsoftc.devq)) {
  255                 if (devsoftc.nonblock) {
  256                         mtx_unlock(&devsoftc.mtx);
  257                         return (EAGAIN);
  258                 }
  259                 rv = cv_wait_sig(&devsoftc.cv, &devsoftc.mtx);
  260                 if (rv) {
  261                         /*
  262                          * Need to translate ERESTART to EINTR here? -- jake
  263                          */
  264                         mtx_unlock(&devsoftc.mtx);
  265                         return (rv);
  266                 }
  267         }
  268         n1 = STAILQ_FIRST(&devsoftc.devq);
  269         STAILQ_REMOVE_HEAD(&devsoftc.devq, dei_link);
  270         devsoftc.queued--;
  271         mtx_unlock(&devsoftc.mtx);
  272         rv = uiomove(n1->dei_data, strlen(n1->dei_data), uio);
  273         uma_zfree(devsoftc.zone, n1);
  274         return (rv);
  275 }
  276 
  277 static  int
  278 devioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
  279 {
  280         switch (cmd) {
  281         case FIONBIO:
  282                 if (*(int*)data)
  283                         devsoftc.nonblock = 1;
  284                 else
  285                         devsoftc.nonblock = 0;
  286                 return (0);
  287         case FIOASYNC:
  288                 if (*(int*)data)
  289                         devsoftc.async = 1;
  290                 else
  291                         devsoftc.async = 0;
  292                 return (0);
  293         case FIOSETOWN:
  294                 return fsetown(*(int *)data, &devsoftc.sigio);
  295         case FIOGETOWN:
  296                 *(int *)data = fgetown(&devsoftc.sigio);
  297                 return (0);
  298 
  299                 /* (un)Support for other fcntl() calls. */
  300         case FIOCLEX:
  301         case FIONCLEX:
  302         case FIONREAD:
  303         default:
  304                 break;
  305         }
  306         return (ENOTTY);
  307 }
  308 
  309 static  int
  310 devpoll(struct cdev *dev, int events, struct thread *td)
  311 {
  312         int     revents = 0;
  313 
  314         mtx_lock(&devsoftc.mtx);
  315         if (events & (POLLIN | POLLRDNORM)) {
  316                 if (!STAILQ_EMPTY(&devsoftc.devq))
  317                         revents = events & (POLLIN | POLLRDNORM);
  318                 else
  319                         selrecord(td, &devsoftc.sel);
  320         }
  321         mtx_unlock(&devsoftc.mtx);
  322 
  323         return (revents);
  324 }
  325 
  326 static int
  327 devkqfilter(struct cdev *dev, struct knote *kn)
  328 {
  329         int error;
  330 
  331         if (kn->kn_filter == EVFILT_READ) {
  332                 kn->kn_fop = &devctl_rfiltops;
  333                 knlist_add(&devsoftc.sel.si_note, kn, 0);
  334                 error = 0;
  335         } else
  336                 error = EINVAL;
  337         return (error);
  338 }
  339 
  340 static void
  341 filt_devctl_detach(struct knote *kn)
  342 {
  343         knlist_remove(&devsoftc.sel.si_note, kn, 0);
  344 }
  345 
  346 static int
  347 filt_devctl_read(struct knote *kn, long hint)
  348 {
  349         kn->kn_data = devsoftc.queued;
  350         return (kn->kn_data != 0);
  351 }
  352 
  353 /**
  354  * @brief Return whether the userland process is running
  355  */
  356 bool
  357 devctl_process_running(void)
  358 {
  359         return (devsoftc.inuse == 1);
  360 }
  361 
  362 static struct dev_event_info *
  363 devctl_alloc_dei(void)
  364 {
  365         struct dev_event_info *dei = NULL;
  366 
  367         mtx_lock(&devsoftc.mtx);
  368         if (devctl_queue_length == 0)
  369                 goto out;
  370         dei = uma_zalloc(devsoftc.zone, M_NOWAIT);
  371         if (dei == NULL)
  372                 dei = uma_zalloc(devsoftc.zone, M_NOWAIT | M_USE_RESERVE);
  373         if (dei == NULL) {
  374                 /*
  375                  * Guard against no items in the queue. Normally, this won't
  376                  * happen, but if lots of events happen all at once and there's
  377                  * a chance we're out of allocated space but none have yet been
  378                  * queued when we get here, leaving nothing to steal. This can
  379                  * also happen with error injection. Fail safe by returning
  380                  * NULL in that case..
  381                  */
  382                 if (devsoftc.queued == 0)
  383                         goto out;
  384                 dei = STAILQ_FIRST(&devsoftc.devq);
  385                 STAILQ_REMOVE_HEAD(&devsoftc.devq, dei_link);
  386                 devsoftc.queued--;
  387         }
  388         MPASS(dei != NULL);
  389         *dei->dei_data = '\0';
  390 out:
  391         mtx_unlock(&devsoftc.mtx);
  392         return (dei);
  393 }
  394 
  395 static struct dev_event_info *
  396 devctl_alloc_dei_sb(struct sbuf *sb)
  397 {
  398         struct dev_event_info *dei;
  399 
  400         dei = devctl_alloc_dei();
  401         if (dei != NULL)
  402                 sbuf_new(sb, dei->dei_data, sizeof(dei->dei_data), SBUF_FIXEDLEN);
  403         return (dei);
  404 }
  405 
  406 static void
  407 devctl_free_dei(struct dev_event_info *dei)
  408 {
  409         uma_zfree(devsoftc.zone, dei);
  410 }
  411 
  412 static void
  413 devctl_queue(struct dev_event_info *dei)
  414 {
  415         mtx_lock(&devsoftc.mtx);
  416         STAILQ_INSERT_TAIL(&devsoftc.devq, dei, dei_link);
  417         devsoftc.queued++;
  418         cv_broadcast(&devsoftc.cv);
  419         KNOTE_LOCKED(&devsoftc.sel.si_note, 0);
  420         mtx_unlock(&devsoftc.mtx);
  421         selwakeup(&devsoftc.sel);
  422         if (devsoftc.async && devsoftc.sigio != NULL)
  423                 pgsigio(&devsoftc.sigio, SIGIO, 0);
  424 }
  425 
  426 /**
  427  * @brief Send a 'notification' to userland, using standard ways
  428  */
  429 void
  430 devctl_notify(const char *system, const char *subsystem, const char *type,
  431     const char *data)
  432 {
  433         struct dev_event_info *dei;
  434         struct sbuf sb;
  435 
  436         if (system == NULL || subsystem == NULL || type == NULL)
  437                 return;
  438         dei = devctl_alloc_dei_sb(&sb);
  439         if (dei == NULL)
  440                 return;
  441         sbuf_cpy(&sb, "!system=");
  442         sbuf_cat(&sb, system);
  443         sbuf_cat(&sb, " subsystem=");
  444         sbuf_cat(&sb, subsystem);
  445         sbuf_cat(&sb, " type=");
  446         sbuf_cat(&sb, type);
  447         if (data != NULL) {
  448                 sbuf_putc(&sb, ' ');
  449                 sbuf_cat(&sb, data);
  450         }
  451         sbuf_putc(&sb, '\n');
  452         if (sbuf_finish(&sb) != 0)
  453                 devctl_free_dei(dei);   /* overflow -> drop it */
  454         else
  455                 devctl_queue(dei);
  456 }
  457 
  458 /*
  459  * Common routine that tries to make sending messages as easy as possible.
  460  * We allocate memory for the data, copy strings into that, but do not
  461  * free it unless there's an error.  The dequeue part of the driver should
  462  * free the data.  We don't send data when the device is disabled.  We do
  463  * send data, even when we have no listeners, because we wish to avoid
  464  * races relating to startup and restart of listening applications.
  465  *
  466  * devaddq is designed to string together the type of event, with the
  467  * object of that event, plus the plug and play info and location info
  468  * for that event.  This is likely most useful for devices, but less
  469  * useful for other consumers of this interface.  Those should use
  470  * the devctl_notify() interface instead.
  471  *
  472  * Output:
  473  *      ${type}${what} at $(location dev) $(pnp-info dev) on $(parent dev)
  474  */
  475 static void
  476 devaddq(const char *type, const char *what, device_t dev)
  477 {
  478         struct dev_event_info *dei;
  479         const char *parstr;
  480         struct sbuf sb;
  481 
  482         dei = devctl_alloc_dei_sb(&sb);
  483         if (dei == NULL)
  484                 return;
  485         sbuf_cpy(&sb, type);
  486         sbuf_cat(&sb, what);
  487         sbuf_cat(&sb, " at ");
  488 
  489         /* Add in the location */
  490         bus_child_location(dev, &sb);
  491         sbuf_putc(&sb, ' ');
  492 
  493         /* Add in pnpinfo */
  494         bus_child_pnpinfo(dev, &sb);
  495 
  496         /* Get the parent of this device, or / if high enough in the tree. */
  497         if (device_get_parent(dev) == NULL)
  498                 parstr = ".";   /* Or '/' ? */
  499         else
  500                 parstr = device_get_nameunit(device_get_parent(dev));
  501         sbuf_cat(&sb, " on ");
  502         sbuf_cat(&sb, parstr);
  503         sbuf_putc(&sb, '\n');
  504         if (sbuf_finish(&sb) != 0)
  505                 goto bad;
  506         devctl_queue(dei);
  507         return;
  508 bad:
  509         devctl_free_dei(dei);
  510 }
  511 
  512 static int
  513 sysctl_devctl_queue(SYSCTL_HANDLER_ARGS)
  514 {
  515         int q, error;
  516 
  517         q = devctl_queue_length;
  518         error = sysctl_handle_int(oidp, &q, 0, req);
  519         if (error || !req->newptr)
  520                 return (error);
  521         if (q < 0)
  522                 return (EINVAL);
  523 
  524         /*
  525          * When set as a tunable, we've not yet initialized the mutex.
  526          * It is safe to just assign to devctl_queue_length and return
  527          * as we're racing no one. We'll use whatever value set in
  528          * devinit.
  529          */
  530         if (!mtx_initialized(&devsoftc.mtx)) {
  531                 devctl_queue_length = q;
  532                 return (0);
  533         }
  534 
  535         /*
  536          * XXX It's hard to grow or shrink the UMA zone. Only allow
  537          * disabling the queue size for the moment until underlying
  538          * UMA issues can be sorted out.
  539          */
  540         if (q != 0)
  541                 return (EINVAL);
  542         if (q == devctl_queue_length)
  543                 return (0);
  544         mtx_lock(&devsoftc.mtx);
  545         devctl_queue_length = 0;
  546         uma_zdestroy(devsoftc.zone);
  547         devsoftc.zone = 0;
  548         mtx_unlock(&devsoftc.mtx);
  549         return (0);
  550 }
  551 
  552 /**
  553  * @brief safely quotes strings that might have double quotes in them.
  554  *
  555  * The devctl protocol relies on quoted strings having matching quotes.
  556  * This routine quotes any internal quotes so the resulting string
  557  * is safe to pass to snprintf to construct, for example pnp info strings.
  558  *
  559  * @param sb    sbuf to place the characters into
  560  * @param src   Original buffer.
  561  */
  562 void
  563 devctl_safe_quote_sb(struct sbuf *sb, const char *src)
  564 {
  565         while (*src != '\0') {
  566                 if (*src == '"' || *src == '\\')
  567                         sbuf_putc(sb, '\\');
  568                 sbuf_putc(sb, *src++);
  569         }
  570 }

Cache object: 1860036308197561f74f40c8a8e12216


[ 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.