📄 cw.c
字号:
#include "all.h"#define DEBUG 0#define FIRST SUPER_ADDR#define ADDFREE (100)#define CACHE_ADDR SUPER_ADDR#define MAXAGE 10000#define CDEV(d) (d->cw.c)#define WDEV(d) (d->cw.w)#define RDEV(d) (d->cw.ro)/* cache state */enum{ /* states -- beware these are recorded on the cache */ /* cache worm */ Cnone = 0, /* 0 ? */ Cdirty, /* 1 0 */ Cdump, /* 1 0->1 */ Cread, /* 1 1 */ Cwrite, /* 2 1 */ Cdump1, /* inactive form of dump */ Cerror, /* opcodes -- these are not recorded */ Onone, Oread, Owrite, Ogrow, Odump, Orele, Ofree,};typedef struct Cw Cw;struct Cw{ Device* dev; Device* cdev; Device* wdev; Device* rodev; Cw* link; Filter ncwio[3]; int dbucket; /* last bucket dumped */ Off daddr; /* last block dumped */ Off ncopy; int nodump;/* * following are cached variables for dumps */ Off fsize; Off ndump; int depth; int all; /* local flag to recur on modified directories */ int allflag; /* global flag to recur on modified directories */ Off falsehits; /* times recur found modified blocks */ struct { char name[500]; char namepad[NAMELEN+10]; };};staticchar* cwnames[] ={ [Cnone] "none", [Cdirty] "dirty", [Cdump] "dump", [Cread] "read", [Cwrite] "write", [Cdump1] "dump1", [Cerror] "error", [Onone] "none", [Oread] "read", [Owrite] "write", [Ogrow] "grow", [Odump] "dump", [Orele] "rele",};Centry* getcentry(Bucket*, Off);int cwio(Device*, Off, void*, int);void cmd_cwcmd(int, char*[]);/* * console command * initiate a dump */voidcmd_dump(int argc, char *argv[]){ Filsys *fs; fs = cons.curfs; if(argc > 1) fs = fsstr(argv[1]); if(fs == 0) { print("%s: unknown file system\n", argv[1]); return; } cfsdump(fs);}/* * console command * worm stats */staticvoidcmd_statw(int, char*[]){ Filsys *fs; Iobuf *p; Superb *sb; Cache *h; Bucket *b; Centry *c, *ce; Off m, nw, bw, state[Onone]; Off sbfsize, sbcwraddr, sbroraddr, sblast, sbnext; Off hmsize, hmaddr, dsize, dsizepct; Device *dev; Cw *cw; int s; fs = cons.curfs; dev = fs->dev; if(dev->type != Devcw) { print("curfs not type cw\n"); return; } cw = dev->private; if(cw == 0) { print("curfs not inited\n"); return; } print("cwstats %s\n", fs->name); sbfsize = 0; sbcwraddr = 0; sbroraddr = 0; sblast = 0; sbnext = 0; print(" filesys %s\n", fs->name); print(" nio =%7W%7W%7W\n", cw->ncwio+0, cw->ncwio+1, cw->ncwio+2); p = getbuf(dev, cwsaddr(dev), Bread); if(!p || checktag(p, Tsuper, QPSUPER)) { print("cwstats: checktag super\n"); if(p) { putbuf(p); p = 0; } } if(p) { sb = (Superb*)p->iobuf; sbfsize = sb->fsize; sbcwraddr = sb->cwraddr; sbroraddr = sb->roraddr; sblast = sb->last; sbnext = sb->next; putbuf(p); } p = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres); if(!p || checktag(p, Tcache, QPSUPER)) { print("cwstats: checktag c bucket\n"); if(p) putbuf(p); return; } h = (Cache*)p->iobuf; hmaddr = h->maddr; hmsize = h->msize; print(" maddr = %8lld\n", (Wideoff)hmaddr); print(" msize = %8lld\n", (Wideoff)hmsize); print(" caddr = %8lld\n", (Wideoff)h->caddr); print(" csize = %8lld\n", (Wideoff)h->csize); print(" sbaddr = %8lld\n", (Wideoff)h->sbaddr); print(" craddr = %8lld %8lld\n", (Wideoff)h->cwraddr, (Wideoff)sbcwraddr); print(" roaddr = %8lld %8lld\n", (Wideoff)h->roraddr, (Wideoff)sbroraddr); /* print stats in terms of (first-)disc sides */ dsize = wormsizeside(dev, 0); if (dsize < 1) { if (DEBUG) print("wormsizeside returned size %lld for %Z side 0\n", (Wideoff)dsize, dev); dsize = h->wsize; /* it's probably a fake worm */ if (dsize < 1) dsize = 1000; /* don't divide by zero */ } dsizepct = dsize/100; print(" fsize = %8lld %8lld %2lld+%2lld%%\n", (Wideoff)h->fsize, (Wideoff)sbfsize, (Wideoff)h->fsize/dsize, (Wideoff)(h->fsize%dsize)/dsizepct); print(" slast = %8lld\n", (Wideoff)sblast); print(" snext = %8lld\n", (Wideoff)sbnext); print(" wmax = %8lld %2lld+%2lld%%\n", (Wideoff)h->wmax, (Wideoff)h->wmax/dsize, (Wideoff)(h->wmax%dsize)/dsizepct); print(" wsize = %8lld %2lld+%2lld%%\n", (Wideoff)h->wsize, (Wideoff)h->wsize/dsize, (Wideoff)(h->wsize%dsize)/dsizepct); putbuf(p); bw = 0; /* max filled bucket */ memset(state, 0, sizeof(state)); for(m=0; m<hmsize; m++) { p = getbuf(cw->cdev, hmaddr + m/BKPERBLK, Bread); if(!p || checktag(p, Tbuck, hmaddr + m/BKPERBLK)) { print("cwstats: checktag c bucket\n"); if(p) putbuf(p); return; } b = (Bucket*)p->iobuf + m%BKPERBLK; ce = b->entry + CEPERBK; nw = 0; for(c=b->entry; c<ce; c++) { s = c->state; state[s]++; if(s != Cnone && s != Cread) nw++; } putbuf(p); if(nw > bw) bw = nw; } for(s=Cnone; s<Cerror; s++) print(" %6lld %s\n", (Wideoff)state[s], cwnames[s]); print(" cache %2lld%% full\n", ((Wideoff)bw*100)/CEPERBK);}intdumpblock(Device *dev){ Iobuf *p, *cb, *p1, *p2; Cache *h; Centry *c, *ce, *bc; Bucket *b; Off m, a, msize, maddr, wmax, caddr; int s1, s2, count; Cw *cw; cw = dev->private; if(cw == 0 || cw->nodump) return 0; cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres); h = (Cache*)cb->iobuf; msize = h->msize; maddr = h->maddr; wmax = h->wmax; caddr = h->caddr; putbuf(cb); for(m=msize; m>=0; m--) { a = cw->dbucket + 1; if(a < 0 || a >= msize) a = 0; cw->dbucket = a; p = getbuf(cw->cdev, maddr + a/BKPERBLK, Bread); b = (Bucket*)p->iobuf + a%BKPERBLK; ce = b->entry + CEPERBK; bc = 0; for(c=b->entry; c<ce; c++) if(c->state == Cdump) { if(bc == 0) { bc = c; continue; } if(c->waddr < cw->daddr) { if(bc->waddr < cw->daddr && bc->waddr > c->waddr) bc = c; continue; } if(bc->waddr < cw->daddr || bc->waddr > c->waddr) bc = c; } if(bc) { c = bc; goto found; } putbuf(p); } if(cw->ncopy) { print("%lld blocks copied to worm\n", (Wideoff)cw->ncopy); cw->ncopy = 0; } cw->nodump = 1; return 0;found: a = a*CEPERBK + (c - b->entry) + caddr; p1 = getbuf(devnone, Cwdump1, 0); count = 0;retry: count++; if(count > 10) goto stop; if(devread(cw->cdev, a, p1->iobuf)) goto stop; m = c->waddr; cw->daddr = m; s1 = devwrite(cw->wdev, m, p1->iobuf); if(s1) { p2 = getbuf(devnone, Cwdump2, 0); s2 = devread(cw->wdev, m, p2->iobuf); if(s2) { if(s1 == 0x61 && s2 == 0x60) { putbuf(p2); goto retry; } goto stop1; } if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) goto stop1; putbuf(p2); } /* * reread and compare */ if(conf.dumpreread) { p2 = getbuf(devnone, Cwdump2, 0); s1 = devread(cw->wdev, m, p2->iobuf); if(s1) goto stop1; if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) { print("reread C%lld W%lld didnt compare\n", (Wideoff)a, (Wideoff)m); goto stop1; } putbuf(p2); } putbuf(p1); c->state = Cread; p->flags |= Bmod; putbuf(p); if(m > wmax) { cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bres); h = (Cache*)cb->iobuf; if(m > h->wmax) h->wmax = m; putbuf(cb); } cw->ncopy++; return 1;stop1: putbuf(p2); putbuf(p1); c->state = Cdump1; p->flags |= Bmod; putbuf(p); return 1;stop: putbuf(p1); putbuf(p); print("stopping dump!!\n"); cw->nodump = 1; return 0;}voidcwinit1(Device *dev){ Cw *cw; static int first; cw = dev->private; if(cw) return; if(first == 0) { cmd_install("dump", "-- make dump backup to worm", cmd_dump); cmd_install("statw", "-- cache/worm stats", cmd_statw); cmd_install("cwcmd", "subcommand -- cache/worm errata", cmd_cwcmd); roflag = flag_install("ro", "-- ro reads and writes"); first = 1; } cw = ialloc(sizeof(Cw), 0); dev->private = cw; cw->allflag = 0; dofilter(cw->ncwio+0, C0a, C0b, 1); dofilter(cw->ncwio+1, C1a, C1b, 1); dofilter(cw->ncwio+2, C2a, C2b, 1); cw->dev = dev; cw->cdev = CDEV(dev); cw->wdev = WDEV(dev); cw->rodev = RDEV(dev); devinit(cw->cdev); devinit(cw->wdev);}voidcwinit(Device *dev){ Cw *cw; Cache *h; Iobuf *cb, *p; Off l, m; cwinit1(dev); cw = dev->private; l = devsize(cw->wdev); cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bres); h = (Cache*)cb->iobuf; h->toytime = toytime() + SECOND(30); h->time = time(); m = h->wsize; if(l != m) { print("wdev changed size %lld to %lld\n", (Wideoff)m, (Wideoff)l); h->wsize = l; cb->flags |= Bmod; } for(m=0; m<h->msize; m++) { p = getbuf(cw->cdev, h->maddr + m/BKPERBLK, Bread); if(!p || checktag(p, Tbuck, h->maddr + m/BKPERBLK)) panic("cwinit: checktag c bucket"); putbuf(p); } putbuf(cb);}Offcwsaddr(Device *dev){ Iobuf *cb; Off sa; cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres); sa = ((Cache*)cb->iobuf)->sbaddr; putbuf(cb); return sa;}Offcwraddr(Device *dev){ Iobuf *cb; Off ra; switch(dev->type) { default: print("unknown dev in cwraddr %Z\n", dev); return 1; case Devcw: cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres); ra = ((Cache*)cb->iobuf)->cwraddr; break; case Devro: cb = getbuf(CDEV(dev->ro.parent), CACHE_ADDR, Bread|Bres); ra = ((Cache*)cb->iobuf)->roraddr; break; } putbuf(cb); return ra;}Devsizecwsize(Device *dev){ Iobuf *cb; Devsize fs; cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres); fs = ((Cache*)cb->iobuf)->fsize; putbuf(cb); return fs;}intcwread(Device *dev, Off b, void *c){ return cwio(dev, b, c, Oread) == Cerror;}intcwwrite(Device *dev, Off b, void *c){ return cwio(dev, b, c, Owrite) == Cerror;}introread(Device *dev, Off b, void *c){ Device *d; int s; /* * maybe better is to try buffer pool first */ d = dev->ro.parent; if(d == 0 || d->type != Devcw || d->private == 0 || RDEV(d) != dev) { print("bad rodev %Z\n", dev); return 1; } s = cwio(d, b, 0, Onone); if(s == Cdump || s == Cdump1 || s == Cread) { s = cwio(d, b, c, Oread); if(s == Cdump || s == Cdump1 || s == Cread) { if(cons.flags & roflag) print("roread: %Z %lld -> %Z(hit)\n", dev, (Wideoff)b, d); return 0; } } if(cons.flags & roflag) print("roread: %Z %lld -> %Z(miss)\n", dev, (Wideoff)b, WDEV(d)); return devread(WDEV(d), b, c);}intcwio(Device *dev, Off addr, void *buf, int opcode){ Iobuf *p, *p1, *p2, *cb; Cache *h; Bucket *b; Centry *c; Off bn, a1, a2, max, newmax; int state; Cw *cw; cw = dev->private; cw->ncwio[0].count++; cw->ncwio[1].count++; cw->ncwio[2].count++; cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres); h = (Cache*)cb->iobuf; if(toytime() >= h->toytime) { cb->flags |= Bmod; h->toytime = toytime() + SECOND(30); h->time = time(); } if(addr < 0) { putbuf(cb); return Cerror; } bn = addr % h->msize; a1 = h->maddr + bn/BKPERBLK; a2 = bn*CEPERBK + h->caddr; max = h->wmax; putbuf(cb); newmax = 0; p = getbuf(cw->cdev, a1, Bread|Bmod); if(!p || checktag(p, Tbuck, a1)) panic("cwio: checktag c bucket"); b = (Bucket*)p->iobuf + bn%BKPERBLK; c = getcentry(b, addr); if(c == 0) { putbuf(p); print("%Z disk cache bucket %lld is full\n", cw->cdev, (Wideoff)a1); return Cerror; } a2 += c - b->entry; state = c->state; switch(opcode) { default: goto bad; case Onone: break; case Oread: switch(state) { default: goto bad; case Cread: if(!devread(cw->cdev, a2, buf)) break; c->state = Cnone; case Cnone: if(devread(cw->wdev, addr, buf)) { state = Cerror; break; } if(addr > max) newmax = addr; if(!devwrite(cw->cdev, a2, buf)) c->state = Cread; break; case Cdirty: case Cdump: case Cdump1: case Cwrite: if(devread(cw->cdev, a2, buf)) state = Cerror; break; } break; case Owrite: switch(state) { default: goto bad; case Cdump: case Cdump1: /* * this is hard part -- a dump block must be * sent to the worm if it is rewritten. * if this causes an error, there is no * place to save the dump1 data. the block * is just reclassified as 'dump1' (botch) */ p1 = getbuf(devnone, Cwio1, 0); if(devread(cw->cdev, a2, p1->iobuf)) { putbuf(p1); print("cwio: write induced dump error - r cache\n"); casenone: if(devwrite(cw->cdev, a2, buf)) { state = Cerror; break; } c->state = Cdump1; break; } if(devwrite(cw->wdev, addr, p1->iobuf)) { p2 = getbuf(devnone, Cwio2, 0); if(devread(cw->wdev, addr, p2->iobuf)) { putbuf(p1); putbuf(p2); print("cwio: write induced dump error - r+w worm\n"); goto casenone; } if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) { putbuf(p1); putbuf(p2); print("cwio: write induced dump error - w worm\n"); goto casenone; } putbuf(p2); } putbuf(p1); c->state = Cread; if(addr > max) newmax = addr; cw->ncopy++; case Cnone: case Cread: if(devwrite(cw->cdev, a2, buf)) { state = Cerror; break; } c->state = Cwrite; break; case Cdirty: case Cwrite: if(devwrite(cw->cdev, a2, buf)) state = Cerror; break; } break; case Ogrow: if(state != Cnone) { print("%Z for block %lld cwgrow with state = %s\n", cw->cdev, (Wideoff)addr, cwnames[state]); break; } c->state = Cdirty; break; case Odump: if(state != Cdirty) { /* BOTCH */ print("%Z for block %lld cwdump with state = %s\n", cw->cdev, (Wideoff)addr, cwnames[state]); break; } c->state = Cdump; cw->ndump++; /* only called from dump command */ break; case Orele: if(state != Cwrite) { if(state != Cdump1) print("%Z for block %lld cwrele with state = %s\n", cw->cdev, (Wideoff)addr, cwnames[state]); break; } c->state = Cnone; break; case Ofree: if(state == Cwrite || state == Cread) c->state = Cnone; break; } if(DEBUG) print("cwio: %Z %lld s=%s o=%s ns=%s\n", dev, (Wideoff)addr, cwnames[state], cwnames[opcode], cwnames[c->state]); putbuf(p); if(newmax) { cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bres); h = (Cache*)cb->iobuf; if(newmax > h->wmax) h->wmax = newmax; putbuf(cb); } return state;bad: print("%Z block %lld cw state = %s; cw opcode = %s", dev, (Wideoff)addr, cwnames[state], cwnames[opcode]); return Cerror;}extern Filsys* dev2fs(Device *dev);intcwgrow(Device *dev, Superb *sb, int uid){ char str[NAMELEN]; Iobuf *cb; Cache *h; Filsys *filsys; Off fs, nfs, ws; cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bmod|Bres); h = (Cache*)cb->iobuf; ws = h->wsize; fs = h->fsize; if(fs >= ws)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -