/* * error logging * * other parts of the system may call logerr to record an error * reading the device recovers the error records */ #include "sys/param.h" #include "sys/conf.h" #include "sys/systm.h" /* just for time */ #include "sys/user.h" #include "sys/buf.h" #include "sys/errlog.h" /* * hackish use of overlays: * if this device isn't configured, * errcnt will be zero, errlog will be 1 item long (so it won't be undefined) * if the device is configured, * errcnt is the number of errlog buffers */ int errcnt; struct errlog errlog[1]; /* 1 or more */ static int errlost; static char erptr, ewptr; int erropen(), errread(), errwrite(); struct cdevsw errcdev = cdinit(erropen, nodev, errread, errwrite, nodev); #define PERROR (PUSER-1) erropen(dev, flag) dev_t dev; int flag; { if (errcnt == 0) u.u_error = ENXIO; } errread(dev) dev_t dev; { register int s; if (u.u_count < sizeof(errlog)) { u.u_error = EINVAL; return; } s = spl7(); while (erptr == ewptr) sleep((caddr_t)errlog, PERROR); splx(s); s = errlog[erptr].e_hdr.e_len + sizeof(struct errhdr); iomove((caddr_t)&errlog[erptr], s, B_READ); if (++erptr >= errcnt) erptr = 0; } /* * mostly for debugging */ errwrite(dev) dev_t dev; { char b[MAXEDATA+20]; register int len; register char *p; if ((len = u.u_count) > sizeof(b)) { u.u_error = EINVAL; return; } iomove(b, len, B_WRITE); if (u.u_error) return; p = b; while (--len >= 0) if (*p++ == '\n') break; p[-1] = 0; if (len < 0) len = 0; logerr(b, 0, p, len, 0); } /* * here to log an error: * dev is the name of the device or circumstance * unit is a unit number, e.g. which disk number broke * data is the stuff to be logged; there are len bytes * data should be something bcopy can copy (maybe not device registers) * `hard' is nonzero if this was a hard error */ logerr(dev, unit, data, len, hard) char *dev; int unit; char *data; int len; int hard; { register struct errlog *ep; register int s, i; register char *p; s = spl7(); if ((i = ewptr + 1) >= errcnt) i = 0; if (i == erptr) { /* buffer full */ splx(s); errlost++; return; } ep = &errlog[ewptr]; ewptr = i; splx(s); ep->e_hdr.e_1magic = E_1MAGIC; ep->e_hdr.e_2magic = E_2MAGIC; len = min(len, MAXEDATA); ep->e_hdr.e_len = len; if (hard) ep->e_hdr.e_len |= E_HARD; ep->e_hdr.e_unit = unit; ep->e_hdr.e_time = time; p = dev; while (*p++) /* should be strlen */ ; bcopy(dev, ep->e_hdr.e_dev, min(p - dev, sizeof(ep->e_hdr.e_dev))); if (len) bcopy(data, ep->e_data, len); wakeup((caddr_t)errlog); }