# 2.11BSD#431 - /usr/src/sys/sys/subr_log.c

##### Functions

    logclose          X
    loginit           X
    logioctl          X
    logisopen         X
    logopen           X
    logread           X
    logselect         X
    logwakeup         X
    logwrt            X

##### Variables

    Acctopen          X
    msgbuf            X
    nlog              X

##### Macros

    LOG_ASYNC         X
    LOG_OPEN          X
    LOG_RDPRI         X
    LOG_RDWAIT        X
    NLOG              X

##### struct's

    logsoftc          X

       1: /*
       2:  * Copyright (c) 1982, 1986 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  *
       6:  *	@(#)subr_log.c	2.1 (2.11BSD) 1999/4/29
       7:  */
       8:
       9: /*
      10:  * logioctl() had the wrong number of arguments.  Argh!  Apparently this
      11:  * driver was overlooked when 'dev' was added to ioctl entry points.
      12:  *
      13:  * logclose() returned garbage.  this went unnoticed because most programs
      14:  * don't check status when doing a close.
      15:
      16:  * Remove vax ifdefs - this driver is never going back to vaxland.
      17:  *
      18:  * Add support for multiple log devices.  Minor device 0 is the traditional
      19:  * kernel logger (/dev/klog), minor device 1 is reserved for the future device
      20:  * error logging daemon.  Minor device 2 is used by the 'accounting' daemon
      21:  * 'acctd'.
      22:  */
      23:
      24: #define NLOG    3
      25:     int nlog = NLOG;
      26:
      27: #include "param.h"
      28: #include "user.h"
      29: #include "proc.h"
      30: #include "ioctl.h"
      31: #include "msgbuf.h"
      32: #include "file.h"
      33: #include "inode.h"
      34: #include "errno.h"
      35: #include "uio.h"
      36: #include "machine/seg.h"
      37: #include "map.h"
      38:
      39: #define LOG_RDPRI   (PZERO + 1)
      40:
      41: #define LOG_OPEN    0x01
      42: #define LOG_ASYNC   0x04
      43: #define LOG_RDWAIT  0x08
      44:
      45: /*
      46:  * This is an efficiency hack.  This global is provided for exit() to
      47:  * test and avoid the overhead of function calls when accounting is
      48:  * turned off.
      49: */
      50:     int Acctopen;
      51:
      52:     struct  msgbuf  msgbuf[NLOG];
      53:     static  struct logsoftc
      54:         {
      55:         int sc_state;   /* see above for possibilities */
      56:         struct  proc *sc_selp;  /* process waiting on select call */
      57:         int sc_pgid;    /* process/group for async I/O */
      58:         int sc_overrun; /* full buffer count */
      59:         } logsoftc[NLOG];
      60:
      61: /*ARGSUSED*/
      62: logopen(dev, mode)
      63:     dev_t dev;
      64:     int mode;
      65:     {
      66:     register int    unit = minor(dev);
      67:
      68:     if  (unit >= NLOG)
      69:         return(ENODEV);
      70:     if  (logisopen(unit))
      71:         return(EBUSY);
      72:     if  (msgbuf[unit].msg_click == 0)   /* no buffer allocated */
      73:         return(ENOMEM);
      74:     logsoftc[unit].sc_state |= LOG_OPEN;
      75:     if  (unit == logACCT)
      76:         Acctopen = 1;
      77:     logsoftc[unit].sc_pgid = u.u_procp->p_pid;  /* signal process only */
      78:     logsoftc[unit].sc_overrun = 0;
      79:     return(0);
      80:     }
      81:
      82: /*ARGSUSED*/
      83: logclose(dev, flag)
      84:     dev_t   dev;
      85:     int flag;
      86:     {
      87:     register int unit = minor(dev);
      88:
      89:     logsoftc[unit].sc_state = 0;
      90:     if  (unit == logACCT)
      91:         Acctopen = 0;
      92:     return(0);
      93:     }
      94:
      95: /*
      96:  * This is a helper function to keep knowledge of this driver's data
      97:  * structures away from the rest of the kernel.
      98: */
      99: logisopen(unit)
     100:     int unit;
     101:     {
     102:
     103:     if  (logsoftc[unit].sc_state & LOG_OPEN)
     104:         return(1);
     105:     return(0);
     106:     }
     107:
     108: /*ARGSUSED*/
     109: logread(dev, uio, flag)
     110:     dev_t dev;
     111:     struct uio *uio;
     112:     int flag;
     113:     {
     114:     register int l;
     115:     register struct logsoftc *lp;
     116:     register struct msgbuf *mp;
     117:     int s, error = 0;
     118:     char    buf[ctob(2)];
     119:
     120:     l = minor(dev);
     121:     lp = &logsoftc[l];
     122:     mp = &msgbuf[l];
     123:     s = splhigh();
     124:     while   (mp->msg_bufr == mp->msg_bufx)
     125:         {
     126:         if  (flag & IO_NDELAY)
     127:             {
     128:             splx(s);
     129:             return(EWOULDBLOCK);
     130:             }
     131:         lp->sc_state |= LOG_RDWAIT;
     132:         sleep((caddr_t)mp, LOG_RDPRI);
     133:         }
     134:     lp->sc_state &= ~LOG_RDWAIT;
     135:
     136:     while   (uio->uio_resid)
     137:         {
     138:         l = mp->msg_bufx - mp->msg_bufr;
     139: /*
     140:  * If the reader and writer are equal then we have caught up and there
     141:  * is nothing more to transfer.
     142: */
     143:         if  (l == 0)
     144:             break;
     145: /*
     146:  * If the write pointer is behind the reader then only consider as
     147:  * available for now the bytes from the read pointer thru the end of
     148:  * the buffer.
     149: */
     150:         if  (l < 0)
     151:             {
     152:             l = MSG_BSIZE - mp->msg_bufr;
     153: /*
     154:  * If the reader is exactly at the end of the buffer it is
     155:  * time to wrap it around to the beginning and recalculate the
     156:  * amount of data to transfer.
     157: */
     158:             if  (l == 0)
     159:                 {
     160:                 mp->msg_bufr = 0;
     161:                 continue;
     162:                 }
     163:             }
     164:         l = MIN(l, uio->uio_resid);
     165:         l = MIN(l, sizeof buf);
     166:         mapseg5(mp->msg_click, (btoc(MSG_BSIZE) << 8) | RW);
     167:         bcopy(&mp->msg_bufc[mp->msg_bufr], buf, l);
     168:         normalseg5();
     169:         error = uiomove(buf, l, uio);
     170:         if  (error)
     171:             break;
     172:         mp->msg_bufr += l;
     173:         }
     174:     splx(s);
     175:     return(error);
     176:     }
     177:
     178: /*ARGSUSED*/
     179: logselect(dev, rw)
     180:     dev_t dev;
     181:     int rw;
     182:     {
     183:     register int s = splhigh();
     184:     int unit = minor(dev);
     185:
     186:     switch  (rw)
     187:         {
     188:         case    FREAD:
     189:             if  (msgbuf[unit].msg_bufr != msgbuf[unit].msg_bufx)
     190:                 {
     191:                 splx(s);
     192:                 return(1);
     193:                 }
     194:             logsoftc[unit].sc_selp = u.u_procp;
     195:             break;
     196:         }
     197:     splx(s);
     198:     return(0);
     199:     }
     200:
     201: logwakeup(unit)
     202:     int unit;
     203:     {
     204:     register struct proc *p;
     205:     register struct logsoftc *lp;
     206:     register struct msgbuf *mp;
     207:
     208:     if  (!logisopen(unit))
     209:         return;
     210:     lp = &logsoftc[unit];
     211:     mp = &msgbuf[unit];
     212:     if  (lp->sc_selp)
     213:         {
     214:         selwakeup(lp->sc_selp, (long) 0);
     215:         lp->sc_selp = 0;
     216:         }
     217:     if  (lp->sc_state & LOG_ASYNC && (mp->msg_bufx != mp->msg_bufr))
     218:         {
     219:         if  (lp->sc_pgid < 0)
     220:             gsignal(-lp->sc_pgid, SIGIO);
     221:         else if (p = pfind(lp->sc_pgid))
     222:             psignal(p, SIGIO);
     223:         }
     224:     if  (lp->sc_state & LOG_RDWAIT)
     225:         {
     226:         wakeup((caddr_t)mp);
     227:         lp->sc_state &= ~LOG_RDWAIT;
     228:         }
     229: }
     230:
     231: /*ARGSUSED*/
     232: logioctl(dev, com, data, flag)
     233:     dev_t   dev;
     234:     u_int   com;
     235:     caddr_t data;
     236:     int flag;
     237:     {
     238:     long l;
     239:     register int s;
     240:     int unit;
     241:     register struct logsoftc *lp;
     242:     register struct msgbuf *mp;
     243:
     244:     unit = minor(dev);
     245:     lp = &logsoftc[unit];
     246:     mp = &msgbuf[unit];
     247:
     248:     switch  (com)
     249:         {
     250:         case    FIONREAD:
     251:             s = splhigh();
     252:             l = mp->msg_bufx - mp->msg_bufr;
     253:             splx(s);
     254:             if  (l < 0)
     255:                 l += MSG_BSIZE;
     256:             *(off_t *)data = l;
     257:             break;
     258:         case    FIONBIO:
     259:             break;
     260:         case    FIOASYNC:
     261:             if (*(int *)data)
     262:                 lp->sc_state |= LOG_ASYNC;
     263:             else
     264:                 lp->sc_state &= ~LOG_ASYNC;
     265:             break;
     266:         case    TIOCSPGRP:
     267:             lp->sc_pgid = *(int *)data;
     268:             break;
     269:         case    TIOCGPGRP:
     270:             *(int *)data = lp->sc_pgid;
     271:             break;
     272:         default:
     273:             return(-1);
     274:         }
     275:     return(0);
     276:     }
     277:
     278: /*
     279:  * This is inefficient for single character writes.  Alas, changing this
     280:  * to be buffered would affect the networking code's use of printf.
     281: */
     282:
     283: logwrt(buf,len,log)
     284:     char    *buf;
     285:     int len;
     286:     int log;
     287:     {
     288:     segm    s5;
     289:     register struct msgbuf *mp = &msgbuf[log];
     290:     struct  logsoftc *lp = &logsoftc[log];
     291:     register int    infront;
     292:     int  s, n, writer, err = 0;
     293:
     294:     if  (mp->msg_magic != MSG_MAGIC || (len > MSG_BSIZE))
     295:         return(-1);
     296:     saveseg5(s5);
     297: /*
     298:  * Hate to do this but since this can be called from anywhere in the kernel
     299:  * we have to hold off any interrupt service routines so they don't change
     300:  * things.  This looks like a lot of code but it isn't really.
     301: */
     302:     s = splhigh();
     303:     while   (len)
     304:         {
     305: again:      infront = MSG_BSIZE - mp->msg_bufx;
     306:         if  (infront <= 0)
     307:             {
     308:             mp->msg_bufx = 0;
     309:             infront = MSG_BSIZE - mp->msg_bufr;
     310:             }
     311:         n = mp->msg_bufr - mp->msg_bufx;
     312:         if  (n < 0)     /* bufr < bufx */
     313:             writer = (MSG_BSIZE - mp->msg_bufx) + mp->msg_bufr;
     314:         else if (n == 0)
     315:             writer = MSG_BSIZE;
     316:         else
     317:             {
     318:             writer = n;
     319:             infront = n;
     320:             }
     321:         if  (len > writer)
     322:             {
     323: /*
     324:  * won't fit.  the total number of bytes to be written is
     325:  * greater than the number available.  the buffer is full.
     326:  * throw away the old data and keep the current data by resetting
     327:  * the 'writer' pointer to the current 'reader' position.  Bump the
     328:  * overrun counter in case anyone wants to look at it for debugging.
     329: */
     330:             lp->sc_overrun++;
     331:             mp->msg_bufx = mp->msg_bufr;
     332:             goto    again;
     333:             }
     334:         if  (infront > len)
     335:             infront = len;
     336:         mapseg5(mp->msg_click, (btoc(MSG_BSIZE) << 8) | RW);  /* XXX */
     337:         bcopy(buf, &mp->msg_bufc[mp->msg_bufx], infront);
     338:         restorseg5(s5);
     339:         mp->msg_bufx += infront;
     340:         len -= infront;
     341:         buf += infront;
     342:         }
     343: out:    splx(s);
     344:     return(err);
     345:     }
     346:
     347: /*
     348:  * Initialize the log driver.  Called from the system startup code (machdep2.c).
     349:  * All buffers are the same (MSG_BSIZE) size.
     350: */
     351:
     352: loginit()
     353:     {
     354: register struct msgbuf *mp;
     355:
     356:     for (mp = &msgbuf[0]; mp < &msgbuf[NLOG]; mp++)
     357:         {
     358:         mp->msg_click = malloc(coremap,btoc(MSG_BSIZE));
     359:         if  (!mp->msg_click)
     360:             return(-1);
     361:         mp->msg_magic = MSG_MAGIC;
     362:         mp->msg_bufc = SEG5;
     363:         mp->msg_bufx = mp->msg_bufr = 0;
     364:         }
     365:     return(0);
     366:     }

