#include "sys/param.h" #include "sys/types.h" #include "sys/sysmacros.h" #include "sys/systm.h" #include "sys/buf.h" #include "sys/conf.h" #include "sys/map.h" #include "sys/utsname.h" #include "sys/elog.h" #include "sys/erec.h" #include "sys/err.h" #include "sys/iobuf.h" #include "sys/var.h" typedef int mem_t; int blkacty; errinit() { register struct err *errp; errp = &err; if(errp->e_nslot) { mapinit(errp->e_map, (errp->e_nslot+3)/2); mfree(errp->e_map, (mem_t)errp->e_nslot, (mem_t)1); } errp->e_org = errp->e_ptrs; errp->e_nxt = errp->e_ptrs; } struct errhdr * geteslot(size) { register ns, *p; register struct errhdr *ep; int n, sps; ns = (size+sizeof(struct errhdr)+sizeof(struct errslot)-1) /sizeof(struct errslot); sps = spl7(); n = malloc(err.e_map, (mem_t)ns); splx(sps); if(n == 0) return(NULL); ep = (struct errhdr *)(&err.e_slot[--n]); ns *= sizeof(struct errslot)/sizeof(int); p = (int *)ep; do { *p++ = 0; } while(--ns); ep->e_len = size + sizeof(struct errhdr); return(++ep); } freeslot(ep) register struct errhdr *ep; { register ns, sps; ns = (ep->e_len+sizeof(struct errslot)-1)/sizeof(struct errslot); sps = spl7(); mfree(err.e_map, (mem_t)ns, (mem_t)((((struct errslot *)ep)-err.e_slot)+1)); splx(sps); } struct errhdr * geterec() { register sps; register struct errhdr *ep; register struct err *errp; errp = &err; sps = spl7(); while(*errp->e_org == NULL) (void) sleep((caddr_t)&errp->e_org,PZERO+1); ep = *errp->e_org; *errp->e_org++ = NULL; if(errp->e_org >= &errp->e_ptrs[errp->e_nslot]) errp->e_org = errp->e_ptrs; splx(sps); return(ep); } puterec(ep, type) register struct errhdr *ep; { register sps; register struct err *errp; errp = &err; (--ep)->e_type = type; ep->e_time = time; sps = spl7(); *errp->e_nxt++ = ep; if(errp->e_nxt >= &errp->e_ptrs[errp->e_nslot]) errp->e_nxt = errp->e_ptrs; splx(sps); wakeup((caddr_t)&errp->e_org); } logstart() { register sps; register struct estart *ep; register struct bdevsw *bdp; register struct err *errp; extern nodev(); errp = &err; sps = spl7(); for(errp->e_org = &errp->e_ptrs[errp->e_nslot-1]; errp->e_org >= errp->e_ptrs; errp->e_org--) if(*errp->e_org != NULL) { freeslot(*errp->e_org); *errp->e_org = NULL; } errp->e_org = errp->e_ptrs; errp->e_nxt = errp->e_ptrs; ep = (struct estart *)geteslot(sizeof(struct estart)); splx(sps); if(ep == NULL) return; ep->e_name = utsname; for(bdp = &bdevsw[bdevcnt-1]; bdp >= bdevsw; bdp--) if(bdp->d_strategy != nodev) ep->e_bconf |= 1 << (&bdevsw[0]-bdp); ep->e_bconf = blkacty; puterec((struct errhdr *)ep, E_GOTS); } logtchg(nt) time_t nt; { register struct etimchg *ep; if((ep = (struct etimchg *)geteslot(sizeof(struct etimchg))) != NULL) { ep->e_ntime = nt; puterec((struct errhdr *)ep,E_TCHG); } } logstray(addr) physadr addr; { register struct estray *ep; if((ep = (struct estray *)geteslot(sizeof(struct estray))) != NULL) { ep->e_saddr = addr; ep->e_sbacty = blkacty; puterec((struct errhdr *)ep,E_STRAY); } } logparity(addr) register paddr_t addr; { register struct eparity *ep; if((ep = (struct eparity *)geteslot(sizeof(struct eparity))) != NULL) { ep->e_parreg = addr; puterec((struct errhdr *)ep,E_PRTY); } } /* * fmtberr() is used by block device drivers to build up a valid * eblock structure to be sent to the error log. * * dp the address of the io queue item. * unit the Physical Device error report field * the Logical Device field is the minor device number * cyl the cylinder number * trk the track number * sector the sector number * regcnt the number of following register structures * regs is the address of an array of structures each of which * contain the elements described in struct deverreg. */ /* VARARGS7 */ fmtberr(dp, unit, cyl, trk, sector, regcnt, regs) register struct iobuf *dp; unsigned unit; unsigned cyl; unsigned trk; unsigned sector; long regcnt; struct deverreg *regs; { register struct eblock *ep; register struct buf *bp; register struct deverreg **dr; register char *str1; register char *pp; register short argc; register short nn; struct br { /* just used to generate addr after eblock */ struct eblock eb; char cregs[1]; }; struct iostat *iosp; extern char *longcopy(); if(dp->io_erec != NULL) { dp->io_erec->e_rtry++; return; } /* count the length of the values and strings */ nn = 0; argc = regcnt; dr = ®s; while (argc--) { nn += sizeof((*dr)->draddr); nn += sizeof((*dr)->drvalue); nn += strlen((*dr)->drname) + 1; /* + null */ nn += strlen((*dr)->drbits) + 1; /* + null */ nn += (nn & 1); /* round to even number of bytes */ dr++; } iosp = dp->io_stp; /* want sizeof eblock to the next long address */ if((ep = (struct eblock *) geteslot(sizeof(struct eblock) + nn)) == NULL) { iosp->io_unlog++; return; } nn = major(dp->b_dev); bp = dp->b_actf; ep->e_dev = makedev(nn,(bp==NULL)?minor(dp->b_dev):minor(bp->b_dev)); ep->e_bacty = blkacty; ep->e_stats.io_ops = iosp->io_ops; ep->e_stats.io_misc = iosp->io_misc; ep->e_stats.io_unlog = iosp->io_unlog; ep->e_pos.unit = unit; ep->e_pos.cyl = cyl; ep->e_pos.trk = trk; ep->e_pos.sector = sector; if(bp != NULL) { ep->e_bflags = (bp->b_flags&B_READ) ? E_READ : E_WRITE; if(bp->b_flags & B_PHYS) ep->e_bflags |= E_PHYS; if(bp->b_flags & B_MAP) ep->e_bflags |= E_MAP; ep->e_bnum = bp->b_blkno; ep->e_bytes = bp->b_bcount; ep->e_memadd = paddr(bp); } else ep->e_bflags = E_NOIO; ep->e_nreg = regcnt; pp = &(((struct br *)ep)->cregs[0]); dr = ®s; while(--regcnt >= 0) { /* copy out the number values */ pp = longcopy((char *)&((*dr)->draddr),pp); pp = longcopy((char *)&((*dr)->drvalue),pp); /* copy out the strings themselves */ str1 = (*dr)->drname; while (*str1) { *pp++ = *str1++; } /* copy the terminating null too */ *pp++ = '\0'; str1 = (*dr)->drbits; while (*str1) { *pp++ = *str1++; } *pp++ = '\0'; dr++; } dp->io_erec = ep; } logberr(dp,error) register struct iobuf *dp; { register struct eblock *ep; if((ep = dp->io_erec) == NULL) return; if(error) ep->e_bflags |= E_ERROR; puterec((struct errhdr *)ep,E_BLK); dp->io_erec = NULL; } /* may not be on long address boundary when copied to b2, avoiding any alignment problems on some machines? */ char * longcopy(b1,b2) register char *b1,*b2; { register int ii; for (ii=0; ii < sizeof(long); ii++) { *b2++ = *b1++; } return(b2); }