#include "all.h"#include "mem.h" // for Ticks. #define dprint(...)#define dpprint(...) //print(__VA_ARGS__) #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; 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 */extern Timet nextdump(Timet); 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); nextdump(time());} voidcmd_dumpctl(int argc, char *argv[]){ char *s; if(argc == 2){ if(strcmp(argv[1], "on") == 0) conf.nodump = 0; else conf.nodump = 1; } s = "on\0off"+conf.nodump*3; print("automatic dumps are %s\n", s);} /* * 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 =%W\n", &cw->ncwio); 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) { dprint("wormsizeside sz %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(" %8lld %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, 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; a = a + (c - b->entry)*msize + caddr; p1 = getbuf(devnone, Cwdump1, 0); count = 0; retry: count++; if(count > 10) goto stop; dpprint("dumpblock %lld\n", a); if(devread(cw->cdev, a, p1->iobuf)) goto stop; m = c->waddr; cw->daddr = m; s1 = devwrite(cw->wdev, m, p1->iobuf); if(s1) goto retry; /* * 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); if(conf.fastworm) c->state = Cnone; else 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("dumpctl", "[on|off] -- automatic dumps", cmd_dumpctl); 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"); } cw = ialloc(sizeof(Cw), 0); dev->private = cw; cw->allflag = 0; dofilter(&cw->ncwio); 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;}Lines 1–500 of 2269. Load more
#include "all.h" #include "mem.h" // for Ticks. #define dprint(...) #define dpprint(...) //print(__VA_ARGS__) #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; 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]; }; }; static char* 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 */ extern Timet nextdump(Timet); void cmd_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); nextdump(time()); } void cmd_dumpctl(int argc, char *argv[]) { char *s; if(argc == 2){ if(strcmp(argv[1], "on") == 0) conf.nodump = 0; else conf.nodump = 1; } s = "on\0off"+conf.nodump*3; print("automatic dumps are %s\n", s); } /* * console command * worm stats */ static void cmd_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 =%W\n", &cw->ncwio); 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) { dprint("wormsizeside sz %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(" %8lld %s\n", (Wideoff)state[s], cwnames[s]); print(" cache %2lld%% full\n", ((Wideoff)bw*100)/CEPERBK); } int dumpblock(Device *dev) { Iobuf *p, *cb, *p1, *p2; Cache *h; Centry *c, *ce, *bc; Bucket *b; Off m, a, msize, maddr, wmax, caddr; int s1, 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; a = a + (c - b->entry)*msize + caddr; p1 = getbuf(devnone, Cwdump1, 0); count = 0; retry: count++; if(count > 10) goto stop; dpprint("dumpblock %lld\n", a); if(devread(cw->cdev, a, p1->iobuf)) goto stop; m = c->waddr; cw->daddr = m; s1 = devwrite(cw->wdev, m, p1->iobuf); if(s1) goto retry; /* * 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); if(conf.fastworm) c->state = Cnone; else 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; } void cwinit1(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("dumpctl", "[on|off] -- automatic dumps", cmd_dumpctl); 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"); } cw = ialloc(sizeof(Cw), 0); dev->private = cw; cw->allflag = 0; dofilter(&cw->ncwio); cw->dev = dev; cw->cdev = CDEV(dev); cw->wdev = WDEV(dev); cw->rodev = RDEV(dev); devinit(cw->cdev); devinit(cw->wdev); } void cwinit(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); } Off cwsaddr(Device *dev) { Iobuf *cb; Off sa; cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres); sa = ((Cache*)cb->iobuf)->sbaddr; putbuf(cb); return sa; } Off cwraddr(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; } Devsize cwsize(Device *dev) { Iobuf *cb; Devsize fs; cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres); fs = ((Cache*)cb->iobuf)->fsize; putbuf(cb); return fs; }