USG_PG3/usr/source/opsys/errlog.c
#include "../head/param.h"
#include "../head/systm.h"
#include "../head/user.h"
#include "../head/userx.h"
#include "../head/buf.h"
#include "../head/conf.h"
#include "../head/ipcomm.h"
#include "../head/proc.h"
#include "../head/reg.h"
#include "../head/elog.h"
#define ESTART 1
#define EEND 0
#define SSR3 0172516 /* Memory Management Register 3 */
struct msgqhdr *logqp; /* message queue header of logger */
struct msghdr *lasterr;
struct errtab *errtabs[]; /* pointers to device errtabs */
int mmemwant, msgcore[]; /* interface to messages */
/*
* Error logging system call
* Activates and terminates error logging after ensuring
* that all the prerequisites are met.
*/
serrlog()
{
register struct msgqhdr *qp;
register struct msghdr *mp;
register struct estart *esp;
if(!suser())
return;
if((qp = u.u_msgqhdr) == NULL) {
u.u_error = ENOALOC;
return;
}
switch(u.u_arg[0]) {
case ESTART:
if(logqp != NULL) {
if(qp != logqp)
u.u_error = EBUSY;
return;
}
while((mp = msgsetup(sizeof(*esp))) == NULL) {
mmemwant++;
sleep(msgcore, PMSG-1); /* grab space first */
}
esp = &mp[1];
esp->es_cpu = cputype;
if(cputype == 40)
esp->es_mmr3 = 0;
else
esp->es_mmr3 = SSR3->integ;
esp->es_nbdev = nblkdev;
esp->es_ncdev = nchrdev;
clrstat(&esp->es_conf);
logqp = qp; /* starts logging */
logmsg(mp, E_GO);
return;
case EEND:
if(qp != logqp)
u.u_error = EFUNC;
else
termlog();
return;
}
u.u_error = EINVAL;
}
/*
* When error logging is started, clrstat examines all the
* device errtabs. It clears all the IO statistics for
* any devices that keeps such records. An additional
* responsibility is to fill in the system configuration portion
* of the error log startup record.
*/
clrstat(cp)
int *cp;
{
register struct errtab **ep;
register int c, *p;
struct iostat ios[0];
cp->e_bconf = 0;
cp->e_cconf = 0;
for(ep = errtabs; *ep; ep++) {
c = (1<<(*ep)->e_devnum.d_major);
switch((*ep)->e_devtyp&E_TYPE) {
case E_BLK:
cp->e_bconf =| c;
break;
case E_CHR:
cp->e_cconf =| c;
}
if((p = (*ep)->e_iostat) != NULL) {
c = (sizeof(ios[0])/2)*((*ep)->e_nunit);
do
*p++ = 0;
while(--c);
}
}
}
/*
* Whenever the system's concept of the time of day is
* changed, an error log entry showing the old and the new
* time iw written by logtchg.
*/
logtchg()
{
register struct msghdr *mp;
struct etchg etp[0];
if(logqp) {
if((mp = msgsetup(sizeof(etp[0]))) != NULL) {
(&mp[1])->e_ntime.hiword = u.u_ar0[R0];
(&mp[1])->e_ntime.loword = u.u_ar0[R1];
logmsg(mp, E_TCHG);
}
}
}
/*
* Sends error message type "type" to the error logging process.
* Time stamps all such messages.
*/
logmsg(mp, type)
register struct msghdr *mp;
{
mp->mq_sender = 0;
mp->mq_type = E_NOACK; /* no ack on message */
(&mp[1])->e_type = type;
(&mp[1])->e_ctime = time;
msgsend(logqp, mp);
}
/*
* Log an actual error for the device whose errtab is pointed to
* by "ep". The "sclass" argument allows the driver to
* attach a suffix to the error log entry type.
*/
logerr(ep, sclass)
register struct errtab *ep;
{
if(ep->e_emsg != NULL) {
logmsg(ep->e_emsg, (ep->e_devtyp&E_TYPE)|sclass);
ep->e_emsg = NULL;
}
}
/*
* Perform the actual work of terminating error logging.
* Any pending error messages and a stop message are sent
* to the logger.
*/
termlog()
{
register struct errtab **ep;
register int *ip;
struct eend eep[0];
spl6(); /* ensure no one sneaks in */
for(ep = errtabs; *ep; ep++) {
if((*ep)->e_emsg != NULL)
logerr(*ep, E_EARLY);
}
if((ip = msgsetup(sizeof(eep[0]))) != NULL)
logmsg(ip, E_STOP);
logqp = NULL; /* stops logging */
spl0();
}
/*
* Format a block device error record
*/
fmtblk(ep, devloc, nregs, bp)
int *devloc;
register struct errtab *ep;
register struct buf *bp;
{
register struct eblock *ebp;
struct msghdr *mp;
struct iostat ios[0];
if(logqp == NULL)
return;
if((mp = ep->e_emsg) != NULL) {
(&mp[1])->e_rtry++;
return;
}
if(cputype != 70 && ep->e_devtyp&E_RH70)
nregs =- 2; /* no bae or cs3 on non 70s */
if((mp = msgsetup(sizeof(*ebp)+(nregs<<1))) == NULL) {
ep->e_aunit->io_unlog++;
return;
}
ebp = &mp[1];
ebp->e_dev = ep->e_devnum; /* "true" major + minor */
bcopy(ep->e_aunit, &ebp->e_stat, sizeof(ios[0])/2);
ebp->e_bacty = blkacty;
ebp->e_cacty = chracty;
ebp->e_rtry = 0;
ebp->e_nreg = nregs;
ebp->e_rloc = devloc;
bcopy(devloc, &ebp[1], nregs);
ebp->e_dev.d_minor = bp->b_dev.d_minor;
ebp->eb_bflg = bp->b_flags;
ebp->eb_wcnt = bp->b_wcount;
ebp->eb_maddr.hiword = bp->b_xmem;
ebp->eb_maddr.loword = bp->b_addr;
ebp->eb_bno = bp->b_blkno;
ep->e_emsg = mp;
lasterr = mp;
}