#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 */ long daddr; /* last block dumped */ long ncopy; int nodump;/* * following are cached variables for dumps */ long fsize; long ndump; int depth; int all; /* local flag to recur on modified directories */ int allflag; /* global flag to recur on modified directories */ long 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*, long);int cwio(Device*, long, 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; long m, nw, bw, state[Onone]; long sbfsize, sbcwraddr, sbroraddr, sblast, sbnext; long hmsize, hmaddr; 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 = %8ld\n", hmaddr); print(" msize = %8ld\n", hmsize); print(" caddr = %8ld\n", h->caddr); print(" csize = %8ld\n", h->csize); print(" sbaddr = %8ld\n", h->sbaddr); print(" craddr = %8ld %8ld\n", h->cwraddr, sbcwraddr); print(" roaddr = %8ld %8ld\n", h->roraddr, sbroraddr); print(" fsize = %8ld %8ld %2ld+%2ld%%\n", h->fsize, sbfsize, h->fsize/DSIZE, (h->fsize%DSIZE)/(DSIZE/100)); print(" slast = %8ld\n", sblast); print(" snext = %8ld\n", sbnext); print(" wmax = %8ld %2ld+%2ld%%\n", h->wmax, h->wmax/DSIZE, (h->wmax%DSIZE)/(DSIZE/100)); print(" wsize = %8ld %2ld+%2ld%%\n", h->wsize, h->wsize/DSIZE, (h->wsize%DSIZE)/(DSIZE/100)); 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(" %6ld %s\n", state[s], cwnames[s]); print(" cache %2ld%% full\n", (bw*100)/CEPERBK);} intdumpblock(Device *dev){ Iobuf *p, *cb, *p1, *p2; Cache *h; Centry *c, *ce, *bc; Bucket *b; long 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("%ld blocks copied to worm\n", 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%ld W%ld didnt compare\n", a, 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; long 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 %ld to %ld\n", m, 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);} longcwsaddr(Device *dev){ Iobuf *cb; long sa; cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres); sa = ((Cache*)cb->iobuf)->sbaddr; putbuf(cb); return sa;} longcwraddr(Device *dev){ Iobuf *cb; long 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;} longcwsize(Device *dev){ Iobuf *cb; long fs; cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres); fs = ((Cache*)cb->iobuf)->fsize; putbuf(cb); return fs;} intcwread(Device *dev, long b, void *c){ return cwio(dev, b, c, Oread) == Cerror;} intcwwrite(Device *dev, long b, void *c){ return cwio(dev, b, c, Owrite) == Cerror;} introread(Device *dev, long b, void *c){ Device *d; int s; /* * maybe better is to try buffer pool first */Lines 1–500 of 2246. Load more
#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 */ long daddr; /* last block dumped */ long ncopy; int nodump; /* * following are cached variables for dumps */ long fsize; long ndump; int depth; int all; /* local flag to recur on modified directories */ int allflag; /* global flag to recur on modified directories */ long 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*, long); int cwio(Device*, long, void*, int); void cmd_cwcmd(int, char*[]); /* * console command * initiate a dump */ 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); } /* * console command * worm stats */ static void cmd_statw(int, char*[]) { Filsys *fs; Iobuf *p; Superb *sb; Cache *h; Bucket *b; Centry *c, *ce; long m, nw, bw, state[Onone]; long sbfsize, sbcwraddr, sbroraddr, sblast, sbnext; long hmsize, hmaddr; 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 = %8ld\n", hmaddr); print(" msize = %8ld\n", hmsize); print(" caddr = %8ld\n", h->caddr); print(" csize = %8ld\n", h->csize); print(" sbaddr = %8ld\n", h->sbaddr); print(" craddr = %8ld %8ld\n", h->cwraddr, sbcwraddr); print(" roaddr = %8ld %8ld\n", h->roraddr, sbroraddr); print(" fsize = %8ld %8ld %2ld+%2ld%%\n", h->fsize, sbfsize, h->fsize/DSIZE, (h->fsize%DSIZE)/(DSIZE/100)); print(" slast = %8ld\n", sblast); print(" snext = %8ld\n", sbnext); print(" wmax = %8ld %2ld+%2ld%%\n", h->wmax, h->wmax/DSIZE, (h->wmax%DSIZE)/(DSIZE/100)); print(" wsize = %8ld %2ld+%2ld%%\n", h->wsize, h->wsize/DSIZE, (h->wsize%DSIZE)/(DSIZE/100)); 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(" %6ld %s\n", state[s], cwnames[s]); print(" cache %2ld%% full\n", (bw*100)/CEPERBK); } int dumpblock(Device *dev) { Iobuf *p, *cb, *p1, *p2; Cache *h; Centry *c, *ce, *bc; Bucket *b; long 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("%ld blocks copied to worm\n", 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%ld W%ld didnt compare\n", a, 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; } 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("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); } void cwinit(Device *dev) { Cw *cw; Cache *h; Iobuf *cb, *p; long 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 %ld to %ld\n", m, 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); } long cwsaddr(Device *dev) { Iobuf *cb; long sa; cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres); sa = ((Cache*)cb->iobuf)->sbaddr; putbuf(cb); return sa; } long cwraddr(Device *dev) { Iobuf *cb; long 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; } long cwsize(Device *dev) { Iobuf *cb; long fs; cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres); fs = ((Cache*)cb->iobuf)->fsize; putbuf(cb); return fs; } int cwread(Device *dev, long b, void *c) { return cwio(dev, b, c, Oread) == Cerror; } int cwwrite(Device *dev, long b, void *c) { return cwio(dev, b, c, Owrite) == Cerror; } int roread(Device *dev, long b, void *c) { Device *d; int s; /* * maybe better is to try buffer pool first */