#### Defined functions

logclose defined in line 83; used 2 times

- in /usr/src/sys/pdp/conf.c line 336, 449

loginit defined in line 352; used 1 times

- in /usr/src/sys/pdp/machdep2.c line 227

logioctl defined in line 232; used 2 times

- in /usr/src/sys/pdp/conf.c line 336, 450

logisopen defined in line 99; used 3 times

- in line 70, 208
- in /usr/src/sys/sys/subr_prf.c line 122

logopen defined in line 62; used 2 times

- in /usr/src/sys/pdp/conf.c line 336, 449

logread defined in line 109; used 2 times

- in /usr/src/sys/pdp/conf.c line 336, 449

logselect defined in line 179; used 2 times

- in /usr/src/sys/pdp/conf.c line 336, 450

logwakeup defined in line 201; used 3 times

- in /usr/src/sys/sys/kern_acct.c line 65
- in /usr/src/sys/sys/subr_prf.c line 104, 124

logwrt defined in line 283; used 2 times

- in /usr/src/sys/sys/kern_acct.c line 62
- in /usr/src/sys/sys/subr_prf.c line 333

#### Defined variables

Acctopen defined in line 50; used 3 times

- in line 76, 91
- in /usr/src/sys/sys/kern_exit.c line 77

logsoftc defined in line 59; used 10 times

- in line 74-78(3), 89, 103, 121, 194, 210, 245, 290

msgbuf defined in line 52; used 9 times

- in line 72, 122, 189(2), 211, 246, 289, 356(2)

nlog defined in line 25; never used

#### Defined struct's

logsoftc defined in line 53; used 8 times

- in line 115(2), 205(2), 241(2), 290(2)

#### Defined macros

LOG_ASYNC defined in line 42; used 3 times

- in line 217, 262-264(2)

LOG_OPEN defined in line 41; used 2 times

- in line 74, 103

LOG_RDPRI defined in line 39; used 1 times

- in line 132

LOG_RDWAIT defined in line 43; used 4 times

- in line 131-134(2), 224-227(2)

NLOG defined in line 24; used 5 times

- in line 25, 52, 59, 68, 356

Last modified: 1999-04-30 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1060 |