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/subr_log.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 /*      $NetBSD: subr_log.c,v 1.33 2003/09/22 12:59:57 christos Exp $   */
    2 
    3 /*
    4  * Copyright (c) 1982, 1986, 1993
    5  *      The Regents of the University of California.  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  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)subr_log.c  8.3 (Berkeley) 2/14/95
   32  */
   33 
   34 /*
   35  * Error log buffer for kernel printf's.
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: subr_log.c,v 1.33 2003/09/22 12:59:57 christos Exp $");
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/proc.h>
   44 #include <sys/vnode.h>
   45 #include <sys/ioctl.h>
   46 #include <sys/msgbuf.h>
   47 #include <sys/file.h>
   48 #include <sys/signalvar.h>
   49 #include <sys/syslog.h>
   50 #include <sys/conf.h>
   51 #include <sys/select.h>
   52 #include <sys/poll.h>
   53 
   54 #define LOG_RDPRI       (PZERO + 1)
   55 
   56 #define LOG_ASYNC       0x04
   57 #define LOG_RDWAIT      0x08
   58 
   59 struct logsoftc {
   60         int     sc_state;               /* see above for possibilities */
   61         struct  selinfo sc_selp;        /* process waiting on select call */
   62         pid_t   sc_pgid;                /* process/group for async I/O */
   63 } logsoftc;
   64 
   65 int     log_open;                       /* also used in log() */
   66 int     msgbufmapped;                   /* is the message buffer mapped */
   67 int     msgbufenabled;                  /* is logging to the buffer enabled */
   68 struct  kern_msgbuf *msgbufp;           /* the mapped buffer, itself. */
   69 
   70 dev_type_open(logopen);
   71 dev_type_close(logclose);
   72 dev_type_read(logread);
   73 dev_type_ioctl(logioctl);
   74 dev_type_poll(logpoll);
   75 dev_type_kqfilter(logkqfilter);
   76 
   77 const struct cdevsw log_cdevsw = {
   78         logopen, logclose, logread, nowrite, logioctl,
   79         nostop, notty, logpoll, nommap, logkqfilter,
   80 };
   81 
   82 void
   83 initmsgbuf(buf, bufsize)
   84         caddr_t buf;
   85         size_t bufsize;
   86 {
   87         struct kern_msgbuf *mbp;
   88         long new_bufs;
   89 
   90         /* Sanity-check the given size. */
   91         if (bufsize < sizeof(struct kern_msgbuf))
   92                 return;
   93 
   94         mbp = msgbufp = (struct kern_msgbuf *)buf;
   95 
   96         new_bufs = bufsize - offsetof(struct kern_msgbuf, msg_bufc);
   97         if ((mbp->msg_magic != MSG_MAGIC) || (mbp->msg_bufs != new_bufs) ||
   98             (mbp->msg_bufr < 0) || (mbp->msg_bufr >= mbp->msg_bufs) ||
   99             (mbp->msg_bufx < 0) || (mbp->msg_bufx >= mbp->msg_bufs)) {
  100                 /*
  101                  * If the buffer magic number is wrong, has changed
  102                  * size (which shouldn't happen often), or is
  103                  * internally inconsistent, initialize it.
  104                  */
  105 
  106                 memset(buf, 0, bufsize);
  107                 mbp->msg_magic = MSG_MAGIC;
  108                 mbp->msg_bufs = new_bufs;
  109         }
  110 
  111         /* mark it as ready for use. */
  112         msgbufmapped = msgbufenabled = 1;
  113 }
  114 
  115 /*ARGSUSED*/
  116 int
  117 logopen(dev, flags, mode, p)
  118         dev_t dev;
  119         int flags, mode;
  120         struct proc *p;
  121 {
  122         struct kern_msgbuf *mbp = msgbufp;
  123 
  124         if (log_open)
  125                 return (EBUSY);
  126         log_open = 1;
  127         logsoftc.sc_pgid = p->p_pid;            /* signal process only */
  128         /*
  129          * The message buffer is initialized during system configuration.
  130          * If it's been clobbered, note that and return an error.  (This
  131          * allows a user to potentially read the buffer via /dev/kmem,
  132          * and try to figure out what clobbered it.
  133          */
  134         if (mbp->msg_magic != MSG_MAGIC) {
  135                 msgbufenabled = 0;
  136                 return (ENXIO);
  137         }
  138 
  139         return (0);
  140 }
  141 
  142 /*ARGSUSED*/
  143 int
  144 logclose(dev, flag, mode, p)
  145         dev_t dev;
  146         int flag, mode;
  147         struct proc *p;
  148 {
  149 
  150         log_open = 0;
  151         logsoftc.sc_state = 0;
  152         return (0);
  153 }
  154 
  155 /*ARGSUSED*/
  156 int
  157 logread(dev, uio, flag)
  158         dev_t dev;
  159         struct uio *uio;
  160         int flag;
  161 {
  162         struct kern_msgbuf *mbp = msgbufp;
  163         long l;
  164         int s;
  165         int error = 0;
  166 
  167         s = splhigh();
  168         while (mbp->msg_bufr == mbp->msg_bufx) {
  169                 if (flag & IO_NDELAY) {
  170                         splx(s);
  171                         return (EWOULDBLOCK);
  172                 }
  173                 logsoftc.sc_state |= LOG_RDWAIT;
  174                 error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH,
  175                                "klog", 0);
  176                 if (error) {
  177                         splx(s);
  178                         return (error);
  179                 }
  180         }
  181         splx(s);
  182         logsoftc.sc_state &= ~LOG_RDWAIT;
  183 
  184         while (uio->uio_resid > 0) {
  185                 l = mbp->msg_bufx - mbp->msg_bufr;
  186                 if (l < 0)
  187                         l = mbp->msg_bufs - mbp->msg_bufr;
  188                 l = min(l, uio->uio_resid);
  189                 if (l == 0)
  190                         break;
  191                 error = uiomove((caddr_t)&mbp->msg_bufc[mbp->msg_bufr],
  192                         (int)l, uio);
  193                 if (error)
  194                         break;
  195                 mbp->msg_bufr += l;
  196                 if (mbp->msg_bufr < 0 || mbp->msg_bufr >= mbp->msg_bufs)
  197                         mbp->msg_bufr = 0;
  198         }
  199         return (error);
  200 }
  201 
  202 /*ARGSUSED*/
  203 int
  204 logpoll(dev, events, p)
  205         dev_t dev;
  206         int events;
  207         struct proc *p;
  208 {
  209         int revents = 0;
  210         int s = splhigh();
  211 
  212         if (events & (POLLIN | POLLRDNORM)) {
  213                 if (msgbufp->msg_bufr != msgbufp->msg_bufx)
  214                         revents |= events & (POLLIN | POLLRDNORM);
  215                 else
  216                         selrecord(p, &logsoftc.sc_selp);
  217         }
  218 
  219         splx(s);
  220         return (revents);
  221 }
  222 
  223 static void
  224 filt_logrdetach(struct knote *kn)
  225 {
  226         int s;
  227 
  228         s = splhigh();
  229         SLIST_REMOVE(&logsoftc.sc_selp.sel_klist, kn, knote, kn_selnext);
  230         splx(s);
  231 }
  232 
  233 static int
  234 filt_logread(struct knote *kn, long hint)
  235 {
  236 
  237         if (msgbufp->msg_bufr == msgbufp->msg_bufx)
  238                 return (0);
  239 
  240         if (msgbufp->msg_bufr < msgbufp->msg_bufx)
  241                 kn->kn_data = msgbufp->msg_bufx - msgbufp->msg_bufr;
  242         else
  243                 kn->kn_data = (msgbufp->msg_bufs - msgbufp->msg_bufr) +
  244                     msgbufp->msg_bufx;
  245 
  246         return (1);
  247 }
  248 
  249 static const struct filterops logread_filtops =
  250         { 1, NULL, filt_logrdetach, filt_logread };
  251 
  252 int
  253 logkqfilter(dev_t dev, struct knote *kn)
  254 {
  255         struct klist *klist;
  256         int s;
  257 
  258         switch (kn->kn_filter) {
  259         case EVFILT_READ:
  260                 klist = &logsoftc.sc_selp.sel_klist;
  261                 kn->kn_fop = &logread_filtops;
  262                 break;
  263 
  264         default:
  265                 return (1);
  266         }
  267 
  268         kn->kn_hook = NULL;
  269 
  270         s = splhigh();
  271         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
  272         splx(s);
  273 
  274         return (0);
  275 }
  276 
  277 void
  278 logwakeup()
  279 {
  280         if (!log_open)
  281                 return;
  282         selnotify(&logsoftc.sc_selp, 0);
  283         if (logsoftc.sc_state & LOG_ASYNC)
  284                 fownsignal(logsoftc.sc_pgid, SIGIO, 0, 0, NULL);
  285         if (logsoftc.sc_state & LOG_RDWAIT) {
  286                 wakeup((caddr_t)msgbufp);
  287                 logsoftc.sc_state &= ~LOG_RDWAIT;
  288         }
  289 }
  290 
  291 /*ARGSUSED*/
  292 int
  293 logioctl(dev, com, data, flag, p)
  294         dev_t dev;
  295         u_long com;
  296         caddr_t data;
  297         int flag;
  298         struct proc *p;
  299 {
  300         long l;
  301         int s;
  302 
  303         switch (com) {
  304 
  305         /* return number of characters immediately available */
  306         case FIONREAD:
  307                 s = splhigh();
  308                 l = msgbufp->msg_bufx - msgbufp->msg_bufr;
  309                 splx(s);
  310                 if (l < 0)
  311                         l += msgbufp->msg_bufs;
  312                 *(int *)data = l;
  313                 break;
  314 
  315         case FIONBIO:
  316                 break;
  317 
  318         case FIOASYNC:
  319                 if (*(int *)data)
  320                         logsoftc.sc_state |= LOG_ASYNC;
  321                 else
  322                         logsoftc.sc_state &= ~LOG_ASYNC;
  323                 break;
  324 
  325         case TIOCSPGRP:
  326         case FIOSETOWN:
  327                 return fsetown(p, &logsoftc.sc_pgid, com, data);
  328 
  329         case TIOCGPGRP:
  330         case FIOGETOWN:
  331                 return fgetown(p, logsoftc.sc_pgid, com, data);
  332 
  333         default:
  334                 return (EPASSTHROUGH);
  335         }
  336         return (0);
  337 }

Cache object: 1db28c20ecf5076ec4563ca8654ee9f0


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