101a344a2SDavid du Colombier /*
201a344a2SDavid du Colombier * cached-worm device
301a344a2SDavid du Colombier */
401a344a2SDavid du Colombier #include "all.h"
501a344a2SDavid du Colombier
601a344a2SDavid du Colombier #define CDEV(d) ((d)->cw.c)
701a344a2SDavid du Colombier #define WDEV(d) ((d)->cw.w)
801a344a2SDavid du Colombier #define RDEV(d) ((d)->cw.ro)
901a344a2SDavid du Colombier
1001a344a2SDavid du Colombier enum {
1101a344a2SDavid du Colombier DEBUG = 0,
1201a344a2SDavid du Colombier FIRST = SUPER_ADDR,
1301a344a2SDavid du Colombier
1401a344a2SDavid du Colombier ADDFREE = 100,
1501a344a2SDavid du Colombier CACHE_ADDR = SUPER_ADDR,
1601a344a2SDavid du Colombier MAXAGE = 10000,
1701a344a2SDavid du Colombier };
1801a344a2SDavid du Colombier
1901a344a2SDavid du Colombier /* cache state */
2001a344a2SDavid du Colombier enum
2101a344a2SDavid du Colombier {
2201a344a2SDavid du Colombier /* states -- beware these are recorded on the cache */
2301a344a2SDavid du Colombier /* cache worm */
2401a344a2SDavid du Colombier Cnone = 0, /* 0 ? */
2501a344a2SDavid du Colombier Cdirty, /* 1 0 */
2601a344a2SDavid du Colombier Cdump, /* 1 0->1 */
2701a344a2SDavid du Colombier Cread, /* 1 1 */
2801a344a2SDavid du Colombier Cwrite, /* 2 1 */
2901a344a2SDavid du Colombier Cdump1, /* inactive form of dump */
3001a344a2SDavid du Colombier Cerror,
3101a344a2SDavid du Colombier
3201a344a2SDavid du Colombier /* opcodes -- these are not recorded */
3301a344a2SDavid du Colombier Onone,
3401a344a2SDavid du Colombier Oread,
3501a344a2SDavid du Colombier Owrite,
3601a344a2SDavid du Colombier Ogrow,
3701a344a2SDavid du Colombier Odump,
3801a344a2SDavid du Colombier Orele,
3901a344a2SDavid du Colombier Ofree,
4001a344a2SDavid du Colombier };
4101a344a2SDavid du Colombier
4201a344a2SDavid du Colombier typedef struct Cw Cw;
4301a344a2SDavid du Colombier struct Cw
4401a344a2SDavid du Colombier {
4501a344a2SDavid du Colombier Device* dev;
4601a344a2SDavid du Colombier Device* cdev;
4701a344a2SDavid du Colombier Device* wdev;
4801a344a2SDavid du Colombier Device* rodev;
4901a344a2SDavid du Colombier Cw* link;
5001a344a2SDavid du Colombier
5101a344a2SDavid du Colombier int dbucket; /* last bucket dumped */
5201a344a2SDavid du Colombier Off daddr; /* last block dumped */
5301a344a2SDavid du Colombier Off ncopy;
5401a344a2SDavid du Colombier int nodump;
5501a344a2SDavid du Colombier /*
5601a344a2SDavid du Colombier * following are cached variables for dumps
5701a344a2SDavid du Colombier */
5801a344a2SDavid du Colombier Off fsize;
5901a344a2SDavid du Colombier Off ndump;
6001a344a2SDavid du Colombier int depth;
6101a344a2SDavid du Colombier int all; /* local flag to recur on modified dirs */
6201a344a2SDavid du Colombier int allflag; /* global flag to recur on modified dirs */
6301a344a2SDavid du Colombier Off falsehits; /* times recur found modified blocks */
6401a344a2SDavid du Colombier struct {
6501a344a2SDavid du Colombier char name[500];
6601a344a2SDavid du Colombier char namepad[NAMELEN+10];
6701a344a2SDavid du Colombier };
6801a344a2SDavid du Colombier };
6901a344a2SDavid du Colombier
7001a344a2SDavid du Colombier static char* cwnames[] =
7101a344a2SDavid du Colombier {
7201a344a2SDavid du Colombier [Cnone] "none",
7301a344a2SDavid du Colombier [Cdirty] "dirty",
7401a344a2SDavid du Colombier [Cdump] "dump",
7501a344a2SDavid du Colombier [Cread] "read",
7601a344a2SDavid du Colombier [Cwrite] "write",
7701a344a2SDavid du Colombier [Cdump1] "dump1",
7801a344a2SDavid du Colombier [Cerror] "error",
7901a344a2SDavid du Colombier
8001a344a2SDavid du Colombier [Onone] "none",
8101a344a2SDavid du Colombier [Oread] "read",
8201a344a2SDavid du Colombier [Owrite] "write",
8301a344a2SDavid du Colombier [Ogrow] "grow",
8401a344a2SDavid du Colombier [Odump] "dump",
8501a344a2SDavid du Colombier [Orele] "rele",
8601a344a2SDavid du Colombier };
8701a344a2SDavid du Colombier
88698b102bSDavid du Colombier int oldcachefmt = 1;
89698b102bSDavid du Colombier
9001a344a2SDavid du Colombier Centry* getcentry(Bucket*, Off);
9101a344a2SDavid du Colombier int cwio(Device*, Off, void*, int);
9201a344a2SDavid du Colombier void cmd_cwcmd(int, char*[]);
9301a344a2SDavid du Colombier
9401a344a2SDavid du Colombier /*
9501a344a2SDavid du Colombier * console command
9601a344a2SDavid du Colombier * initiate a dump
9701a344a2SDavid du Colombier */
9801a344a2SDavid du Colombier void
cmd_dump(int argc,char * argv[])9901a344a2SDavid du Colombier cmd_dump(int argc, char *argv[])
10001a344a2SDavid du Colombier {
10101a344a2SDavid du Colombier Filsys *fs;
10201a344a2SDavid du Colombier
10301a344a2SDavid du Colombier fs = cons.curfs;
10401a344a2SDavid du Colombier if(argc > 1)
10501a344a2SDavid du Colombier fs = fsstr(argv[1]);
10601a344a2SDavid du Colombier if(fs == 0) {
10701a344a2SDavid du Colombier print("%s: unknown file system\n", argv[1]);
10801a344a2SDavid du Colombier return;
10901a344a2SDavid du Colombier }
11001a344a2SDavid du Colombier cfsdump(fs);
11101a344a2SDavid du Colombier }
11201a344a2SDavid du Colombier
11301a344a2SDavid du Colombier /*
11401a344a2SDavid du Colombier * console command
11501a344a2SDavid du Colombier * worm stats
11601a344a2SDavid du Colombier */
11701a344a2SDavid du Colombier static void
cmd_statw(int,char * [])11801a344a2SDavid du Colombier cmd_statw(int, char*[])
11901a344a2SDavid du Colombier {
12001a344a2SDavid du Colombier Filsys *fs;
12101a344a2SDavid du Colombier Iobuf *p;
12201a344a2SDavid du Colombier Superb *sb;
12301a344a2SDavid du Colombier Cache *h;
12401a344a2SDavid du Colombier Bucket *b;
12501a344a2SDavid du Colombier Centry *c, *ce;
12601a344a2SDavid du Colombier Off m, nw, bw, state[Onone];
12701a344a2SDavid du Colombier Off sbfsize, sbcwraddr, sbroraddr, sblast, sbnext;
12801a344a2SDavid du Colombier Off hmsize, hmaddr, dsize, dsizepct;
12901a344a2SDavid du Colombier Device *dev;
13001a344a2SDavid du Colombier Cw *cw;
13101a344a2SDavid du Colombier int s;
13201a344a2SDavid du Colombier
13301a344a2SDavid du Colombier fs = cons.curfs;
13401a344a2SDavid du Colombier dev = fs->dev;
13501a344a2SDavid du Colombier if(dev->type != Devcw) {
13601a344a2SDavid du Colombier print("curfs not type cw\n");
13701a344a2SDavid du Colombier return;
13801a344a2SDavid du Colombier }
13901a344a2SDavid du Colombier
14001a344a2SDavid du Colombier cw = dev->private;
14101a344a2SDavid du Colombier if(cw == 0) {
14201a344a2SDavid du Colombier print("curfs not inited\n");
14301a344a2SDavid du Colombier return;
14401a344a2SDavid du Colombier }
14501a344a2SDavid du Colombier
14601a344a2SDavid du Colombier print("cwstats %s\n", fs->name);
14701a344a2SDavid du Colombier
14801a344a2SDavid du Colombier sbfsize = 0;
14901a344a2SDavid du Colombier sbcwraddr = 0;
15001a344a2SDavid du Colombier sbroraddr = 0;
15101a344a2SDavid du Colombier sblast = 0;
15201a344a2SDavid du Colombier sbnext = 0;
15301a344a2SDavid du Colombier
15401a344a2SDavid du Colombier print("\tfilesys %s\n", fs->name);
15501a344a2SDavid du Colombier // print("\tnio =%7W%7W%7W\n", cw->ncwio+0, cw->ncwio+1, cw->ncwio+2);
15601a344a2SDavid du Colombier p = getbuf(dev, cwsaddr(dev), Brd);
15701a344a2SDavid du Colombier if(!p || checktag(p, Tsuper, QPSUPER)) {
15801a344a2SDavid du Colombier print("cwstats: checktag super\n");
15901a344a2SDavid du Colombier if(p) {
16001a344a2SDavid du Colombier putbuf(p);
16101a344a2SDavid du Colombier p = 0;
16201a344a2SDavid du Colombier }
16301a344a2SDavid du Colombier }
16401a344a2SDavid du Colombier if(p) {
16501a344a2SDavid du Colombier sb = (Superb*)p->iobuf;
16601a344a2SDavid du Colombier sbfsize = sb->fsize;
16701a344a2SDavid du Colombier sbcwraddr = sb->cwraddr;
16801a344a2SDavid du Colombier sbroraddr = sb->roraddr;
16901a344a2SDavid du Colombier sblast = sb->last;
17001a344a2SDavid du Colombier sbnext = sb->next;
17101a344a2SDavid du Colombier putbuf(p);
17201a344a2SDavid du Colombier }
17301a344a2SDavid du Colombier
17401a344a2SDavid du Colombier p = getbuf(cw->cdev, CACHE_ADDR, Brd|Bres);
17501a344a2SDavid du Colombier if(!p || checktag(p, Tcache, QPSUPER)) {
17601a344a2SDavid du Colombier print("cwstats: checktag c bucket\n");
17701a344a2SDavid du Colombier if(p)
17801a344a2SDavid du Colombier putbuf(p);
17901a344a2SDavid du Colombier return;
18001a344a2SDavid du Colombier }
18101a344a2SDavid du Colombier h = (Cache*)p->iobuf;
18201a344a2SDavid du Colombier hmaddr = h->maddr;
18301a344a2SDavid du Colombier hmsize = h->msize;
18401a344a2SDavid du Colombier
18501a344a2SDavid du Colombier print("\t\tmaddr = %8lld\n", (Wideoff)hmaddr);
18601a344a2SDavid du Colombier print("\t\tmsize = %8lld\n", (Wideoff)hmsize);
18701a344a2SDavid du Colombier print("\t\tcaddr = %8lld\n", (Wideoff)h->caddr);
18801a344a2SDavid du Colombier print("\t\tcsize = %8lld\n", (Wideoff)h->csize);
18901a344a2SDavid du Colombier print("\t\tsbaddr = %8lld\n", (Wideoff)h->sbaddr);
19001a344a2SDavid du Colombier print("\t\tcraddr = %8lld %8lld\n",
19101a344a2SDavid du Colombier (Wideoff)h->cwraddr, (Wideoff)sbcwraddr);
19201a344a2SDavid du Colombier print("\t\troaddr = %8lld %8lld\n",
19301a344a2SDavid du Colombier (Wideoff)h->roraddr, (Wideoff)sbroraddr);
19401a344a2SDavid du Colombier /* print stats in terms of (first-)disc sides */
19501a344a2SDavid du Colombier dsize = wormsizeside(dev, 0);
19601a344a2SDavid du Colombier if (dsize < 1) {
19701a344a2SDavid du Colombier if (DEBUG)
19801a344a2SDavid du Colombier print("wormsizeside returned size %lld for %Z side 0\n",
19901a344a2SDavid du Colombier (Wideoff)dsize, dev);
20001a344a2SDavid du Colombier dsize = h->wsize; /* it's probably a fake worm */
20101a344a2SDavid du Colombier if (dsize < 1)
20201a344a2SDavid du Colombier dsize = 1000; /* don't divide by zero */
20301a344a2SDavid du Colombier }
20401a344a2SDavid du Colombier dsizepct = dsize/100;
20501a344a2SDavid du Colombier print("\t\tfsize = %8lld %8lld %2lld+%2lld%%\n", (Wideoff)h->fsize,
20601a344a2SDavid du Colombier (Wideoff)sbfsize, (Wideoff)h->fsize/dsize,
20701a344a2SDavid du Colombier (Wideoff)(h->fsize%dsize)/dsizepct);
20801a344a2SDavid du Colombier print("\t\tslast = %8lld\n", (Wideoff)sblast);
20901a344a2SDavid du Colombier print("\t\tsnext = %8lld\n", (Wideoff)sbnext);
21001a344a2SDavid du Colombier print("\t\twmax = %8lld %2lld+%2lld%%\n",
21101a344a2SDavid du Colombier (Wideoff)h->wmax, (Wideoff)h->wmax/dsize,
21201a344a2SDavid du Colombier (Wideoff)(h->wmax%dsize)/dsizepct);
21301a344a2SDavid du Colombier print("\t\twsize = %8lld %2lld+%2lld%%\n",
21401a344a2SDavid du Colombier (Wideoff)h->wsize, (Wideoff)h->wsize/dsize,
21501a344a2SDavid du Colombier (Wideoff)(h->wsize%dsize)/dsizepct);
21601a344a2SDavid du Colombier putbuf(p);
21701a344a2SDavid du Colombier
21801a344a2SDavid du Colombier bw = 0; /* max filled bucket */
21901a344a2SDavid du Colombier memset(state, 0, sizeof(state));
22001a344a2SDavid du Colombier for(m = 0; m < hmsize; m++) {
22101a344a2SDavid du Colombier p = getbuf(cw->cdev, hmaddr + m/BKPERBLK, Brd);
22201a344a2SDavid du Colombier if(!p || checktag(p, Tbuck, hmaddr + m/BKPERBLK)) {
22301a344a2SDavid du Colombier print("cwstats: checktag c bucket\n");
22401a344a2SDavid du Colombier if(p)
22501a344a2SDavid du Colombier putbuf(p);
22601a344a2SDavid du Colombier return;
22701a344a2SDavid du Colombier }
22801a344a2SDavid du Colombier b = (Bucket*)p->iobuf + m%BKPERBLK;
22901a344a2SDavid du Colombier ce = b->entry + CEPERBK;
23001a344a2SDavid du Colombier nw = 0;
23101a344a2SDavid du Colombier for(c = b->entry; c < ce; c++) {
23201a344a2SDavid du Colombier s = c->state;
23301a344a2SDavid du Colombier state[s]++;
23401a344a2SDavid du Colombier if(s != Cnone && s != Cread)
23501a344a2SDavid du Colombier nw++;
23601a344a2SDavid du Colombier }
23701a344a2SDavid du Colombier putbuf(p);
23801a344a2SDavid du Colombier if(nw > bw)
23901a344a2SDavid du Colombier bw = nw;
24001a344a2SDavid du Colombier }
24101a344a2SDavid du Colombier for(s = Cnone; s < Cerror; s++)
24201a344a2SDavid du Colombier print("\t\t%6lld %s\n", (Wideoff)state[s], cwnames[s]);
24301a344a2SDavid du Colombier print("\t\tcache %2lld%% full\n", ((Wideoff)bw*100)/CEPERBK);
24401a344a2SDavid du Colombier }
24501a344a2SDavid du Colombier
24601a344a2SDavid du Colombier int
dumpblock(Device * dev)24701a344a2SDavid du Colombier dumpblock(Device *dev)
24801a344a2SDavid du Colombier {
24901a344a2SDavid du Colombier Iobuf *p, *cb, *p1, *p2;
25001a344a2SDavid du Colombier Cache *h;
25101a344a2SDavid du Colombier Centry *c, *ce, *bc;
25201a344a2SDavid du Colombier Bucket *b;
25301a344a2SDavid du Colombier Off m, a, msize, maddr, wmax, caddr;
25401a344a2SDavid du Colombier int s1, s2, count;
25501a344a2SDavid du Colombier Cw *cw;
25601a344a2SDavid du Colombier
25701a344a2SDavid du Colombier cw = dev->private;
25801a344a2SDavid du Colombier if(cw == 0 || cw->nodump)
25901a344a2SDavid du Colombier return 0;
26001a344a2SDavid du Colombier
26101a344a2SDavid du Colombier cb = getbuf(cw->cdev, CACHE_ADDR, Brd|Bres);
26201a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
26301a344a2SDavid du Colombier msize = h->msize;
26401a344a2SDavid du Colombier maddr = h->maddr;
26501a344a2SDavid du Colombier wmax = h->wmax;
26601a344a2SDavid du Colombier caddr = h->caddr;
26701a344a2SDavid du Colombier putbuf(cb);
26801a344a2SDavid du Colombier
26901a344a2SDavid du Colombier for(m=msize; m>=0; m--) {
27001a344a2SDavid du Colombier a = cw->dbucket + 1;
27101a344a2SDavid du Colombier if(a < 0 || a >= msize)
27201a344a2SDavid du Colombier a = 0;
27301a344a2SDavid du Colombier cw->dbucket = a;
27401a344a2SDavid du Colombier p = getbuf(cw->cdev, maddr + a/BKPERBLK, Brd);
27501a344a2SDavid du Colombier b = (Bucket*)p->iobuf + a%BKPERBLK;
27601a344a2SDavid du Colombier ce = b->entry + CEPERBK;
27701a344a2SDavid du Colombier bc = 0;
27801a344a2SDavid du Colombier for(c = b->entry; c < ce; c++)
27901a344a2SDavid du Colombier if(c->state == Cdump) {
28001a344a2SDavid du Colombier if(bc == 0) {
28101a344a2SDavid du Colombier bc = c;
28201a344a2SDavid du Colombier continue;
28301a344a2SDavid du Colombier }
28401a344a2SDavid du Colombier if(c->waddr < cw->daddr) {
28501a344a2SDavid du Colombier if(bc->waddr < cw->daddr &&
28601a344a2SDavid du Colombier bc->waddr > c->waddr)
28701a344a2SDavid du Colombier bc = c;
28801a344a2SDavid du Colombier continue;
28901a344a2SDavid du Colombier }
29001a344a2SDavid du Colombier if(bc->waddr < cw->daddr ||
29101a344a2SDavid du Colombier bc->waddr > c->waddr)
29201a344a2SDavid du Colombier bc = c;
29301a344a2SDavid du Colombier }
29401a344a2SDavid du Colombier if(bc) {
29501a344a2SDavid du Colombier c = bc;
29601a344a2SDavid du Colombier goto found;
29701a344a2SDavid du Colombier }
29801a344a2SDavid du Colombier putbuf(p);
29901a344a2SDavid du Colombier }
30001a344a2SDavid du Colombier if(cw->ncopy) {
30101a344a2SDavid du Colombier print("%lld blocks copied to worm\n", (Wideoff)cw->ncopy);
30201a344a2SDavid du Colombier cw->ncopy = 0;
30301a344a2SDavid du Colombier }
30401a344a2SDavid du Colombier cw->nodump = 1;
30501a344a2SDavid du Colombier return 0;
30601a344a2SDavid du Colombier
30701a344a2SDavid du Colombier found:
308698b102bSDavid du Colombier if (oldcachefmt)
30901a344a2SDavid du Colombier a = a*CEPERBK + (c - b->entry) + caddr;
310698b102bSDavid du Colombier else
311698b102bSDavid du Colombier a += (c - b->entry)*msize + caddr;
31201a344a2SDavid du Colombier p1 = getbuf(devnone, Cwdump1, 0);
31301a344a2SDavid du Colombier count = 0;
31401a344a2SDavid du Colombier
31501a344a2SDavid du Colombier retry:
31601a344a2SDavid du Colombier count++;
317698b102bSDavid du Colombier if(count > 10 || devread(cw->cdev, a, p1->iobuf))
31801a344a2SDavid du Colombier goto stop;
31901a344a2SDavid du Colombier m = c->waddr;
32001a344a2SDavid du Colombier cw->daddr = m;
32101a344a2SDavid du Colombier s1 = devwrite(cw->wdev, m, p1->iobuf);
32201a344a2SDavid du Colombier if(s1) {
32301a344a2SDavid du Colombier p2 = getbuf(devnone, Cwdump2, 0);
32401a344a2SDavid du Colombier s2 = devread(cw->wdev, m, p2->iobuf);
32501a344a2SDavid du Colombier if(s2) {
32601a344a2SDavid du Colombier if(s1 == 0x61 && s2 == 0x60) {
32701a344a2SDavid du Colombier putbuf(p2);
32801a344a2SDavid du Colombier goto retry;
32901a344a2SDavid du Colombier }
33001a344a2SDavid du Colombier goto stop1;
33101a344a2SDavid du Colombier }
33201a344a2SDavid du Colombier if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE))
33301a344a2SDavid du Colombier goto stop1;
33401a344a2SDavid du Colombier putbuf(p2);
33501a344a2SDavid du Colombier }
33601a344a2SDavid du Colombier /*
33701a344a2SDavid du Colombier * reread and compare
33801a344a2SDavid du Colombier */
33901a344a2SDavid du Colombier if(conf.dumpreread) {
34001a344a2SDavid du Colombier p2 = getbuf(devnone, Cwdump2, 0);
34101a344a2SDavid du Colombier s1 = devread(cw->wdev, m, p2->iobuf);
34201a344a2SDavid du Colombier if(s1)
34301a344a2SDavid du Colombier goto stop1;
34401a344a2SDavid du Colombier if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) {
34501a344a2SDavid du Colombier print("reread C%lld W%lld didnt compare\n",
34601a344a2SDavid du Colombier (Wideoff)a, (Wideoff)m);
34701a344a2SDavid du Colombier goto stop1;
34801a344a2SDavid du Colombier }
34901a344a2SDavid du Colombier putbuf(p2);
35001a344a2SDavid du Colombier }
35101a344a2SDavid du Colombier
35201a344a2SDavid du Colombier putbuf(p1);
35301a344a2SDavid du Colombier c->state = Cread;
35401a344a2SDavid du Colombier p->flags |= Bmod;
35501a344a2SDavid du Colombier putbuf(p);
35601a344a2SDavid du Colombier
35701a344a2SDavid du Colombier if(m > wmax) {
35801a344a2SDavid du Colombier cb = getbuf(cw->cdev, CACHE_ADDR, Brd|Bmod|Bres);
35901a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
36001a344a2SDavid du Colombier if(m > h->wmax)
36101a344a2SDavid du Colombier h->wmax = m;
36201a344a2SDavid du Colombier putbuf(cb);
36301a344a2SDavid du Colombier }
36401a344a2SDavid du Colombier cw->ncopy++;
36501a344a2SDavid du Colombier return 1;
36601a344a2SDavid du Colombier
36701a344a2SDavid du Colombier stop1:
36801a344a2SDavid du Colombier putbuf(p2);
36901a344a2SDavid du Colombier putbuf(p1);
37001a344a2SDavid du Colombier c->state = Cdump1;
37101a344a2SDavid du Colombier p->flags |= Bmod;
37201a344a2SDavid du Colombier putbuf(p);
37301a344a2SDavid du Colombier return 1;
37401a344a2SDavid du Colombier
37501a344a2SDavid du Colombier stop:
37601a344a2SDavid du Colombier putbuf(p1);
37701a344a2SDavid du Colombier putbuf(p);
37801a344a2SDavid du Colombier print("stopping dump!!\n");
37901a344a2SDavid du Colombier cw->nodump = 1;
38001a344a2SDavid du Colombier return 0;
38101a344a2SDavid du Colombier }
38201a344a2SDavid du Colombier
38301a344a2SDavid du Colombier void
cwinit1(Device * dev)38401a344a2SDavid du Colombier cwinit1(Device *dev)
38501a344a2SDavid du Colombier {
38601a344a2SDavid du Colombier Cw *cw;
38701a344a2SDavid du Colombier static int first;
38801a344a2SDavid du Colombier
38901a344a2SDavid du Colombier cw = dev->private;
39001a344a2SDavid du Colombier if(cw)
39101a344a2SDavid du Colombier return;
39201a344a2SDavid du Colombier
39301a344a2SDavid du Colombier if(first == 0) {
39401a344a2SDavid du Colombier cmd_install("dump", "-- make dump backup to worm", cmd_dump);
39501a344a2SDavid du Colombier cmd_install("statw", "-- cache/worm stats", cmd_statw);
39601a344a2SDavid du Colombier cmd_install("cwcmd", "subcommand -- cache/worm errata", cmd_cwcmd);
39701a344a2SDavid du Colombier roflag = flag_install("ro", "-- ro reads and writes");
39801a344a2SDavid du Colombier first = 1;
39901a344a2SDavid du Colombier }
40001a344a2SDavid du Colombier cw = malloc(sizeof(Cw));
40101a344a2SDavid du Colombier dev->private = cw;
40201a344a2SDavid du Colombier
40301a344a2SDavid du Colombier cw->allflag = 0;
40401a344a2SDavid du Colombier
40501a344a2SDavid du Colombier cw->dev = dev;
40601a344a2SDavid du Colombier cw->cdev = CDEV(dev);
40701a344a2SDavid du Colombier cw->wdev = WDEV(dev);
40801a344a2SDavid du Colombier cw->rodev = RDEV(dev);
40901a344a2SDavid du Colombier
41001a344a2SDavid du Colombier devinit(cw->cdev);
41101a344a2SDavid du Colombier devinit(cw->wdev);
41201a344a2SDavid du Colombier }
41301a344a2SDavid du Colombier
41401a344a2SDavid du Colombier void
cwinit(Device * dev)41501a344a2SDavid du Colombier cwinit(Device *dev)
41601a344a2SDavid du Colombier {
41701a344a2SDavid du Colombier Cw *cw;
41801a344a2SDavid du Colombier Cache *h;
41901a344a2SDavid du Colombier Iobuf *cb, *p;
42001a344a2SDavid du Colombier Off l, m;
42101a344a2SDavid du Colombier
42201a344a2SDavid du Colombier cwinit1(dev);
42301a344a2SDavid du Colombier
42401a344a2SDavid du Colombier cw = dev->private;
42501a344a2SDavid du Colombier l = devsize(cw->wdev);
42601a344a2SDavid du Colombier cb = getbuf(cw->cdev, CACHE_ADDR, Brd|Bmod|Bres);
42701a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
42801a344a2SDavid du Colombier h->toytime = toytime() + SECOND(30);
42901a344a2SDavid du Colombier h->time = time(nil);
43001a344a2SDavid du Colombier m = h->wsize;
43101a344a2SDavid du Colombier if(l != m) {
43201a344a2SDavid du Colombier print("wdev changed size %lld to %lld\n",
43301a344a2SDavid du Colombier (Wideoff)m, (Wideoff)l);
43401a344a2SDavid du Colombier h->wsize = l;
43501a344a2SDavid du Colombier cb->flags |= Bmod;
43601a344a2SDavid du Colombier }
43701a344a2SDavid du Colombier
43801a344a2SDavid du Colombier for(m=0; m<h->msize; m++) {
43901a344a2SDavid du Colombier p = getbuf(cw->cdev, h->maddr + m/BKPERBLK, Brd);
44001a344a2SDavid du Colombier if(!p || checktag(p, Tbuck, h->maddr + m/BKPERBLK))
44101a344a2SDavid du Colombier panic("cwinit: checktag c bucket");
44201a344a2SDavid du Colombier putbuf(p);
44301a344a2SDavid du Colombier }
44401a344a2SDavid du Colombier putbuf(cb);
44501a344a2SDavid du Colombier }
44601a344a2SDavid du Colombier
44701a344a2SDavid du Colombier Off
cwsaddr(Device * dev)44801a344a2SDavid du Colombier cwsaddr(Device *dev)
44901a344a2SDavid du Colombier {
45001a344a2SDavid du Colombier Iobuf *cb;
45101a344a2SDavid du Colombier Off sa;
45201a344a2SDavid du Colombier
45301a344a2SDavid du Colombier cb = getbuf(CDEV(dev), CACHE_ADDR, Brd|Bres);
45401a344a2SDavid du Colombier sa = ((Cache*)cb->iobuf)->sbaddr;
45501a344a2SDavid du Colombier putbuf(cb);
45601a344a2SDavid du Colombier return sa;
45701a344a2SDavid du Colombier }
45801a344a2SDavid du Colombier
45901a344a2SDavid du Colombier Off
cwraddr(Device * dev)46001a344a2SDavid du Colombier cwraddr(Device *dev)
46101a344a2SDavid du Colombier {
46201a344a2SDavid du Colombier Iobuf *cb;
46301a344a2SDavid du Colombier Off ra;
46401a344a2SDavid du Colombier
46501a344a2SDavid du Colombier switch(dev->type) {
46601a344a2SDavid du Colombier default:
46701a344a2SDavid du Colombier print("unknown dev in cwraddr %Z\n", dev);
46801a344a2SDavid du Colombier return 1;
46901a344a2SDavid du Colombier
47001a344a2SDavid du Colombier case Devcw:
47101a344a2SDavid du Colombier cb = getbuf(CDEV(dev), CACHE_ADDR, Brd|Bres);
47201a344a2SDavid du Colombier ra = ((Cache*)cb->iobuf)->cwraddr;
47301a344a2SDavid du Colombier break;
47401a344a2SDavid du Colombier
47501a344a2SDavid du Colombier case Devro:
47601a344a2SDavid du Colombier cb = getbuf(CDEV(dev->ro.parent), CACHE_ADDR, Brd|Bres);
47701a344a2SDavid du Colombier ra = ((Cache*)cb->iobuf)->roraddr;
47801a344a2SDavid du Colombier break;
47901a344a2SDavid du Colombier }
48001a344a2SDavid du Colombier putbuf(cb);
48101a344a2SDavid du Colombier return ra;
48201a344a2SDavid du Colombier }
48301a344a2SDavid du Colombier
48401a344a2SDavid du Colombier Devsize
cwsize(Device * dev)48501a344a2SDavid du Colombier cwsize(Device *dev)
48601a344a2SDavid du Colombier {
48701a344a2SDavid du Colombier Iobuf *cb;
48801a344a2SDavid du Colombier Devsize fs;
48901a344a2SDavid du Colombier
49001a344a2SDavid du Colombier cb = getbuf(CDEV(dev), CACHE_ADDR, Brd|Bres);
49101a344a2SDavid du Colombier fs = ((Cache*)cb->iobuf)->fsize;
49201a344a2SDavid du Colombier putbuf(cb);
49301a344a2SDavid du Colombier return fs;
49401a344a2SDavid du Colombier }
49501a344a2SDavid du Colombier
49601a344a2SDavid du Colombier int
cwread(Device * dev,Off b,void * c)49701a344a2SDavid du Colombier cwread(Device *dev, Off b, void *c)
49801a344a2SDavid du Colombier {
49901a344a2SDavid du Colombier return cwio(dev, b, c, Oread) == Cerror;
50001a344a2SDavid du Colombier }
50101a344a2SDavid du Colombier
50201a344a2SDavid du Colombier int
cwwrite(Device * dev,Off b,void * c)50301a344a2SDavid du Colombier cwwrite(Device *dev, Off b, void *c)
50401a344a2SDavid du Colombier {
50501a344a2SDavid du Colombier return cwio(dev, b, c, Owrite) == Cerror;
50601a344a2SDavid du Colombier }
50701a344a2SDavid du Colombier
50801a344a2SDavid du Colombier int
roread(Device * dev,Off b,void * c)50901a344a2SDavid du Colombier roread(Device *dev, Off b, void *c)
51001a344a2SDavid du Colombier {
51101a344a2SDavid du Colombier Device *d;
51201a344a2SDavid du Colombier int s;
51301a344a2SDavid du Colombier
51401a344a2SDavid du Colombier /*
51501a344a2SDavid du Colombier * maybe better is to try buffer pool first
51601a344a2SDavid du Colombier */
51701a344a2SDavid du Colombier d = dev->ro.parent;
51801a344a2SDavid du Colombier if(d == 0 || d->type != Devcw ||
51901a344a2SDavid du Colombier d->private == 0 || RDEV(d) != dev) {
52001a344a2SDavid du Colombier print("bad rodev %Z\n", dev);
52101a344a2SDavid du Colombier return 1;
52201a344a2SDavid du Colombier }
52301a344a2SDavid du Colombier s = cwio(d, b, 0, Onone);
52401a344a2SDavid du Colombier if(s == Cdump || s == Cdump1 || s == Cread) {
52501a344a2SDavid du Colombier s = cwio(d, b, c, Oread);
52601a344a2SDavid du Colombier if(s == Cdump || s == Cdump1 || s == Cread) {
52701a344a2SDavid du Colombier if(cons.flags & roflag)
52801a344a2SDavid du Colombier print("roread: %Z %lld -> %Z(hit)\n",
52901a344a2SDavid du Colombier dev, (Wideoff)b, d);
53001a344a2SDavid du Colombier return 0;
53101a344a2SDavid du Colombier }
53201a344a2SDavid du Colombier }
53301a344a2SDavid du Colombier if(cons.flags & roflag)
53401a344a2SDavid du Colombier print("roread: %Z %lld -> %Z(miss)\n",
53501a344a2SDavid du Colombier dev, (Wideoff)b, WDEV(d));
53601a344a2SDavid du Colombier return devread(WDEV(d), b, c);
53701a344a2SDavid du Colombier }
53801a344a2SDavid du Colombier
53901a344a2SDavid du Colombier int
cwio(Device * dev,Off addr,void * buf,int opcode)54001a344a2SDavid du Colombier cwio(Device *dev, Off addr, void *buf, int opcode)
54101a344a2SDavid du Colombier {
54201a344a2SDavid du Colombier Iobuf *p, *p1, *p2, *cb;
54301a344a2SDavid du Colombier Cache *h;
54401a344a2SDavid du Colombier Bucket *b;
54501a344a2SDavid du Colombier Centry *c;
54601a344a2SDavid du Colombier Off bn, a1, a2, max, newmax;
54701a344a2SDavid du Colombier int state;
54801a344a2SDavid du Colombier Cw *cw;
54901a344a2SDavid du Colombier
55001a344a2SDavid du Colombier cw = dev->private;
55101a344a2SDavid du Colombier
55201a344a2SDavid du Colombier cb = getbuf(cw->cdev, CACHE_ADDR, Brd|Bres);
55301a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
55401a344a2SDavid du Colombier if(toytime() >= h->toytime) {
55501a344a2SDavid du Colombier cb->flags |= Bmod;
55601a344a2SDavid du Colombier h->toytime = toytime() + SECOND(30);
55701a344a2SDavid du Colombier h->time = time(nil);
55801a344a2SDavid du Colombier }
55901a344a2SDavid du Colombier
56001a344a2SDavid du Colombier if(addr < 0) {
56101a344a2SDavid du Colombier putbuf(cb);
56201a344a2SDavid du Colombier return Cerror;
56301a344a2SDavid du Colombier }
56401a344a2SDavid du Colombier
56501a344a2SDavid du Colombier bn = addr % h->msize;
56601a344a2SDavid du Colombier a1 = h->maddr + bn/BKPERBLK;
567698b102bSDavid du Colombier if (oldcachefmt)
56801a344a2SDavid du Colombier a2 = bn*CEPERBK + h->caddr;
569698b102bSDavid du Colombier else
570698b102bSDavid du Colombier a2 = bn + h->caddr;
57101a344a2SDavid du Colombier max = h->wmax;
57201a344a2SDavid du Colombier
57301a344a2SDavid du Colombier putbuf(cb);
57401a344a2SDavid du Colombier newmax = 0;
57501a344a2SDavid du Colombier
57601a344a2SDavid du Colombier p = getbuf(cw->cdev, a1, Brd|Bmod);
57701a344a2SDavid du Colombier if(!p || checktag(p, Tbuck, a1))
57801a344a2SDavid du Colombier panic("cwio: checktag c bucket");
57901a344a2SDavid du Colombier b = (Bucket*)p->iobuf + bn%BKPERBLK;
58001a344a2SDavid du Colombier
58101a344a2SDavid du Colombier c = getcentry(b, addr);
58201a344a2SDavid du Colombier if(c == 0) {
58301a344a2SDavid du Colombier putbuf(p);
58401a344a2SDavid du Colombier print("%Z disk cache bucket %lld is full\n",
58501a344a2SDavid du Colombier cw->cdev, (Wideoff)a1);
58601a344a2SDavid du Colombier return Cerror;
58701a344a2SDavid du Colombier }
588*e6d20ddfSDavid du Colombier if (oldcachefmt)
58901a344a2SDavid du Colombier a2 += c - b->entry;
590*e6d20ddfSDavid du Colombier else
591*e6d20ddfSDavid du Colombier a2 += (c - b->entry) * h->msize;
59201a344a2SDavid du Colombier
59301a344a2SDavid du Colombier state = c->state;
59401a344a2SDavid du Colombier switch(opcode) {
59501a344a2SDavid du Colombier default:
59601a344a2SDavid du Colombier goto bad;
59701a344a2SDavid du Colombier
59801a344a2SDavid du Colombier case Onone:
59901a344a2SDavid du Colombier break;
60001a344a2SDavid du Colombier
60101a344a2SDavid du Colombier case Oread:
60201a344a2SDavid du Colombier switch(state) {
60301a344a2SDavid du Colombier default:
60401a344a2SDavid du Colombier goto bad;
60501a344a2SDavid du Colombier
60601a344a2SDavid du Colombier case Cread:
60701a344a2SDavid du Colombier if(!devread(cw->cdev, a2, buf))
60801a344a2SDavid du Colombier break;
60901a344a2SDavid du Colombier c->state = Cnone;
61001a344a2SDavid du Colombier
61101a344a2SDavid du Colombier case Cnone:
61201a344a2SDavid du Colombier if(devread(cw->wdev, addr, buf)) {
61301a344a2SDavid du Colombier state = Cerror;
61401a344a2SDavid du Colombier break;
61501a344a2SDavid du Colombier }
61601a344a2SDavid du Colombier if(addr > max)
61701a344a2SDavid du Colombier newmax = addr;
61801a344a2SDavid du Colombier if(!devwrite(cw->cdev, a2, buf))
61901a344a2SDavid du Colombier c->state = Cread;
62001a344a2SDavid du Colombier break;
62101a344a2SDavid du Colombier
62201a344a2SDavid du Colombier case Cdirty:
62301a344a2SDavid du Colombier case Cdump:
62401a344a2SDavid du Colombier case Cdump1:
62501a344a2SDavid du Colombier case Cwrite:
62601a344a2SDavid du Colombier if(devread(cw->cdev, a2, buf))
62701a344a2SDavid du Colombier state = Cerror;
62801a344a2SDavid du Colombier break;
62901a344a2SDavid du Colombier }
63001a344a2SDavid du Colombier break;
63101a344a2SDavid du Colombier
63201a344a2SDavid du Colombier case Owrite:
63301a344a2SDavid du Colombier switch(state) {
63401a344a2SDavid du Colombier default:
63501a344a2SDavid du Colombier goto bad;
63601a344a2SDavid du Colombier
63701a344a2SDavid du Colombier case Cdump:
63801a344a2SDavid du Colombier case Cdump1:
63901a344a2SDavid du Colombier /*
64001a344a2SDavid du Colombier * this is hard part -- a dump block must be
64101a344a2SDavid du Colombier * sent to the worm if it is rewritten.
64201a344a2SDavid du Colombier * if this causes an error, there is no
64301a344a2SDavid du Colombier * place to save the dump1 data. the block
64401a344a2SDavid du Colombier * is just reclassified as 'dump1' (botch)
64501a344a2SDavid du Colombier */
64601a344a2SDavid du Colombier p1 = getbuf(devnone, Cwio1, 0);
64701a344a2SDavid du Colombier if(devread(cw->cdev, a2, p1->iobuf)) {
64801a344a2SDavid du Colombier putbuf(p1);
64901a344a2SDavid du Colombier print("cwio: write induced dump error - r cache\n");
65001a344a2SDavid du Colombier
65101a344a2SDavid du Colombier casenone:
65201a344a2SDavid du Colombier if(devwrite(cw->cdev, a2, buf)) {
65301a344a2SDavid du Colombier state = Cerror;
65401a344a2SDavid du Colombier break;
65501a344a2SDavid du Colombier }
65601a344a2SDavid du Colombier c->state = Cdump1;
65701a344a2SDavid du Colombier break;
65801a344a2SDavid du Colombier }
65901a344a2SDavid du Colombier if(devwrite(cw->wdev, addr, p1->iobuf)) {
66001a344a2SDavid du Colombier p2 = getbuf(devnone, Cwio2, 0);
66101a344a2SDavid du Colombier if(devread(cw->wdev, addr, p2->iobuf)) {
66201a344a2SDavid du Colombier putbuf(p1);
66301a344a2SDavid du Colombier putbuf(p2);
66401a344a2SDavid du Colombier print("cwio: write induced dump error - r+w worm\n");
66501a344a2SDavid du Colombier goto casenone;
66601a344a2SDavid du Colombier }
66701a344a2SDavid du Colombier if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) {
66801a344a2SDavid du Colombier putbuf(p1);
66901a344a2SDavid du Colombier putbuf(p2);
67001a344a2SDavid du Colombier print("cwio: write induced dump error - w worm\n");
67101a344a2SDavid du Colombier goto casenone;
67201a344a2SDavid du Colombier }
67301a344a2SDavid du Colombier putbuf(p2);
67401a344a2SDavid du Colombier }
67501a344a2SDavid du Colombier putbuf(p1);
67601a344a2SDavid du Colombier c->state = Cread;
67701a344a2SDavid du Colombier if(addr > max)
67801a344a2SDavid du Colombier newmax = addr;
67901a344a2SDavid du Colombier cw->ncopy++;
68001a344a2SDavid du Colombier
68101a344a2SDavid du Colombier case Cnone:
68201a344a2SDavid du Colombier case Cread:
68301a344a2SDavid du Colombier if(devwrite(cw->cdev, a2, buf)) {
68401a344a2SDavid du Colombier state = Cerror;
68501a344a2SDavid du Colombier break;
68601a344a2SDavid du Colombier }
68701a344a2SDavid du Colombier c->state = Cwrite;
68801a344a2SDavid du Colombier break;
68901a344a2SDavid du Colombier
69001a344a2SDavid du Colombier case Cdirty:
69101a344a2SDavid du Colombier case Cwrite:
69201a344a2SDavid du Colombier if(devwrite(cw->cdev, a2, buf))
69301a344a2SDavid du Colombier state = Cerror;
69401a344a2SDavid du Colombier break;
69501a344a2SDavid du Colombier }
69601a344a2SDavid du Colombier break;
69701a344a2SDavid du Colombier
69801a344a2SDavid du Colombier case Ogrow:
69901a344a2SDavid du Colombier if(state != Cnone) {
70001a344a2SDavid du Colombier print("%Z for block %lld cwgrow with state = %s\n",
70101a344a2SDavid du Colombier cw->cdev, (Wideoff)addr, cwnames[state]);
70201a344a2SDavid du Colombier break;
70301a344a2SDavid du Colombier }
70401a344a2SDavid du Colombier c->state = Cdirty;
70501a344a2SDavid du Colombier break;
70601a344a2SDavid du Colombier
70701a344a2SDavid du Colombier case Odump:
70801a344a2SDavid du Colombier if(state != Cdirty) { /* BOTCH */
70901a344a2SDavid du Colombier print("%Z for block %lld cwdump with state = %s\n",
71001a344a2SDavid du Colombier cw->cdev, (Wideoff)addr, cwnames[state]);
71101a344a2SDavid du Colombier break;
71201a344a2SDavid du Colombier }
71301a344a2SDavid du Colombier c->state = Cdump;
71401a344a2SDavid du Colombier cw->ndump++; /* only called from dump command */
71501a344a2SDavid du Colombier break;
71601a344a2SDavid du Colombier
71701a344a2SDavid du Colombier case Orele:
71801a344a2SDavid du Colombier if(state != Cwrite) {
71901a344a2SDavid du Colombier if(state != Cdump1)
72001a344a2SDavid du Colombier print("%Z for block %lld cwrele with state = %s\n",
72101a344a2SDavid du Colombier cw->cdev, (Wideoff)addr, cwnames[state]);
72201a344a2SDavid du Colombier break;
72301a344a2SDavid du Colombier }
72401a344a2SDavid du Colombier c->state = Cnone;
72501a344a2SDavid du Colombier break;
72601a344a2SDavid du Colombier
72701a344a2SDavid du Colombier case Ofree:
72801a344a2SDavid du Colombier if(state == Cwrite || state == Cread)
72901a344a2SDavid du Colombier c->state = Cnone;
73001a344a2SDavid du Colombier break;
73101a344a2SDavid du Colombier }
73201a344a2SDavid du Colombier if(DEBUG)
73301a344a2SDavid du Colombier print("cwio: %Z %lld s=%s o=%s ns=%s\n",
73401a344a2SDavid du Colombier dev, (Wideoff)addr, cwnames[state],
73501a344a2SDavid du Colombier cwnames[opcode],
73601a344a2SDavid du Colombier cwnames[c->state]);
73701a344a2SDavid du Colombier putbuf(p);
73801a344a2SDavid du Colombier if(newmax) {
73901a344a2SDavid du Colombier cb = getbuf(cw->cdev, CACHE_ADDR, Brd|Bmod|Bres);
74001a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
74101a344a2SDavid du Colombier if(newmax > h->wmax)
74201a344a2SDavid du Colombier h->wmax = newmax;
74301a344a2SDavid du Colombier putbuf(cb);
74401a344a2SDavid du Colombier }
74501a344a2SDavid du Colombier return state;
74601a344a2SDavid du Colombier
74701a344a2SDavid du Colombier bad:
74801a344a2SDavid du Colombier print("%Z block %lld cw state = %s; cw opcode = %s",
74901a344a2SDavid du Colombier dev, (Wideoff)addr, cwnames[state], cwnames[opcode]);
75001a344a2SDavid du Colombier return Cerror;
75101a344a2SDavid du Colombier }
75201a344a2SDavid du Colombier
75301a344a2SDavid du Colombier
75401a344a2SDavid du Colombier int
cwgrow(Device * dev,Superb * sb,int uid)75501a344a2SDavid du Colombier cwgrow(Device *dev, Superb *sb, int uid)
75601a344a2SDavid du Colombier {
75701a344a2SDavid du Colombier char str[NAMELEN];
75801a344a2SDavid du Colombier Iobuf *cb;
75901a344a2SDavid du Colombier Cache *h;
76001a344a2SDavid du Colombier Filsys *filsys;
76101a344a2SDavid du Colombier Off fs, nfs, ws;
76201a344a2SDavid du Colombier
76301a344a2SDavid du Colombier cb = getbuf(CDEV(dev), CACHE_ADDR, Brd|Bmod|Bres);
76401a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
76501a344a2SDavid du Colombier ws = h->wsize;
76601a344a2SDavid du Colombier fs = h->fsize;
76701a344a2SDavid du Colombier if(fs >= ws)
76801a344a2SDavid du Colombier return 0;
76901a344a2SDavid du Colombier nfs = fs + ADDFREE;
77001a344a2SDavid du Colombier if(nfs >= ws)
77101a344a2SDavid du Colombier nfs = ws;
77201a344a2SDavid du Colombier h->fsize = nfs;
77301a344a2SDavid du Colombier putbuf(cb);
77401a344a2SDavid du Colombier
77501a344a2SDavid du Colombier sb->fsize = nfs;
77601a344a2SDavid du Colombier filsys = dev2fs(dev);
77701a344a2SDavid du Colombier if (filsys == nil)
77801a344a2SDavid du Colombier print("%Z", dev);
77901a344a2SDavid du Colombier else
78001a344a2SDavid du Colombier print("%s", filsys->name);
78101a344a2SDavid du Colombier uidtostr(str, uid, 1);
78201a344a2SDavid du Colombier print(" grow from %lld to %lld limit %lld by %s uid=%d\n",
78301a344a2SDavid du Colombier (Wideoff)fs, (Wideoff)nfs, (Wideoff)ws, str, uid);
78401a344a2SDavid du Colombier for(nfs--; nfs>=fs; nfs--)
78501a344a2SDavid du Colombier switch(cwio(dev, nfs, 0, Ogrow)) {
78601a344a2SDavid du Colombier case Cerror:
78701a344a2SDavid du Colombier return 0;
78801a344a2SDavid du Colombier case Cnone:
78901a344a2SDavid du Colombier addfree(dev, nfs, sb);
79001a344a2SDavid du Colombier }
79101a344a2SDavid du Colombier return 1;
79201a344a2SDavid du Colombier }
79301a344a2SDavid du Colombier
79401a344a2SDavid du Colombier int
cwfree(Device * dev,Off addr)79501a344a2SDavid du Colombier cwfree(Device *dev, Off addr)
79601a344a2SDavid du Colombier {
79701a344a2SDavid du Colombier int state;
79801a344a2SDavid du Colombier
79901a344a2SDavid du Colombier if(dev->type == Devcw) {
80001a344a2SDavid du Colombier state = cwio(dev, addr, 0, Ofree);
80101a344a2SDavid du Colombier if(state != Cdirty)
80201a344a2SDavid du Colombier return 1; /* do not put in freelist */
80301a344a2SDavid du Colombier }
80401a344a2SDavid du Colombier return 0; /* put in freelist */
80501a344a2SDavid du Colombier }
80601a344a2SDavid du Colombier
80701a344a2SDavid du Colombier #ifdef unused
80801a344a2SDavid du Colombier int
bktcheck(Bucket * b)80901a344a2SDavid du Colombier bktcheck(Bucket *b)
81001a344a2SDavid du Colombier {
81101a344a2SDavid du Colombier Centry *c, *c1, *c2, *ce;
81201a344a2SDavid du Colombier int err;
81301a344a2SDavid du Colombier
81401a344a2SDavid du Colombier err = 0;
81501a344a2SDavid du Colombier if(b->agegen < CEPERBK || b->agegen > MAXAGE) {
81601a344a2SDavid du Colombier print("agegen %ld\n", b->agegen);
81701a344a2SDavid du Colombier err = 1;
81801a344a2SDavid du Colombier }
81901a344a2SDavid du Colombier
82001a344a2SDavid du Colombier ce = b->entry + CEPERBK;
82101a344a2SDavid du Colombier c1 = 0; /* lowest age last pass */
82201a344a2SDavid du Colombier for(;;) {
82301a344a2SDavid du Colombier c2 = 0; /* lowest age this pass */
82401a344a2SDavid du Colombier for(c = b->entry; c < ce; c++) {
82501a344a2SDavid du Colombier if(c1 != 0 && c != c1) {
82601a344a2SDavid du Colombier if(c->age == c1->age) {
82701a344a2SDavid du Colombier print("same age %d\n", c->age);
82801a344a2SDavid du Colombier err = 1;
82901a344a2SDavid du Colombier }
83001a344a2SDavid du Colombier if(c1->waddr == c->waddr)
83101a344a2SDavid du Colombier if(c1->state != Cnone)
83201a344a2SDavid du Colombier if(c->state != Cnone) {
83301a344a2SDavid du Colombier print("same waddr %lld\n",
83401a344a2SDavid du Colombier (Wideoff)c->waddr);
83501a344a2SDavid du Colombier err = 1;
83601a344a2SDavid du Colombier }
83701a344a2SDavid du Colombier }
83801a344a2SDavid du Colombier if(c1 != 0 && c->age <= c1->age)
83901a344a2SDavid du Colombier continue;
84001a344a2SDavid du Colombier if(c2 == 0 || c->age < c2->age)
84101a344a2SDavid du Colombier c2 = c;
84201a344a2SDavid du Colombier }
84301a344a2SDavid du Colombier if(c2 == 0)
84401a344a2SDavid du Colombier break;
84501a344a2SDavid du Colombier c1 = c2;
84601a344a2SDavid du Colombier if(c1->age >= b->agegen) {
84701a344a2SDavid du Colombier print("age >= generator %d %ld\n", c1->age, b->agegen);
84801a344a2SDavid du Colombier err = 1;
84901a344a2SDavid du Colombier }
85001a344a2SDavid du Colombier }
85101a344a2SDavid du Colombier return err;
85201a344a2SDavid du Colombier }
85301a344a2SDavid du Colombier #endif
85401a344a2SDavid du Colombier
85501a344a2SDavid du Colombier void
resequence(Bucket * b)85601a344a2SDavid du Colombier resequence(Bucket *b)
85701a344a2SDavid du Colombier {
85801a344a2SDavid du Colombier Centry *c, *ce, *cr;
85901a344a2SDavid du Colombier int age, i;
86001a344a2SDavid du Colombier
86101a344a2SDavid du Colombier ce = b->entry + CEPERBK;
86201a344a2SDavid du Colombier for(c = b->entry; c < ce; c++) {
86301a344a2SDavid du Colombier c->age += CEPERBK;
86401a344a2SDavid du Colombier if(c->age < CEPERBK)
86501a344a2SDavid du Colombier c->age = MAXAGE;
86601a344a2SDavid du Colombier }
86701a344a2SDavid du Colombier b->agegen += CEPERBK;
86801a344a2SDavid du Colombier
86901a344a2SDavid du Colombier age = 0;
87001a344a2SDavid du Colombier for(i=0;; i++) {
87101a344a2SDavid du Colombier cr = 0;
87201a344a2SDavid du Colombier for(c = b->entry; c < ce; c++) {
87301a344a2SDavid du Colombier if(c->age < i)
87401a344a2SDavid du Colombier continue;
87501a344a2SDavid du Colombier if(cr == 0 || c->age < age) {
87601a344a2SDavid du Colombier cr = c;
87701a344a2SDavid du Colombier age = c->age;
87801a344a2SDavid du Colombier }
87901a344a2SDavid du Colombier }
88001a344a2SDavid du Colombier if(cr == 0)
88101a344a2SDavid du Colombier break;
88201a344a2SDavid du Colombier cr->age = i;
88301a344a2SDavid du Colombier }
88401a344a2SDavid du Colombier b->agegen = i;
88501a344a2SDavid du Colombier cons.nreseq++;
88601a344a2SDavid du Colombier }
88701a344a2SDavid du Colombier
88801a344a2SDavid du Colombier Centry*
getcentry(Bucket * b,Off addr)88901a344a2SDavid du Colombier getcentry(Bucket *b, Off addr)
89001a344a2SDavid du Colombier {
89101a344a2SDavid du Colombier Centry *c, *ce, *cr;
89201a344a2SDavid du Colombier int s, age;
89301a344a2SDavid du Colombier
89401a344a2SDavid du Colombier /*
89501a344a2SDavid du Colombier * search for cache hit
89601a344a2SDavid du Colombier * find oldest block as byproduct
89701a344a2SDavid du Colombier */
89801a344a2SDavid du Colombier ce = b->entry + CEPERBK;
89901a344a2SDavid du Colombier age = 0;
90001a344a2SDavid du Colombier cr = 0;
90101a344a2SDavid du Colombier for(c = b->entry; c < ce; c++) {
90201a344a2SDavid du Colombier s = c->state;
90301a344a2SDavid du Colombier if(s == Cnone) {
90401a344a2SDavid du Colombier cr = c;
90501a344a2SDavid du Colombier age = 0;
90601a344a2SDavid du Colombier continue;
90701a344a2SDavid du Colombier }
90801a344a2SDavid du Colombier if(c->waddr == addr)
90901a344a2SDavid du Colombier goto found;
91001a344a2SDavid du Colombier if(s == Cread)
91101a344a2SDavid du Colombier if(cr == 0 || c->age < age) {
91201a344a2SDavid du Colombier cr = c;
91301a344a2SDavid du Colombier age = c->age;
91401a344a2SDavid du Colombier }
91501a344a2SDavid du Colombier }
91601a344a2SDavid du Colombier
91701a344a2SDavid du Colombier /*
91801a344a2SDavid du Colombier * remap entry
91901a344a2SDavid du Colombier */
92001a344a2SDavid du Colombier c = cr;
92101a344a2SDavid du Colombier if(c == 0)
92201a344a2SDavid du Colombier return 0; /* bucket is full */
92301a344a2SDavid du Colombier
92401a344a2SDavid du Colombier c->state = Cnone;
92501a344a2SDavid du Colombier c->waddr = addr;
92601a344a2SDavid du Colombier
92701a344a2SDavid du Colombier found:
92801a344a2SDavid du Colombier /*
92901a344a2SDavid du Colombier * update the age to get filo cache.
93001a344a2SDavid du Colombier * small number in age means old
93101a344a2SDavid du Colombier */
93201a344a2SDavid du Colombier if(!cons.noage || c->state == Cnone) {
93301a344a2SDavid du Colombier age = b->agegen;
93401a344a2SDavid du Colombier c->age = age;
93501a344a2SDavid du Colombier age++;
93601a344a2SDavid du Colombier b->agegen = age;
93701a344a2SDavid du Colombier if(age < 0 || age >= MAXAGE)
93801a344a2SDavid du Colombier resequence(b);
93901a344a2SDavid du Colombier }
94001a344a2SDavid du Colombier return c;
94101a344a2SDavid du Colombier }
94201a344a2SDavid du Colombier
94301a344a2SDavid du Colombier /*
94401a344a2SDavid du Colombier * ream the cache
94501a344a2SDavid du Colombier * calculate new buckets
94601a344a2SDavid du Colombier */
94701a344a2SDavid du Colombier Iobuf*
cacheinit(Device * dev)94801a344a2SDavid du Colombier cacheinit(Device *dev)
94901a344a2SDavid du Colombier {
95001a344a2SDavid du Colombier Iobuf *cb, *p;
95101a344a2SDavid du Colombier Cache *h;
95201a344a2SDavid du Colombier Device *cdev;
95301a344a2SDavid du Colombier Off m;
95401a344a2SDavid du Colombier
95501a344a2SDavid du Colombier print("cache init %Z\n", dev);
95601a344a2SDavid du Colombier cdev = CDEV(dev);
95701a344a2SDavid du Colombier devinit(cdev);
95801a344a2SDavid du Colombier
95901a344a2SDavid du Colombier cb = getbuf(cdev, CACHE_ADDR, Bmod|Bres);
96001a344a2SDavid du Colombier memset(cb->iobuf, 0, RBUFSIZE);
96101a344a2SDavid du Colombier settag(cb, Tcache, QPSUPER);
96201a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
96301a344a2SDavid du Colombier
96401a344a2SDavid du Colombier /*
96501a344a2SDavid du Colombier * calculate csize such that
96601a344a2SDavid du Colombier * tsize = msize/BKPERBLK + csize and
96701a344a2SDavid du Colombier * msize = csize/CEPERBK
96801a344a2SDavid du Colombier */
96901a344a2SDavid du Colombier h->maddr = CACHE_ADDR + 1;
97001a344a2SDavid du Colombier m = devsize(cdev) - h->maddr;
97101a344a2SDavid du Colombier h->csize = ((Devsize)(m-1) * CEPERBK*BKPERBLK) / (CEPERBK*BKPERBLK+1);
97201a344a2SDavid du Colombier h->msize = h->csize/CEPERBK - 5;
97301a344a2SDavid du Colombier while(!prime(h->msize))
97401a344a2SDavid du Colombier h->msize--;
97501a344a2SDavid du Colombier h->csize = h->msize*CEPERBK;
97601a344a2SDavid du Colombier h->caddr = h->maddr + (h->msize+BKPERBLK-1)/BKPERBLK;
97701a344a2SDavid du Colombier h->wsize = devsize(WDEV(dev));
97801a344a2SDavid du Colombier
97901a344a2SDavid du Colombier if(h->msize <= 0)
98001a344a2SDavid du Colombier panic("cache too small");
98101a344a2SDavid du Colombier if(h->caddr + h->csize > m)
98201a344a2SDavid du Colombier panic("cache size error");
98301a344a2SDavid du Colombier
98401a344a2SDavid du Colombier /*
98501a344a2SDavid du Colombier * setup cache map
98601a344a2SDavid du Colombier */
98701a344a2SDavid du Colombier for(m=h->maddr; m<h->caddr; m++) {
98801a344a2SDavid du Colombier p = getbuf(cdev, m, Bmod);
98901a344a2SDavid du Colombier memset(p->iobuf, 0, RBUFSIZE);
99001a344a2SDavid du Colombier settag(p, Tbuck, m);
99101a344a2SDavid du Colombier putbuf(p);
99201a344a2SDavid du Colombier }
99301a344a2SDavid du Colombier print("done cacheinit\n");
99401a344a2SDavid du Colombier return cb;
99501a344a2SDavid du Colombier }
99601a344a2SDavid du Colombier
99701a344a2SDavid du Colombier Off
getstartsb(Device * dev)99801a344a2SDavid du Colombier getstartsb(Device *dev)
99901a344a2SDavid du Colombier {
100001a344a2SDavid du Colombier Filsys *f;
100101a344a2SDavid du Colombier Startsb *s;
100201a344a2SDavid du Colombier
100301a344a2SDavid du Colombier for(f=filsys; f->name; f++)
100401a344a2SDavid du Colombier if(devcmpr(f->dev, dev) == 0) {
100501a344a2SDavid du Colombier for(s=startsb; s->name; s++)
100601a344a2SDavid du Colombier if(strcmp(f->name, s->name) == 0)
100701a344a2SDavid du Colombier return s->startsb;
100801a344a2SDavid du Colombier print(
100901a344a2SDavid du Colombier "getstartsb: no special starting superblock for %Z %s\n",
101001a344a2SDavid du Colombier dev, f->name);
101101a344a2SDavid du Colombier return FIRST;
101201a344a2SDavid du Colombier }
101301a344a2SDavid du Colombier print("getstartsb: no filsys for device %Z\n", dev);
101401a344a2SDavid du Colombier return FIRST;
101501a344a2SDavid du Colombier }
101601a344a2SDavid du Colombier
101701a344a2SDavid du Colombier /*
101801a344a2SDavid du Colombier * ream the cache
101901a344a2SDavid du Colombier * calculate new buckets
102001a344a2SDavid du Colombier * get superblock from
102101a344a2SDavid du Colombier * last worm dump block.
102201a344a2SDavid du Colombier */
102301a344a2SDavid du Colombier void
cwrecover(Device * dev)102401a344a2SDavid du Colombier cwrecover(Device *dev)
102501a344a2SDavid du Colombier {
102601a344a2SDavid du Colombier Iobuf *p, *cb;
102701a344a2SDavid du Colombier Cache *h;
102801a344a2SDavid du Colombier Superb *s;
102901a344a2SDavid du Colombier Off m, baddr;
103001a344a2SDavid du Colombier Device *wdev;
103101a344a2SDavid du Colombier
103201a344a2SDavid du Colombier // print("cwrecover %Z\n", dev); // DEBUG
103301a344a2SDavid du Colombier cwinit1(dev);
103401a344a2SDavid du Colombier wdev = WDEV(dev);
103501a344a2SDavid du Colombier
103601a344a2SDavid du Colombier p = getbuf(devnone, Cwxx1, 0);
103701a344a2SDavid du Colombier s = (Superb*)p->iobuf;
103801a344a2SDavid du Colombier baddr = 0;
103901a344a2SDavid du Colombier m = getstartsb(dev);
104001a344a2SDavid du Colombier localconfinit();
104101a344a2SDavid du Colombier if(conf.firstsb)
104201a344a2SDavid du Colombier m = conf.firstsb;
104301a344a2SDavid du Colombier for(;;) {
104401a344a2SDavid du Colombier memset(p->iobuf, 0, RBUFSIZE);
104501a344a2SDavid du Colombier if(devread(wdev, m, p->iobuf) ||
104601a344a2SDavid du Colombier checktag(p, Tsuper, QPSUPER))
104701a344a2SDavid du Colombier break;
104801a344a2SDavid du Colombier baddr = m;
104901a344a2SDavid du Colombier m = s->next;
105001a344a2SDavid du Colombier print("dump %lld is good; %lld next\n", (Wideoff)baddr, (Wideoff)m);
105101a344a2SDavid du Colombier if(baddr == conf.recovsb)
105201a344a2SDavid du Colombier break;
105301a344a2SDavid du Colombier }
105401a344a2SDavid du Colombier putbuf(p);
105501a344a2SDavid du Colombier if(!baddr)
105601a344a2SDavid du Colombier panic("recover: no superblock");
105701a344a2SDavid du Colombier
105801a344a2SDavid du Colombier p = getbuf(wdev, baddr, Brd);
105901a344a2SDavid du Colombier s = (Superb*)p->iobuf;
106001a344a2SDavid du Colombier
106101a344a2SDavid du Colombier cb = cacheinit(dev);
106201a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
106301a344a2SDavid du Colombier h->sbaddr = baddr;
106401a344a2SDavid du Colombier h->cwraddr = s->cwraddr;
106501a344a2SDavid du Colombier h->roraddr = s->roraddr;
106601a344a2SDavid du Colombier h->fsize = s->fsize + 100; /* this must be conservative */
106701a344a2SDavid du Colombier if(conf.recovcw)
106801a344a2SDavid du Colombier h->cwraddr = conf.recovcw;
106901a344a2SDavid du Colombier if(conf.recovro)
107001a344a2SDavid du Colombier h->roraddr = conf.recovro;
107101a344a2SDavid du Colombier
107201a344a2SDavid du Colombier putbuf(cb);
107301a344a2SDavid du Colombier putbuf(p);
107401a344a2SDavid du Colombier
107501a344a2SDavid du Colombier p = getbuf(dev, baddr, Brd|Bmod);
107601a344a2SDavid du Colombier s = (Superb*)p->iobuf;
107701a344a2SDavid du Colombier
107801a344a2SDavid du Colombier memset(&s->fbuf, 0, sizeof(s->fbuf));
107901a344a2SDavid du Colombier s->fbuf.free[0] = 0;
108001a344a2SDavid du Colombier s->fbuf.nfree = 1;
108101a344a2SDavid du Colombier s->tfree = 0;
108201a344a2SDavid du Colombier if(conf.recovcw)
108301a344a2SDavid du Colombier s->cwraddr = conf.recovcw;
108401a344a2SDavid du Colombier if(conf.recovro)
108501a344a2SDavid du Colombier s->roraddr = conf.recovro;
108601a344a2SDavid du Colombier
108701a344a2SDavid du Colombier putbuf(p);
108801a344a2SDavid du Colombier print("done recover\n");
108901a344a2SDavid du Colombier }
109001a344a2SDavid du Colombier
109101a344a2SDavid du Colombier /*
109201a344a2SDavid du Colombier * ream the cache
109301a344a2SDavid du Colombier * calculate new buckets
109401a344a2SDavid du Colombier * initialize superblock.
109501a344a2SDavid du Colombier */
109601a344a2SDavid du Colombier void
cwream(Device * dev)109701a344a2SDavid du Colombier cwream(Device *dev)
109801a344a2SDavid du Colombier {
109901a344a2SDavid du Colombier Iobuf *p, *cb;
110001a344a2SDavid du Colombier Cache *h;
110101a344a2SDavid du Colombier Superb *s;
110201a344a2SDavid du Colombier Off m, baddr;
110301a344a2SDavid du Colombier Device *cdev;
110401a344a2SDavid du Colombier
110501a344a2SDavid du Colombier print("cwream %Z\n", dev);
110601a344a2SDavid du Colombier cwinit1(dev);
110701a344a2SDavid du Colombier cdev = CDEV(dev);
110801a344a2SDavid du Colombier devinit(cdev);
110901a344a2SDavid du Colombier
111001a344a2SDavid du Colombier baddr = FIRST; /* baddr = super addr
111101a344a2SDavid du Colombier baddr+1 = cw root
111201a344a2SDavid du Colombier baddr+2 = ro root
111301a344a2SDavid du Colombier baddr+3 = reserved next superblock */
111401a344a2SDavid du Colombier
111501a344a2SDavid du Colombier cb = cacheinit(dev);
111601a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
111701a344a2SDavid du Colombier
111801a344a2SDavid du Colombier h->sbaddr = baddr;
111901a344a2SDavid du Colombier h->cwraddr = baddr+1;
112001a344a2SDavid du Colombier h->roraddr = baddr+2;
112101a344a2SDavid du Colombier h->fsize = 0; /* prevents superream from freeing */
112201a344a2SDavid du Colombier
112301a344a2SDavid du Colombier putbuf(cb);
112401a344a2SDavid du Colombier
112501a344a2SDavid du Colombier for(m=0; m<3; m++)
112601a344a2SDavid du Colombier cwio(dev, baddr+m, 0, Ogrow);
112701a344a2SDavid du Colombier superream(dev, baddr);
112801a344a2SDavid du Colombier rootream(dev, baddr+1); /* cw root */
112901a344a2SDavid du Colombier rootream(dev, baddr+2); /* ro root */
113001a344a2SDavid du Colombier
113101a344a2SDavid du Colombier cb = getbuf(cdev, CACHE_ADDR, Brd|Bmod|Bres);
113201a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
113301a344a2SDavid du Colombier h->fsize = baddr+4;
113401a344a2SDavid du Colombier putbuf(cb);
113501a344a2SDavid du Colombier
113601a344a2SDavid du Colombier p = getbuf(dev, baddr, Brd|Bmod|Bimm);
113701a344a2SDavid du Colombier s = (Superb*)p->iobuf;
113801a344a2SDavid du Colombier s->last = baddr;
113901a344a2SDavid du Colombier s->cwraddr = baddr+1;
114001a344a2SDavid du Colombier s->roraddr = baddr+2;
114101a344a2SDavid du Colombier s->next = baddr+3;
114201a344a2SDavid du Colombier s->fsize = baddr+4;
114301a344a2SDavid du Colombier putbuf(p);
114401a344a2SDavid du Colombier
114501a344a2SDavid du Colombier for(m=0; m<3; m++)
114601a344a2SDavid du Colombier cwio(dev, baddr+m, 0, Odump);
114701a344a2SDavid du Colombier }
114801a344a2SDavid du Colombier
114901a344a2SDavid du Colombier Off
rewalk1(Cw * cw,Off addr,int slot,Wpath * up)115001a344a2SDavid du Colombier rewalk1(Cw *cw, Off addr, int slot, Wpath *up)
115101a344a2SDavid du Colombier {
115201a344a2SDavid du Colombier Iobuf *p, *p1;
115301a344a2SDavid du Colombier Dentry *d;
115401a344a2SDavid du Colombier
115501a344a2SDavid du Colombier if(up == 0)
115601a344a2SDavid du Colombier return cwraddr(cw->dev);
115701a344a2SDavid du Colombier up->addr = rewalk1(cw, up->addr, up->slot, up->up);
115801a344a2SDavid du Colombier p = getbuf(cw->dev, up->addr, Brd|Bmod);
115901a344a2SDavid du Colombier d = getdir(p, up->slot);
116001a344a2SDavid du Colombier if(!d || !(d->mode & DALLOC)) {
116101a344a2SDavid du Colombier print("rewalk1 1\n");
116201a344a2SDavid du Colombier if(p)
116301a344a2SDavid du Colombier putbuf(p);
116401a344a2SDavid du Colombier return addr;
116501a344a2SDavid du Colombier }
116601a344a2SDavid du Colombier p1 = dnodebuf(p, d, slot/DIRPERBUF, 0, 0);
116701a344a2SDavid du Colombier if(!p1) {
116801a344a2SDavid du Colombier print("rewalk1 2\n");
116901a344a2SDavid du Colombier if(p)
117001a344a2SDavid du Colombier putbuf(p);
117101a344a2SDavid du Colombier return addr;
117201a344a2SDavid du Colombier }
117301a344a2SDavid du Colombier if(DEBUG)
117401a344a2SDavid du Colombier print("rewalk1 %lld to %lld \"%s\"\n",
117501a344a2SDavid du Colombier (Wideoff)addr, (Wideoff)p1->addr, d->name);
117601a344a2SDavid du Colombier addr = p1->addr;
117701a344a2SDavid du Colombier p1->flags |= Bmod;
117801a344a2SDavid du Colombier putbuf(p1);
117901a344a2SDavid du Colombier putbuf(p);
118001a344a2SDavid du Colombier return addr;
118101a344a2SDavid du Colombier }
118201a344a2SDavid du Colombier
118301a344a2SDavid du Colombier Off
rewalk2(Cw * cw,Off addr,int slot,Wpath * up)118401a344a2SDavid du Colombier rewalk2(Cw *cw, Off addr, int slot, Wpath *up)
118501a344a2SDavid du Colombier {
118601a344a2SDavid du Colombier Iobuf *p, *p1;
118701a344a2SDavid du Colombier Dentry *d;
118801a344a2SDavid du Colombier
118901a344a2SDavid du Colombier if(up == 0)
119001a344a2SDavid du Colombier return cwraddr(cw->rodev);
119101a344a2SDavid du Colombier up->addr = rewalk2(cw, up->addr, up->slot, up->up);
119201a344a2SDavid du Colombier p = getbuf(cw->rodev, up->addr, Brd);
119301a344a2SDavid du Colombier d = getdir(p, up->slot);
119401a344a2SDavid du Colombier if(!d || !(d->mode & DALLOC)) {
119501a344a2SDavid du Colombier print("rewalk2 1\n");
119601a344a2SDavid du Colombier if(p)
119701a344a2SDavid du Colombier putbuf(p);
119801a344a2SDavid du Colombier return addr;
119901a344a2SDavid du Colombier }
120001a344a2SDavid du Colombier p1 = dnodebuf(p, d, slot/DIRPERBUF, 0, 0);
120101a344a2SDavid du Colombier if(!p1) {
120201a344a2SDavid du Colombier print("rewalk2 2\n");
120301a344a2SDavid du Colombier if(p)
120401a344a2SDavid du Colombier putbuf(p);
120501a344a2SDavid du Colombier return addr;
120601a344a2SDavid du Colombier }
120701a344a2SDavid du Colombier if(DEBUG)
120801a344a2SDavid du Colombier print("rewalk2 %lld to %lld \"%s\"\n",
120901a344a2SDavid du Colombier (Wideoff)addr, (Wideoff)p1->addr, d->name);
121001a344a2SDavid du Colombier addr = p1->addr;
121101a344a2SDavid du Colombier putbuf(p1);
121201a344a2SDavid du Colombier putbuf(p);
121301a344a2SDavid du Colombier return addr;
121401a344a2SDavid du Colombier }
121501a344a2SDavid du Colombier
121601a344a2SDavid du Colombier void
rewalk(Cw * cw)121701a344a2SDavid du Colombier rewalk(Cw *cw)
121801a344a2SDavid du Colombier {
121901a344a2SDavid du Colombier int h;
122001a344a2SDavid du Colombier File *f;
122101a344a2SDavid du Colombier
122201a344a2SDavid du Colombier for(h=0; h<nelem(flist); h++)
122301a344a2SDavid du Colombier for(f=flist[h]; f; f=f->next) {
122401a344a2SDavid du Colombier if(!f->fs)
122501a344a2SDavid du Colombier continue;
122601a344a2SDavid du Colombier if(cw->dev == f->fs->dev)
122701a344a2SDavid du Colombier f->addr = rewalk1(cw, f->addr, f->slot, f->wpath);
122801a344a2SDavid du Colombier else
122901a344a2SDavid du Colombier if(cw->rodev == f->fs->dev)
123001a344a2SDavid du Colombier f->addr = rewalk2(cw, f->addr, f->slot, f->wpath);
123101a344a2SDavid du Colombier }
123201a344a2SDavid du Colombier }
123301a344a2SDavid du Colombier
123401a344a2SDavid du Colombier Off
split(Cw * cw,Iobuf * p,Off addr)123501a344a2SDavid du Colombier split(Cw *cw, Iobuf *p, Off addr)
123601a344a2SDavid du Colombier {
123701a344a2SDavid du Colombier Off na;
123801a344a2SDavid du Colombier int state;
123901a344a2SDavid du Colombier
124001a344a2SDavid du Colombier na = 0;
124101a344a2SDavid du Colombier if(p && (p->flags & Bmod)) {
124201a344a2SDavid du Colombier p->flags |= Bimm;
124301a344a2SDavid du Colombier putbuf(p);
124401a344a2SDavid du Colombier p = 0;
124501a344a2SDavid du Colombier }
124601a344a2SDavid du Colombier state = cwio(cw->dev, addr, 0, Onone); /* read the state (twice?) */
124701a344a2SDavid du Colombier switch(state) {
124801a344a2SDavid du Colombier default:
124901a344a2SDavid du Colombier panic("split: unknown state %s", cwnames[state]);
125001a344a2SDavid du Colombier
125101a344a2SDavid du Colombier case Cerror:
125201a344a2SDavid du Colombier case Cnone:
125301a344a2SDavid du Colombier case Cdump:
125401a344a2SDavid du Colombier case Cread:
125501a344a2SDavid du Colombier break;
125601a344a2SDavid du Colombier
125701a344a2SDavid du Colombier case Cdump1:
125801a344a2SDavid du Colombier case Cwrite:
125901a344a2SDavid du Colombier /*
126001a344a2SDavid du Colombier * botch.. could be done by relabeling
126101a344a2SDavid du Colombier */
126201a344a2SDavid du Colombier if(!p) {
126301a344a2SDavid du Colombier p = getbuf(cw->dev, addr, Brd);
126401a344a2SDavid du Colombier if(!p) {
126501a344a2SDavid du Colombier print("split: null getbuf\n");
126601a344a2SDavid du Colombier break;
126701a344a2SDavid du Colombier }
126801a344a2SDavid du Colombier }
126901a344a2SDavid du Colombier na = cw->fsize;
127001a344a2SDavid du Colombier cw->fsize = na+1;
127101a344a2SDavid du Colombier cwio(cw->dev, na, 0, Ogrow);
127201a344a2SDavid du Colombier cwio(cw->dev, na, p->iobuf, Owrite);
127301a344a2SDavid du Colombier cwio(cw->dev, na, 0, Odump);
127401a344a2SDavid du Colombier cwio(cw->dev, addr, 0, Orele);
127501a344a2SDavid du Colombier break;
127601a344a2SDavid du Colombier
127701a344a2SDavid du Colombier case Cdirty:
127801a344a2SDavid du Colombier cwio(cw->dev, addr, 0, Odump);
127901a344a2SDavid du Colombier break;
128001a344a2SDavid du Colombier }
128101a344a2SDavid du Colombier if(p)
128201a344a2SDavid du Colombier putbuf(p);
128301a344a2SDavid du Colombier return na;
128401a344a2SDavid du Colombier }
128501a344a2SDavid du Colombier
128601a344a2SDavid du Colombier int
isdirty(Cw * cw,Iobuf * p,Off addr,int tag)128701a344a2SDavid du Colombier isdirty(Cw *cw, Iobuf *p, Off addr, int tag)
128801a344a2SDavid du Colombier {
128901a344a2SDavid du Colombier int s;
129001a344a2SDavid du Colombier
129101a344a2SDavid du Colombier if(p && (p->flags & Bmod))
129201a344a2SDavid du Colombier return 1;
129301a344a2SDavid du Colombier s = cwio(cw->dev, addr, 0, Onone);
129401a344a2SDavid du Colombier if(s == Cdirty || s == Cwrite)
129501a344a2SDavid du Colombier return 1;
129601a344a2SDavid du Colombier if(tag >= Tind1 && tag <= Tmaxind)
129701a344a2SDavid du Colombier /* botch, get these modified */
129801a344a2SDavid du Colombier if(s != Cnone)
129901a344a2SDavid du Colombier return 1;
130001a344a2SDavid du Colombier return 0;
130101a344a2SDavid du Colombier }
130201a344a2SDavid du Colombier
130301a344a2SDavid du Colombier Off
cwrecur(Cw * cw,Off addr,int tag,int tag1,long qp)130401a344a2SDavid du Colombier cwrecur(Cw *cw, Off addr, int tag, int tag1, long qp)
130501a344a2SDavid du Colombier {
130601a344a2SDavid du Colombier Iobuf *p;
130701a344a2SDavid du Colombier Dentry *d;
130801a344a2SDavid du Colombier int i, j, shouldstop;
130901a344a2SDavid du Colombier Off na;
131001a344a2SDavid du Colombier char *np;
131101a344a2SDavid du Colombier
131201a344a2SDavid du Colombier shouldstop = 0;
131301a344a2SDavid du Colombier p = getbuf(cw->dev, addr, Bprobe);
131401a344a2SDavid du Colombier if(!isdirty(cw, p, addr, tag)) {
131501a344a2SDavid du Colombier if(!cw->all) {
131601a344a2SDavid du Colombier if(DEBUG)
131701a344a2SDavid du Colombier print("cwrecur: %lld t=%s not dirty %s\n",
131801a344a2SDavid du Colombier (Wideoff)addr, tagnames[tag], cw->name);
131901a344a2SDavid du Colombier if(p)
132001a344a2SDavid du Colombier putbuf(p);
132101a344a2SDavid du Colombier return 0;
132201a344a2SDavid du Colombier }
132301a344a2SDavid du Colombier shouldstop = 1;
132401a344a2SDavid du Colombier }
132501a344a2SDavid du Colombier if(DEBUG)
132601a344a2SDavid du Colombier print("cwrecur: %lld t=%s %s\n",
132701a344a2SDavid du Colombier (Wideoff)addr, tagnames[tag], cw->name);
132801a344a2SDavid du Colombier if(cw->depth >= 100) {
132901a344a2SDavid du Colombier print("dump depth too great %s\n", cw->name);
133001a344a2SDavid du Colombier if(p)
133101a344a2SDavid du Colombier putbuf(p);
133201a344a2SDavid du Colombier return 0;
133301a344a2SDavid du Colombier }
133401a344a2SDavid du Colombier cw->depth++;
133501a344a2SDavid du Colombier
133601a344a2SDavid du Colombier switch(tag) {
133701a344a2SDavid du Colombier default:
133801a344a2SDavid du Colombier print("cwrecur: unknown tag %d %s\n", tag, cw->name);
133901a344a2SDavid du Colombier
134001a344a2SDavid du Colombier case Tfile:
134101a344a2SDavid du Colombier break;
134201a344a2SDavid du Colombier
134301a344a2SDavid du Colombier case Tsuper:
134401a344a2SDavid du Colombier case Tdir:
134501a344a2SDavid du Colombier if(!p) {
134601a344a2SDavid du Colombier p = getbuf(cw->dev, addr, Brd);
134701a344a2SDavid du Colombier if(!p) {
134801a344a2SDavid du Colombier print("cwrecur: Tdir p null %s\n",
134901a344a2SDavid du Colombier cw->name);
135001a344a2SDavid du Colombier break;
135101a344a2SDavid du Colombier }
135201a344a2SDavid du Colombier }
135301a344a2SDavid du Colombier if(tag == Tdir) {
135401a344a2SDavid du Colombier cw->namepad[0] = 0; /* force room */
135501a344a2SDavid du Colombier np = strchr(cw->name, 0);
135601a344a2SDavid du Colombier *np++ = '/';
135701a344a2SDavid du Colombier } else {
135801a344a2SDavid du Colombier np = 0; /* set */
135901a344a2SDavid du Colombier cw->name[0] = 0;
136001a344a2SDavid du Colombier }
136101a344a2SDavid du Colombier
136201a344a2SDavid du Colombier for(i=0; i<DIRPERBUF; i++) {
136301a344a2SDavid du Colombier d = getdir(p, i);
136401a344a2SDavid du Colombier if(!(d->mode & DALLOC))
136501a344a2SDavid du Colombier continue;
136601a344a2SDavid du Colombier qp = d->qid.path & ~QPDIR;
136701a344a2SDavid du Colombier if(tag == Tdir)
136801a344a2SDavid du Colombier strncpy(np, d->name, NAMELEN);
136901a344a2SDavid du Colombier else
137001a344a2SDavid du Colombier if(i > 0)
137101a344a2SDavid du Colombier print("cwrecur: root with >1 directory\n");
137201a344a2SDavid du Colombier tag1 = Tfile;
137301a344a2SDavid du Colombier if(d->mode & DDIR)
137401a344a2SDavid du Colombier tag1 = Tdir;
137501a344a2SDavid du Colombier for(j=0; j<NDBLOCK; j++) {
137601a344a2SDavid du Colombier na = d->dblock[j];
137701a344a2SDavid du Colombier if(na) {
137801a344a2SDavid du Colombier na = cwrecur(cw, na, tag1, 0, qp);
137901a344a2SDavid du Colombier if(na) {
138001a344a2SDavid du Colombier d->dblock[j] = na;
138101a344a2SDavid du Colombier p->flags |= Bmod;
138201a344a2SDavid du Colombier }
138301a344a2SDavid du Colombier }
138401a344a2SDavid du Colombier }
138501a344a2SDavid du Colombier for (j = 0; j < NIBLOCK; j++) {
138601a344a2SDavid du Colombier na = d->iblocks[j];
138701a344a2SDavid du Colombier if(na) {
138801a344a2SDavid du Colombier na = cwrecur(cw, na, Tind1+j, tag1, qp);
138901a344a2SDavid du Colombier if(na) {
139001a344a2SDavid du Colombier d->iblocks[j] = na;
139101a344a2SDavid du Colombier p->flags |= Bmod;
139201a344a2SDavid du Colombier }
139301a344a2SDavid du Colombier }
139401a344a2SDavid du Colombier }
139501a344a2SDavid du Colombier }
139601a344a2SDavid du Colombier break;
139701a344a2SDavid du Colombier
139801a344a2SDavid du Colombier case Tind1:
139901a344a2SDavid du Colombier j = tag1;
140001a344a2SDavid du Colombier tag1 = 0;
140101a344a2SDavid du Colombier goto tind;
140201a344a2SDavid du Colombier
140301a344a2SDavid du Colombier case Tind2:
140401a344a2SDavid du Colombier #ifndef COMPAT32
140501a344a2SDavid du Colombier case Tind3:
140601a344a2SDavid du Colombier case Tind4:
140701a344a2SDavid du Colombier /* add more Tind tags here ... */
140801a344a2SDavid du Colombier #endif
140901a344a2SDavid du Colombier j = tag-1;
141001a344a2SDavid du Colombier tind:
141101a344a2SDavid du Colombier if(!p) {
141201a344a2SDavid du Colombier p = getbuf(cw->dev, addr, Brd);
141301a344a2SDavid du Colombier if(!p) {
141401a344a2SDavid du Colombier print("cwrecur: Tind p null %s\n", cw->name);
141501a344a2SDavid du Colombier break;
141601a344a2SDavid du Colombier }
141701a344a2SDavid du Colombier }
141801a344a2SDavid du Colombier for(i=0; i<INDPERBUF; i++) {
141901a344a2SDavid du Colombier na = ((Off *)p->iobuf)[i];
142001a344a2SDavid du Colombier if(na) {
142101a344a2SDavid du Colombier na = cwrecur(cw, na, j, tag1, qp);
142201a344a2SDavid du Colombier if(na) {
142301a344a2SDavid du Colombier ((Off *)p->iobuf)[i] = na;
142401a344a2SDavid du Colombier p->flags |= Bmod;
142501a344a2SDavid du Colombier }
142601a344a2SDavid du Colombier }
142701a344a2SDavid du Colombier }
142801a344a2SDavid du Colombier break;
142901a344a2SDavid du Colombier }
143001a344a2SDavid du Colombier na = split(cw, p, addr);
143101a344a2SDavid du Colombier cw->depth--;
143201a344a2SDavid du Colombier if(na && shouldstop) {
143301a344a2SDavid du Colombier if(cw->falsehits < 10)
143401a344a2SDavid du Colombier print("shouldstop %lld %lld t=%s %s\n",
143501a344a2SDavid du Colombier (Wideoff)addr, (Wideoff)na,
143601a344a2SDavid du Colombier tagnames[tag], cw->name);
143701a344a2SDavid du Colombier cw->falsehits++;
143801a344a2SDavid du Colombier }
143901a344a2SDavid du Colombier return na;
144001a344a2SDavid du Colombier }
144101a344a2SDavid du Colombier
144201a344a2SDavid du Colombier Timet nextdump(Timet t);
144301a344a2SDavid du Colombier
144401a344a2SDavid du Colombier void
cfsdump(Filsys * fs)144501a344a2SDavid du Colombier cfsdump(Filsys *fs)
144601a344a2SDavid du Colombier {
144701a344a2SDavid du Colombier long m, n, i;
144801a344a2SDavid du Colombier Off orba, rba, oroa, roa, sba, a;
144901a344a2SDavid du Colombier Timet tim;
145001a344a2SDavid du Colombier char tstr[20];
145101a344a2SDavid du Colombier Iobuf *pr, *p1, *p;
145201a344a2SDavid du Colombier Dentry *dr, *d1, *d;
145301a344a2SDavid du Colombier Cache *h;
145401a344a2SDavid du Colombier Superb *s;
145501a344a2SDavid du Colombier Cw *cw;
145601a344a2SDavid du Colombier
145701a344a2SDavid du Colombier if(fs->dev->type != Devcw) {
145801a344a2SDavid du Colombier print("cant dump; not cw device: %Z\n", fs->dev);
145901a344a2SDavid du Colombier return;
146001a344a2SDavid du Colombier }
146101a344a2SDavid du Colombier cw = fs->dev->private;
146201a344a2SDavid du Colombier if(cw == 0) {
146301a344a2SDavid du Colombier print("cant dump: has not been inited: %Z\n", fs->dev);
146401a344a2SDavid du Colombier return;
146501a344a2SDavid du Colombier }
146601a344a2SDavid du Colombier
146701a344a2SDavid du Colombier tim = toytime();
146801a344a2SDavid du Colombier wlock(&mainlock); /* dump */
146901a344a2SDavid du Colombier
147001a344a2SDavid du Colombier /*
147101a344a2SDavid du Colombier * set up static structure
147201a344a2SDavid du Colombier * with frequent variables
147301a344a2SDavid du Colombier */
147401a344a2SDavid du Colombier cw->ndump = 0;
147501a344a2SDavid du Colombier cw->name[0] = 0;
147601a344a2SDavid du Colombier cw->depth = 0;
147701a344a2SDavid du Colombier
147801a344a2SDavid du Colombier /*
147901a344a2SDavid du Colombier * cw root
148001a344a2SDavid du Colombier */
148101a344a2SDavid du Colombier sync("before dump");
148201a344a2SDavid du Colombier cw->fsize = cwsize(cw->dev);
148301a344a2SDavid du Colombier orba = cwraddr(cw->dev);
148401a344a2SDavid du Colombier print("cwroot %lld", (Wideoff)orba);
148501a344a2SDavid du Colombier cons.noage = 1;
148601a344a2SDavid du Colombier cw->all = cw->allflag;
148701a344a2SDavid du Colombier rba = cwrecur(cw, orba, Tsuper, 0, QPROOT);
148801a344a2SDavid du Colombier if(rba == 0)
148901a344a2SDavid du Colombier rba = orba;
149001a344a2SDavid du Colombier print("->%lld\n", (Wideoff)rba);
149101a344a2SDavid du Colombier sync("after cw");
149201a344a2SDavid du Colombier
149301a344a2SDavid du Colombier /*
149401a344a2SDavid du Colombier * partial super block
149501a344a2SDavid du Colombier */
149601a344a2SDavid du Colombier p = getbuf(cw->dev, cwsaddr(cw->dev), Brd|Bmod|Bimm);
149701a344a2SDavid du Colombier s = (Superb*)p->iobuf;
149801a344a2SDavid du Colombier s->fsize = cw->fsize;
149901a344a2SDavid du Colombier s->cwraddr = rba;
150001a344a2SDavid du Colombier putbuf(p);
150101a344a2SDavid du Colombier
150201a344a2SDavid du Colombier /*
150301a344a2SDavid du Colombier * partial cache block
150401a344a2SDavid du Colombier */
150501a344a2SDavid du Colombier p = getbuf(cw->cdev, CACHE_ADDR, Brd|Bmod|Bimm|Bres);
150601a344a2SDavid du Colombier h = (Cache*)p->iobuf;
150701a344a2SDavid du Colombier h->fsize = cw->fsize;
150801a344a2SDavid du Colombier h->cwraddr = rba;
150901a344a2SDavid du Colombier putbuf(p);
151001a344a2SDavid du Colombier
151101a344a2SDavid du Colombier /*
151201a344a2SDavid du Colombier * ro root
151301a344a2SDavid du Colombier */
151401a344a2SDavid du Colombier oroa = cwraddr(cw->rodev);
151501a344a2SDavid du Colombier pr = getbuf(cw->dev, oroa, Brd|Bmod);
151601a344a2SDavid du Colombier dr = getdir(pr, 0);
151701a344a2SDavid du Colombier
151801a344a2SDavid du Colombier datestr(tstr, time(nil)); /* tstr = "yyyymmdd" */
151901a344a2SDavid du Colombier n = 0;
152001a344a2SDavid du Colombier for(a=0;; a++) {
152101a344a2SDavid du Colombier p1 = dnodebuf(pr, dr, a, Tdir, 0);
152201a344a2SDavid du Colombier if(!p1)
152301a344a2SDavid du Colombier goto bad;
152401a344a2SDavid du Colombier n++;
152501a344a2SDavid du Colombier for(i=0; i<DIRPERBUF; i++) {
152601a344a2SDavid du Colombier d1 = getdir(p1, i);
152701a344a2SDavid du Colombier if(!d1)
152801a344a2SDavid du Colombier goto bad;
152901a344a2SDavid du Colombier if(!(d1->mode & DALLOC))
153001a344a2SDavid du Colombier goto found1;
153101a344a2SDavid du Colombier if(!memcmp(d1->name, tstr, 4))
153201a344a2SDavid du Colombier goto found2; /* found entry */
153301a344a2SDavid du Colombier }
153401a344a2SDavid du Colombier putbuf(p1);
153501a344a2SDavid du Colombier }
153601a344a2SDavid du Colombier
153701a344a2SDavid du Colombier /*
153801a344a2SDavid du Colombier * no year directory, create one
153901a344a2SDavid du Colombier */
154001a344a2SDavid du Colombier found1:
154101a344a2SDavid du Colombier p = getbuf(cw->dev, rba, Brd);
154201a344a2SDavid du Colombier d = getdir(p, 0);
154301a344a2SDavid du Colombier d1->qid = d->qid;
154401a344a2SDavid du Colombier d1->qid.version += n;
154501a344a2SDavid du Colombier memmove(d1->name, tstr, 4);
154601a344a2SDavid du Colombier d1->mode = d->mode;
154701a344a2SDavid du Colombier d1->uid = d->uid;
154801a344a2SDavid du Colombier d1->gid = d->gid;
154901a344a2SDavid du Colombier putbuf(p);
155001a344a2SDavid du Colombier accessdir(p1, d1, FWRITE, 0);
155101a344a2SDavid du Colombier
155201a344a2SDavid du Colombier /*
155301a344a2SDavid du Colombier * put mmdd[count] in year directory
155401a344a2SDavid du Colombier */
155501a344a2SDavid du Colombier found2:
155601a344a2SDavid du Colombier accessdir(p1, d1, FREAD, 0);
155701a344a2SDavid du Colombier putbuf(pr);
155801a344a2SDavid du Colombier pr = p1;
155901a344a2SDavid du Colombier dr = d1;
156001a344a2SDavid du Colombier
156101a344a2SDavid du Colombier n = 0;
156201a344a2SDavid du Colombier m = 0;
156301a344a2SDavid du Colombier for(a=0;; a++) {
156401a344a2SDavid du Colombier p1 = dnodebuf(pr, dr, a, Tdir, 0);
156501a344a2SDavid du Colombier if(!p1)
156601a344a2SDavid du Colombier goto bad;
156701a344a2SDavid du Colombier n++;
156801a344a2SDavid du Colombier for(i=0; i<DIRPERBUF; i++) {
156901a344a2SDavid du Colombier d1 = getdir(p1, i);
157001a344a2SDavid du Colombier if(!d1)
157101a344a2SDavid du Colombier goto bad;
157201a344a2SDavid du Colombier if(!(d1->mode & DALLOC))
157301a344a2SDavid du Colombier goto found;
157401a344a2SDavid du Colombier if(!memcmp(d1->name, tstr+4, 4))
157501a344a2SDavid du Colombier m++;
157601a344a2SDavid du Colombier }
157701a344a2SDavid du Colombier putbuf(p1);
157801a344a2SDavid du Colombier }
157901a344a2SDavid du Colombier
158001a344a2SDavid du Colombier /*
158101a344a2SDavid du Colombier * empty slot put in root
158201a344a2SDavid du Colombier */
158301a344a2SDavid du Colombier found:
158401a344a2SDavid du Colombier if(m) /* how many dumps this date */
158501a344a2SDavid du Colombier sprint(tstr+8, "%ld", m);
158601a344a2SDavid du Colombier
158701a344a2SDavid du Colombier p = getbuf(cw->dev, rba, Brd);
158801a344a2SDavid du Colombier d = getdir(p, 0);
158901a344a2SDavid du Colombier *d1 = *d; /* qid is QPROOT */
159001a344a2SDavid du Colombier putbuf(p);
159101a344a2SDavid du Colombier strcpy(d1->name, tstr+4);
159201a344a2SDavid du Colombier d1->qid.version += n;
159301a344a2SDavid du Colombier accessdir(p1, d1, FWRITE, 0);
159401a344a2SDavid du Colombier putbuf(p1);
159501a344a2SDavid du Colombier putbuf(pr);
159601a344a2SDavid du Colombier
159701a344a2SDavid du Colombier cw->fsize = cwsize(cw->dev);
159801a344a2SDavid du Colombier oroa = cwraddr(cw->rodev); /* probably redundant */
159901a344a2SDavid du Colombier print("roroot %lld", (Wideoff)oroa);
160001a344a2SDavid du Colombier
160101a344a2SDavid du Colombier cons.noage = 0;
160201a344a2SDavid du Colombier cw->all = 0;
160301a344a2SDavid du Colombier roa = cwrecur(cw, oroa, Tsuper, 0, QPROOT);
160401a344a2SDavid du Colombier if(roa == 0) {
160501a344a2SDavid du Colombier print("[same]");
160601a344a2SDavid du Colombier roa = oroa;
160701a344a2SDavid du Colombier }
160801a344a2SDavid du Colombier print("->%lld /%.4s/%s\n", (Wideoff)roa, tstr, tstr+4);
160901a344a2SDavid du Colombier sync("after ro");
161001a344a2SDavid du Colombier
161101a344a2SDavid du Colombier /*
161201a344a2SDavid du Colombier * final super block
161301a344a2SDavid du Colombier */
161401a344a2SDavid du Colombier a = cwsaddr(cw->dev);
161501a344a2SDavid du Colombier print("sblock %lld", (Wideoff)a);
161601a344a2SDavid du Colombier p = getbuf(cw->dev, a, Brd|Bmod|Bimm);
161701a344a2SDavid du Colombier s = (Superb*)p->iobuf;
161801a344a2SDavid du Colombier s->last = a;
161901a344a2SDavid du Colombier sba = s->next;
162001a344a2SDavid du Colombier s->next = cw->fsize;
162101a344a2SDavid du Colombier cw->fsize++;
162201a344a2SDavid du Colombier s->fsize = cw->fsize;
162301a344a2SDavid du Colombier s->roraddr = roa;
162401a344a2SDavid du Colombier
162501a344a2SDavid du Colombier cwio(cw->dev, sba, 0, Ogrow);
162601a344a2SDavid du Colombier cwio(cw->dev, sba, p->iobuf, Owrite);
162701a344a2SDavid du Colombier cwio(cw->dev, sba, 0, Odump);
162801a344a2SDavid du Colombier print("->%lld (->%lld)\n", (Wideoff)sba, (Wideoff)s->next);
162901a344a2SDavid du Colombier
163001a344a2SDavid du Colombier putbuf(p);
163101a344a2SDavid du Colombier
163201a344a2SDavid du Colombier /*
163301a344a2SDavid du Colombier * final cache block
163401a344a2SDavid du Colombier */
163501a344a2SDavid du Colombier p = getbuf(cw->cdev, CACHE_ADDR, Brd|Bmod|Bimm|Bres);
163601a344a2SDavid du Colombier h = (Cache*)p->iobuf;
163701a344a2SDavid du Colombier h->fsize = cw->fsize;
163801a344a2SDavid du Colombier h->roraddr = roa;
163901a344a2SDavid du Colombier h->sbaddr = sba;
164001a344a2SDavid du Colombier putbuf(p);
164101a344a2SDavid du Colombier
164201a344a2SDavid du Colombier rewalk(cw);
164301a344a2SDavid du Colombier sync("all done");
164401a344a2SDavid du Colombier
164501a344a2SDavid du Colombier print("%lld blocks queued for worm\n", (Wideoff)cw->ndump);
164601a344a2SDavid du Colombier print("%lld falsehits\n", (Wideoff)cw->falsehits);
164701a344a2SDavid du Colombier cw->nodump = 0;
164801a344a2SDavid du Colombier
164901a344a2SDavid du Colombier /*
165001a344a2SDavid du Colombier * extend all of the locks
165101a344a2SDavid du Colombier */
165201a344a2SDavid du Colombier tim = toytime() - tim;
165301a344a2SDavid du Colombier for(i=0; i<NTLOCK; i++)
165401a344a2SDavid du Colombier if(tlocks[i].time > 0)
165501a344a2SDavid du Colombier tlocks[i].time += tim;
165601a344a2SDavid du Colombier
165701a344a2SDavid du Colombier wunlock(&mainlock);
165801a344a2SDavid du Colombier nextdump(time(nil));
165901a344a2SDavid du Colombier return;
166001a344a2SDavid du Colombier
166101a344a2SDavid du Colombier bad:
166201a344a2SDavid du Colombier panic("dump: bad");
166301a344a2SDavid du Colombier }
166401a344a2SDavid du Colombier
166501a344a2SDavid du Colombier void
mvstates(Device * dev,int s1,int s2,int side)166601a344a2SDavid du Colombier mvstates(Device *dev, int s1, int s2, int side)
166701a344a2SDavid du Colombier {
166801a344a2SDavid du Colombier Iobuf *p, *cb;
166901a344a2SDavid du Colombier Cache *h;
167001a344a2SDavid du Colombier Bucket *b;
167101a344a2SDavid du Colombier Centry *c, *ce;
167201a344a2SDavid du Colombier Off m, lo, hi, msize, maddr;
167301a344a2SDavid du Colombier Cw *cw;
167401a344a2SDavid du Colombier
167501a344a2SDavid du Colombier cw = dev->private;
167601a344a2SDavid du Colombier lo = 0;
167701a344a2SDavid du Colombier hi = lo + devsize(dev->cw.w); /* size of all sides totalled */
167801a344a2SDavid du Colombier if(side >= 0) {
167901a344a2SDavid du Colombier /* operate on only a single disc side */
168001a344a2SDavid du Colombier Sidestarts ss;
168101a344a2SDavid du Colombier
168201a344a2SDavid du Colombier wormsidestarts(dev, side, &ss);
168301a344a2SDavid du Colombier lo = ss.sstart;
168401a344a2SDavid du Colombier hi = ss.s1start;
168501a344a2SDavid du Colombier }
168601a344a2SDavid du Colombier cb = getbuf(cw->cdev, CACHE_ADDR, Brd|Bres);
168701a344a2SDavid du Colombier if(!cb || checktag(cb, Tcache, QPSUPER))
168801a344a2SDavid du Colombier panic("cwstats: checktag c bucket");
168901a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
169001a344a2SDavid du Colombier msize = h->msize;
169101a344a2SDavid du Colombier maddr = h->maddr;
169201a344a2SDavid du Colombier putbuf(cb);
169301a344a2SDavid du Colombier
169401a344a2SDavid du Colombier for(m=0; m<msize; m++) {
169501a344a2SDavid du Colombier p = getbuf(cw->cdev, maddr + m/BKPERBLK, Brd|Bmod);
169601a344a2SDavid du Colombier if(!p || checktag(p, Tbuck, maddr + m/BKPERBLK))
169701a344a2SDavid du Colombier panic("cwtest: checktag c bucket");
169801a344a2SDavid du Colombier b = (Bucket*)p->iobuf + m%BKPERBLK;
169901a344a2SDavid du Colombier ce = b->entry + CEPERBK;
170001a344a2SDavid du Colombier for(c=b->entry; c<ce; c++)
170101a344a2SDavid du Colombier if(c->state == s1 && c->waddr >= lo && c->waddr < hi)
170201a344a2SDavid du Colombier c->state = s2;
170301a344a2SDavid du Colombier putbuf(p);
170401a344a2SDavid du Colombier }
170501a344a2SDavid du Colombier }
170601a344a2SDavid du Colombier
170701a344a2SDavid du Colombier void
prchain(Device * dev,Off m,int flg)170801a344a2SDavid du Colombier prchain(Device *dev, Off m, int flg)
170901a344a2SDavid du Colombier {
171001a344a2SDavid du Colombier Iobuf *p;
171101a344a2SDavid du Colombier Superb *s;
171201a344a2SDavid du Colombier
171301a344a2SDavid du Colombier if(m == 0) {
171401a344a2SDavid du Colombier if(flg)
171501a344a2SDavid du Colombier m = cwsaddr(dev);
171601a344a2SDavid du Colombier else
171701a344a2SDavid du Colombier m = getstartsb(dev);
171801a344a2SDavid du Colombier }
171901a344a2SDavid du Colombier p = getbuf(devnone, Cwxx2, 0);
172001a344a2SDavid du Colombier s = (Superb*)p->iobuf;
172101a344a2SDavid du Colombier for(;;) {
172201a344a2SDavid du Colombier memset(p->iobuf, 0, RBUFSIZE);
172301a344a2SDavid du Colombier if(devread(WDEV(dev), m, p->iobuf) ||
172401a344a2SDavid du Colombier checktag(p, Tsuper, QPSUPER))
172501a344a2SDavid du Colombier break;
172601a344a2SDavid du Colombier if(flg) {
172701a344a2SDavid du Colombier print("dump %lld is good; %lld prev\n", (Wideoff)m,
172801a344a2SDavid du Colombier (Wideoff)s->last);
172901a344a2SDavid du Colombier print("\t%lld cwroot; %lld roroot\n",
173001a344a2SDavid du Colombier (Wideoff)s->cwraddr, (Wideoff)s->roraddr);
173101a344a2SDavid du Colombier if(m <= s->last)
173201a344a2SDavid du Colombier break;
173301a344a2SDavid du Colombier m = s->last;
173401a344a2SDavid du Colombier } else {
173501a344a2SDavid du Colombier print("dump %lld is good; %lld next\n", (Wideoff)m,
173601a344a2SDavid du Colombier (Wideoff)s->next);
173701a344a2SDavid du Colombier print("\t%lld cwroot; %lld roroot\n",
173801a344a2SDavid du Colombier (Wideoff)s->cwraddr, (Wideoff)s->roraddr);
173901a344a2SDavid du Colombier if(m >= s->next)
174001a344a2SDavid du Colombier break;
174101a344a2SDavid du Colombier m = s->next;
174201a344a2SDavid du Colombier }
174301a344a2SDavid du Colombier }
174401a344a2SDavid du Colombier putbuf(p);
174501a344a2SDavid du Colombier }
174601a344a2SDavid du Colombier
174701a344a2SDavid du Colombier void
touchsb(Device * dev)174801a344a2SDavid du Colombier touchsb(Device *dev)
174901a344a2SDavid du Colombier {
175001a344a2SDavid du Colombier Iobuf *p;
175101a344a2SDavid du Colombier Off m;
175201a344a2SDavid du Colombier
175301a344a2SDavid du Colombier m = cwsaddr(dev);
175401a344a2SDavid du Colombier p = getbuf(devnone, Cwxx2, 0);
175501a344a2SDavid du Colombier
175601a344a2SDavid du Colombier memset(p->iobuf, 0, RBUFSIZE);
175701a344a2SDavid du Colombier if(devread(WDEV(dev), m, p->iobuf) ||
175801a344a2SDavid du Colombier checktag(p, Tsuper, QPSUPER))
175901a344a2SDavid du Colombier print("%Z block %lld WORM SUPER BLOCK READ FAILED\n",
176001a344a2SDavid du Colombier WDEV(dev), (Wideoff)m);
176101a344a2SDavid du Colombier else
176201a344a2SDavid du Colombier print("%Z touch superblock %lld\n", WDEV(dev), (Wideoff)m);
176301a344a2SDavid du Colombier putbuf(p);
176401a344a2SDavid du Colombier }
176501a344a2SDavid du Colombier
176601a344a2SDavid du Colombier void
storesb(Device * dev,Off last,int doit)176701a344a2SDavid du Colombier storesb(Device *dev, Off last, int doit)
176801a344a2SDavid du Colombier {
176901a344a2SDavid du Colombier Iobuf *ph, *ps;
177001a344a2SDavid du Colombier Cache *h;
177101a344a2SDavid du Colombier Superb *s;
177201a344a2SDavid du Colombier Off sbaddr, qidgen;
177301a344a2SDavid du Colombier
177401a344a2SDavid du Colombier sbaddr = cwsaddr(dev);
177501a344a2SDavid du Colombier
177601a344a2SDavid du Colombier ps = getbuf(devnone, Cwxx2, 0);
177701a344a2SDavid du Colombier if(!ps) {
177801a344a2SDavid du Colombier print("sbstore: getbuf\n");
177901a344a2SDavid du Colombier return;
178001a344a2SDavid du Colombier }
178101a344a2SDavid du Colombier
178201a344a2SDavid du Colombier /*
178301a344a2SDavid du Colombier * try to read last sb
178401a344a2SDavid du Colombier */
178501a344a2SDavid du Colombier memset(ps->iobuf, 0, RBUFSIZE);
178601a344a2SDavid du Colombier if(devread(WDEV(dev), last, ps->iobuf) ||
178701a344a2SDavid du Colombier checktag(ps, Tsuper, QPSUPER))
178801a344a2SDavid du Colombier print("read last failed\n");
178901a344a2SDavid du Colombier else
179001a344a2SDavid du Colombier print("read last succeeded\n");
179101a344a2SDavid du Colombier
179201a344a2SDavid du Colombier s = (Superb*)ps->iobuf;
179301a344a2SDavid du Colombier qidgen = s->qidgen;
179401a344a2SDavid du Colombier if(qidgen == 0)
179501a344a2SDavid du Colombier qidgen = 0x31415;
179601a344a2SDavid du Colombier qidgen += 1000;
179701a344a2SDavid du Colombier if(s->next != sbaddr)
179801a344a2SDavid du Colombier print("next(last) is not sbaddr %lld %lld\n",
179901a344a2SDavid du Colombier (Wideoff)s->next, (Wideoff)sbaddr);
180001a344a2SDavid du Colombier else
180101a344a2SDavid du Colombier print("next(last) is sbaddr\n");
180201a344a2SDavid du Colombier
180301a344a2SDavid du Colombier /*
180401a344a2SDavid du Colombier * read cached superblock
180501a344a2SDavid du Colombier */
180601a344a2SDavid du Colombier ph = getbuf(CDEV(dev), CACHE_ADDR, Brd|Bres);
180701a344a2SDavid du Colombier if(!ph || checktag(ph, Tcache, QPSUPER)) {
180801a344a2SDavid du Colombier print("cwstats: checktag c bucket\n");
180901a344a2SDavid du Colombier if(ph)
181001a344a2SDavid du Colombier putbuf(ph);
181101a344a2SDavid du Colombier putbuf(ps);
181201a344a2SDavid du Colombier return;
181301a344a2SDavid du Colombier } else
181401a344a2SDavid du Colombier print("read cached sb succeeded\n");
181501a344a2SDavid du Colombier
181601a344a2SDavid du Colombier h = (Cache*)ph->iobuf;
181701a344a2SDavid du Colombier
181801a344a2SDavid du Colombier memset(ps->iobuf, 0, RBUFSIZE);
181901a344a2SDavid du Colombier settag(ps, Tsuper, QPSUPER);
182001a344a2SDavid du Colombier ps->flags = 0;
182101a344a2SDavid du Colombier s = (Superb*)ps->iobuf;
182201a344a2SDavid du Colombier
182301a344a2SDavid du Colombier s->cwraddr = h->cwraddr;
182401a344a2SDavid du Colombier s->roraddr = h->roraddr;
182501a344a2SDavid du Colombier s->fsize = h->fsize;
182601a344a2SDavid du Colombier s->fstart = 2;
182701a344a2SDavid du Colombier s->last = last;
182801a344a2SDavid du Colombier s->next = h->roraddr+1;
182901a344a2SDavid du Colombier
183001a344a2SDavid du Colombier s->qidgen = qidgen;
183101a344a2SDavid du Colombier putbuf(ph);
183201a344a2SDavid du Colombier
183301a344a2SDavid du Colombier if(s->fsize-1 != s->next ||
183401a344a2SDavid du Colombier s->fsize-2 != s->roraddr ||
183501a344a2SDavid du Colombier s->fsize-5 != s->cwraddr) {
183601a344a2SDavid du Colombier print("addrs not in relationship %lld %lld %lld %lld\n",
183701a344a2SDavid du Colombier (Wideoff)s->cwraddr, (Wideoff)s->roraddr,
183801a344a2SDavid du Colombier (Wideoff)s->next, (Wideoff)s->fsize);
183901a344a2SDavid du Colombier putbuf(ps);
184001a344a2SDavid du Colombier return;
184101a344a2SDavid du Colombier } else
184201a344a2SDavid du Colombier print("addresses in relation\n");
184301a344a2SDavid du Colombier
184401a344a2SDavid du Colombier if(doit)
184501a344a2SDavid du Colombier if(devwrite(WDEV(dev), sbaddr, ps->iobuf))
184601a344a2SDavid du Colombier print("%Z block %lld WORM SUPER BLOCK WRITE FAILED\n",
184701a344a2SDavid du Colombier WDEV(dev), (Wideoff)sbaddr);
184801a344a2SDavid du Colombier ps->flags = 0;
184901a344a2SDavid du Colombier putbuf(ps);
185001a344a2SDavid du Colombier }
185101a344a2SDavid du Colombier
185201a344a2SDavid du Colombier void
savecache(Device * dev)185301a344a2SDavid du Colombier savecache(Device *dev)
185401a344a2SDavid du Colombier {
185501a344a2SDavid du Colombier Iobuf *p, *cb;
185601a344a2SDavid du Colombier Cache *h;
185701a344a2SDavid du Colombier Bucket *b;
185801a344a2SDavid du Colombier Centry *c, *ce;
185901a344a2SDavid du Colombier long n, left;
186001a344a2SDavid du Colombier Off m, maddr, msize, *longp, nbyte;
186101a344a2SDavid du Colombier Device *cdev;
186201a344a2SDavid du Colombier
186301a344a2SDavid du Colombier if(walkto("/adm/cache") || con_open(FID2, OWRITE|OTRUNC)) {
186401a344a2SDavid du Colombier print("cant open /adm/cache\n");
186501a344a2SDavid du Colombier return;
186601a344a2SDavid du Colombier }
186701a344a2SDavid du Colombier cdev = CDEV(dev);
186801a344a2SDavid du Colombier cb = getbuf(cdev, CACHE_ADDR, Brd|Bres);
186901a344a2SDavid du Colombier if(!cb || checktag(cb, Tcache, QPSUPER))
187001a344a2SDavid du Colombier panic("savecache: checktag c bucket");
187101a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
187201a344a2SDavid du Colombier msize = h->msize;
187301a344a2SDavid du Colombier maddr = h->maddr;
187401a344a2SDavid du Colombier putbuf(cb);
187501a344a2SDavid du Colombier
187601a344a2SDavid du Colombier n = BUFSIZE; /* calculate write size */
187701a344a2SDavid du Colombier if(n > MAXDAT)
187801a344a2SDavid du Colombier n = MAXDAT;
187901a344a2SDavid du Colombier
188001a344a2SDavid du Colombier cb = getbuf(devnone, Cwxx4, 0);
188101a344a2SDavid du Colombier longp = (Off *)cb->iobuf;
188201a344a2SDavid du Colombier left = n/sizeof(Off);
188301a344a2SDavid du Colombier cons.offset = 0;
188401a344a2SDavid du Colombier
188501a344a2SDavid du Colombier for(m=0; m<msize; m++) {
188601a344a2SDavid du Colombier if(left < BKPERBLK) {
188701a344a2SDavid du Colombier nbyte = (n/sizeof(Off) - left) * sizeof(Off);
188801a344a2SDavid du Colombier con_write(FID2, cb->iobuf, cons.offset, nbyte);
188901a344a2SDavid du Colombier cons.offset += nbyte;
189001a344a2SDavid du Colombier longp = (Off *)cb->iobuf;
189101a344a2SDavid du Colombier left = n/sizeof(Off);
189201a344a2SDavid du Colombier }
189301a344a2SDavid du Colombier p = getbuf(cdev, maddr + m/BKPERBLK, Brd);
189401a344a2SDavid du Colombier if(!p || checktag(p, Tbuck, maddr + m/BKPERBLK))
189501a344a2SDavid du Colombier panic("cwtest: checktag c bucket");
189601a344a2SDavid du Colombier b = (Bucket*)p->iobuf + m%BKPERBLK;
189701a344a2SDavid du Colombier ce = b->entry + CEPERBK;
189801a344a2SDavid du Colombier for(c = b->entry; c < ce; c++)
189901a344a2SDavid du Colombier if(c->state == Cread) {
190001a344a2SDavid du Colombier *longp++ = c->waddr;
190101a344a2SDavid du Colombier left--;
190201a344a2SDavid du Colombier }
190301a344a2SDavid du Colombier putbuf(p);
190401a344a2SDavid du Colombier }
190501a344a2SDavid du Colombier nbyte = (n/sizeof(Off) - left) * sizeof(Off);
190601a344a2SDavid du Colombier con_write(FID2, cb->iobuf, cons.offset, nbyte);
190701a344a2SDavid du Colombier putbuf(cb);
190801a344a2SDavid du Colombier }
190901a344a2SDavid du Colombier
191001a344a2SDavid du Colombier void
loadcache(Device * dev,int dskno)191101a344a2SDavid du Colombier loadcache(Device *dev, int dskno)
191201a344a2SDavid du Colombier {
191301a344a2SDavid du Colombier Iobuf *p, *cb;
191401a344a2SDavid du Colombier Off m, nbyte, *longp, count;
191501a344a2SDavid du Colombier Sidestarts ss;
191601a344a2SDavid du Colombier
191701a344a2SDavid du Colombier if(walkto("/adm/cache") || con_open(FID2, OREAD)) {
191801a344a2SDavid du Colombier print("cant open /adm/cache\n");
191901a344a2SDavid du Colombier return;
192001a344a2SDavid du Colombier }
192101a344a2SDavid du Colombier
192201a344a2SDavid du Colombier cb = getbuf(devnone, Cwxx4, 0);
192301a344a2SDavid du Colombier cons.offset = 0;
192401a344a2SDavid du Colombier count = 0;
192501a344a2SDavid du Colombier
192601a344a2SDavid du Colombier if (dskno >= 0)
192701a344a2SDavid du Colombier wormsidestarts(dev, dskno, &ss);
192801a344a2SDavid du Colombier for(;;) {
192901a344a2SDavid du Colombier memset(cb->iobuf, 0, BUFSIZE);
193001a344a2SDavid du Colombier nbyte = con_read(FID2, cb->iobuf, cons.offset, 100) / sizeof(Off);
193101a344a2SDavid du Colombier if(nbyte <= 0)
193201a344a2SDavid du Colombier break;
193301a344a2SDavid du Colombier cons.offset += nbyte * sizeof(Off);
193401a344a2SDavid du Colombier longp = (Off *)cb->iobuf;
193501a344a2SDavid du Colombier while(nbyte > 0) {
193601a344a2SDavid du Colombier m = *longp++;
193701a344a2SDavid du Colombier nbyte--;
193801a344a2SDavid du Colombier if(m == 0)
193901a344a2SDavid du Colombier continue;
194001a344a2SDavid du Colombier /* if given a diskno, restrict to just that disc side */
194101a344a2SDavid du Colombier if(dskno < 0 || m >= ss.sstart && m < ss.s1start) {
194201a344a2SDavid du Colombier p = getbuf(dev, m, Brd);
194301a344a2SDavid du Colombier if(p)
194401a344a2SDavid du Colombier putbuf(p);
194501a344a2SDavid du Colombier count++;
194601a344a2SDavid du Colombier }
194701a344a2SDavid du Colombier }
194801a344a2SDavid du Colombier }
194901a344a2SDavid du Colombier putbuf(cb);
195001a344a2SDavid du Colombier print("%lld blocks loaded from worm %d\n", (Wideoff)count, dskno);
195101a344a2SDavid du Colombier }
195201a344a2SDavid du Colombier
195301a344a2SDavid du Colombier void
morecache(Device * dev,int dskno,Off size)195401a344a2SDavid du Colombier morecache(Device *dev, int dskno, Off size)
195501a344a2SDavid du Colombier {
195601a344a2SDavid du Colombier Iobuf *p;
195701a344a2SDavid du Colombier Off m, ml, mh, mm, count;
195801a344a2SDavid du Colombier Cache *h;
195901a344a2SDavid du Colombier Sidestarts ss;
196001a344a2SDavid du Colombier
196101a344a2SDavid du Colombier p = getbuf(CDEV(dev), CACHE_ADDR, Brd|Bres);
196201a344a2SDavid du Colombier if(!p || checktag(p, Tcache, QPSUPER))
196301a344a2SDavid du Colombier panic("savecache: checktag c bucket");
196401a344a2SDavid du Colombier h = (Cache*)p->iobuf;
196501a344a2SDavid du Colombier mm = h->wmax;
196601a344a2SDavid du Colombier putbuf(p);
196701a344a2SDavid du Colombier
196801a344a2SDavid du Colombier wormsidestarts(dev, dskno, &ss);
196901a344a2SDavid du Colombier ml = ss.sstart; /* start at beginning of disc side #dskno */
197001a344a2SDavid du Colombier mh = ml + size;
197101a344a2SDavid du Colombier if(mh > mm) {
197201a344a2SDavid du Colombier mh = mm;
197301a344a2SDavid du Colombier print("limited to %lld\n", (Wideoff)mh-ml);
197401a344a2SDavid du Colombier }
197501a344a2SDavid du Colombier
197601a344a2SDavid du Colombier count = 0;
197701a344a2SDavid du Colombier for(m=ml; m < mh; m++) {
197801a344a2SDavid du Colombier p = getbuf(dev, m, Brd);
197901a344a2SDavid du Colombier if(p)
198001a344a2SDavid du Colombier putbuf(p);
198101a344a2SDavid du Colombier count++;
198201a344a2SDavid du Colombier }
198301a344a2SDavid du Colombier print("%lld blocks loaded from worm %d\n", (Wideoff)count, dskno);
198401a344a2SDavid du Colombier }
198501a344a2SDavid du Colombier
198601a344a2SDavid du Colombier void
blockcmp(Device * dev,Off wa,Off ca)198701a344a2SDavid du Colombier blockcmp(Device *dev, Off wa, Off ca)
198801a344a2SDavid du Colombier {
198901a344a2SDavid du Colombier Iobuf *p1, *p2;
199001a344a2SDavid du Colombier int i, c;
199101a344a2SDavid du Colombier
199201a344a2SDavid du Colombier p1 = getbuf(WDEV(dev), wa, Brd);
199301a344a2SDavid du Colombier if(!p1) {
199401a344a2SDavid du Colombier print("blockcmp: wdev error\n");
199501a344a2SDavid du Colombier return;
199601a344a2SDavid du Colombier }
199701a344a2SDavid du Colombier
199801a344a2SDavid du Colombier p2 = getbuf(CDEV(dev), ca, Brd);
199901a344a2SDavid du Colombier if(!p2) {
200001a344a2SDavid du Colombier print("blockcmp: cdev error\n");
200101a344a2SDavid du Colombier putbuf(p1);
200201a344a2SDavid du Colombier return;
200301a344a2SDavid du Colombier }
200401a344a2SDavid du Colombier
200501a344a2SDavid du Colombier c = 0;
200601a344a2SDavid du Colombier for(i=0; i<RBUFSIZE; i++)
200701a344a2SDavid du Colombier if(p1->iobuf[i] != p2->iobuf[i]) {
200801a344a2SDavid du Colombier print("%4d: %.2x %.2x\n",
200901a344a2SDavid du Colombier i,
201001a344a2SDavid du Colombier p1->iobuf[i]&0xff,
201101a344a2SDavid du Colombier p2->iobuf[i]&0xff);
201201a344a2SDavid du Colombier c++;
201301a344a2SDavid du Colombier if(c >= 10)
201401a344a2SDavid du Colombier break;
201501a344a2SDavid du Colombier }
201601a344a2SDavid du Colombier
201701a344a2SDavid du Colombier if(c == 0)
201801a344a2SDavid du Colombier print("no error\n");
201901a344a2SDavid du Colombier putbuf(p1);
202001a344a2SDavid du Colombier putbuf(p2);
202101a344a2SDavid du Colombier }
202201a344a2SDavid du Colombier
202301a344a2SDavid du Colombier void
wblock(Device * dev,Off addr)202401a344a2SDavid du Colombier wblock(Device *dev, Off addr)
202501a344a2SDavid du Colombier {
202601a344a2SDavid du Colombier Iobuf *p1;
202701a344a2SDavid du Colombier int i;
202801a344a2SDavid du Colombier
202901a344a2SDavid du Colombier p1 = getbuf(dev, addr, Brd);
203001a344a2SDavid du Colombier if(p1) {
203101a344a2SDavid du Colombier i = devwrite(WDEV(dev), addr, p1->iobuf);
203201a344a2SDavid du Colombier print("i = %d\n", i);
203301a344a2SDavid du Colombier putbuf(p1);
203401a344a2SDavid du Colombier }
203501a344a2SDavid du Colombier }
203601a344a2SDavid du Colombier
203701a344a2SDavid du Colombier void
cwtest(Device *)203801a344a2SDavid du Colombier cwtest(Device*)
203901a344a2SDavid du Colombier {
204001a344a2SDavid du Colombier }
204101a344a2SDavid du Colombier
204201a344a2SDavid du Colombier #ifdef XXX
204301a344a2SDavid du Colombier /* garbage to change sb size
204401a344a2SDavid du Colombier * probably will need it someday
204501a344a2SDavid du Colombier */
204601a344a2SDavid du Colombier fsz = number(0, 0, 10);
204701a344a2SDavid du Colombier count = 0;
204801a344a2SDavid du Colombier if(fsz == number(0, -1, 10))
204901a344a2SDavid du Colombier count = -1; /* really do it */
205001a344a2SDavid du Colombier print("fsize = %ld\n", fsz);
205101a344a2SDavid du Colombier cdev = CDEV(dev);
205201a344a2SDavid du Colombier cb = getbuf(cdev, CACHE_ADDR, Brd|Bres);
205301a344a2SDavid du Colombier if(!cb || checktag(cb, Tcache, QPSUPER))
205401a344a2SDavid du Colombier panic("cwstats: checktag c bucket");
205501a344a2SDavid du Colombier h = (Cache*)cb->iobuf;
205601a344a2SDavid du Colombier for(m=0; m<h->msize; m++) {
205701a344a2SDavid du Colombier p = getbuf(cdev, h->maddr + m/BKPERBLK, Brd|Bmod);
205801a344a2SDavid du Colombier if(!p || checktag(p, Tbuck, h->maddr + m/BKPERBLK))
205901a344a2SDavid du Colombier panic("cwtest: checktag c bucket");
206001a344a2SDavid du Colombier b = (Bucket*)p->iobuf + m%BKPERBLK;
206101a344a2SDavid du Colombier ce = b->entry + CEPERBK;
206201a344a2SDavid du Colombier for(c=b->entry; c<ce; c++) {
206301a344a2SDavid du Colombier if(c->waddr < fsz)
206401a344a2SDavid du Colombier continue;
206501a344a2SDavid du Colombier if(count < 0) {
206601a344a2SDavid du Colombier c->state = Cnone;
206701a344a2SDavid du Colombier continue;
206801a344a2SDavid du Colombier }
206901a344a2SDavid du Colombier if(c->state != Cdirty)
207001a344a2SDavid du Colombier count++;
207101a344a2SDavid du Colombier }
207201a344a2SDavid du Colombier putbuf(p);
207301a344a2SDavid du Colombier }
207401a344a2SDavid du Colombier if(count < 0) {
207501a344a2SDavid du Colombier print("old cache hsize = %ld\n", h->fsize);
207601a344a2SDavid du Colombier h->fsize = fsz;
207701a344a2SDavid du Colombier cb->flags |= Bmod;
207801a344a2SDavid du Colombier p = getbuf(dev, h->sbaddr, Brd|Bmod);
207901a344a2SDavid du Colombier s = (Superb*)p->iobuf;
208001a344a2SDavid du Colombier print("old super hsize = %ld\n", s->fsize);
208101a344a2SDavid du Colombier s->fsize = fsz;
208201a344a2SDavid du Colombier putbuf(p);
208301a344a2SDavid du Colombier }
208401a344a2SDavid du Colombier putbuf(cb);
208501a344a2SDavid du Colombier print("count = %lld\n", (Wideoff)count);
208601a344a2SDavid du Colombier #endif
208701a344a2SDavid du Colombier
208801a344a2SDavid du Colombier int
convstate(char * name)208901a344a2SDavid du Colombier convstate(char *name)
209001a344a2SDavid du Colombier {
209101a344a2SDavid du Colombier int i;
209201a344a2SDavid du Colombier
209301a344a2SDavid du Colombier for(i=0; i<nelem(cwnames); i++)
209401a344a2SDavid du Colombier if(cwnames[i])
209501a344a2SDavid du Colombier if(strcmp(cwnames[i], name) == 0)
209601a344a2SDavid du Colombier return i;
209701a344a2SDavid du Colombier return -1;
209801a344a2SDavid du Colombier }
209901a344a2SDavid du Colombier
210001a344a2SDavid du Colombier void
searchtag(Device * d,Off a,int tag,int n)210101a344a2SDavid du Colombier searchtag(Device *d, Off a, int tag, int n)
210201a344a2SDavid du Colombier {
210301a344a2SDavid du Colombier Iobuf *p;
210401a344a2SDavid du Colombier Tag *t;
210501a344a2SDavid du Colombier int i;
210601a344a2SDavid du Colombier
210701a344a2SDavid du Colombier if(a == 0)
210801a344a2SDavid du Colombier a = getstartsb(d);
210901a344a2SDavid du Colombier p = getbuf(devnone, Cwxx2, 0);
211001a344a2SDavid du Colombier t = (Tag*)(p->iobuf+BUFSIZE);
211101a344a2SDavid du Colombier for(i=0; i<n; i++) {
211201a344a2SDavid du Colombier memset(p->iobuf, 0, RBUFSIZE);
211301a344a2SDavid du Colombier if(devread(WDEV(d), a+i, p->iobuf)) {
211401a344a2SDavid du Colombier if(n == 1000)
211501a344a2SDavid du Colombier break;
211601a344a2SDavid du Colombier continue;
211701a344a2SDavid du Colombier }
211801a344a2SDavid du Colombier if(t->tag == tag) {
211901a344a2SDavid du Colombier print("tag %d found at %Z %lld\n", tag, d, (Wideoff)a+i);
212001a344a2SDavid du Colombier break;
212101a344a2SDavid du Colombier }
212201a344a2SDavid du Colombier }
212301a344a2SDavid du Colombier putbuf(p);
212401a344a2SDavid du Colombier }
212501a344a2SDavid du Colombier
212601a344a2SDavid du Colombier void
cmd_cwcmd(int argc,char * argv[])212701a344a2SDavid du Colombier cmd_cwcmd(int argc, char *argv[])
212801a344a2SDavid du Colombier {
212901a344a2SDavid du Colombier Device *dev;
213001a344a2SDavid du Colombier char *arg;
213101a344a2SDavid du Colombier char str[28];
213201a344a2SDavid du Colombier Off s1, s2, a, b, n;
213301a344a2SDavid du Colombier Cw *cw;
213401a344a2SDavid du Colombier
213501a344a2SDavid du Colombier if(argc <= 1) {
213601a344a2SDavid du Colombier print("\tcwcmd mvstate state1 state2 [platter]\n");
213701a344a2SDavid du Colombier print("\tcwcmd prchain [start] [bakflg]\n");
213801a344a2SDavid du Colombier print("\tcwcmd searchtag [start] [tag] [blocks]\n");
213901a344a2SDavid du Colombier print("\tcwcmd touchsb\n");
214001a344a2SDavid du Colombier print("\tcwcmd savecache\n");
214101a344a2SDavid du Colombier print("\tcwcmd loadcache [dskno]\n");
214201a344a2SDavid du Colombier print("\tcwcmd morecache dskno [count]\n");
214301a344a2SDavid du Colombier print("\tcwcmd blockcmp wbno cbno\n");
214401a344a2SDavid du Colombier print("\tcwcmd startdump [01]\n");
214501a344a2SDavid du Colombier print("\tcwcmd acct\n");
214601a344a2SDavid du Colombier print("\tcwcmd clearacct\n");
214701a344a2SDavid du Colombier return;
214801a344a2SDavid du Colombier }
214901a344a2SDavid du Colombier arg = argv[1];
215001a344a2SDavid du Colombier
215101a344a2SDavid du Colombier /*
215201a344a2SDavid du Colombier * items not depend on a cw filesystem
215301a344a2SDavid du Colombier */
215401a344a2SDavid du Colombier if(strcmp(arg, "acct") == 0) {
215501a344a2SDavid du Colombier for(a=0; a<nelem(growacct); a++) {
215601a344a2SDavid du Colombier b = growacct[a];
215701a344a2SDavid du Colombier if(b) {
215801a344a2SDavid du Colombier uidtostr(str, a, 1);
215901a344a2SDavid du Colombier print("%10lld %s\n",
216001a344a2SDavid du Colombier ((Wideoff)b*ADDFREE*RBUFSIZE+500000)/1000000,
216101a344a2SDavid du Colombier str);
216201a344a2SDavid du Colombier }
216301a344a2SDavid du Colombier }
216401a344a2SDavid du Colombier return;
216501a344a2SDavid du Colombier }
216601a344a2SDavid du Colombier if(strcmp(arg, "clearacct") == 0) {
216701a344a2SDavid du Colombier memset(growacct, 0, sizeof(growacct));
216801a344a2SDavid du Colombier return;
216901a344a2SDavid du Colombier }
217001a344a2SDavid du Colombier
217101a344a2SDavid du Colombier /*
217201a344a2SDavid du Colombier * items depend on cw filesystem
217301a344a2SDavid du Colombier */
217401a344a2SDavid du Colombier dev = cons.curfs->dev;
217501a344a2SDavid du Colombier if(dev == 0 || dev->type != Devcw || dev->private == 0) {
217601a344a2SDavid du Colombier print("cfs not a cw filesystem: %Z\n", dev);
217701a344a2SDavid du Colombier return;
217801a344a2SDavid du Colombier }
217901a344a2SDavid du Colombier cw = dev->private;
218001a344a2SDavid du Colombier if(strcmp(arg, "searchtag") == 0) {
218101a344a2SDavid du Colombier a = 0;
218201a344a2SDavid du Colombier if(argc > 2)
218301a344a2SDavid du Colombier a = number(argv[2], 0, 10);
218401a344a2SDavid du Colombier b = Tsuper;
218501a344a2SDavid du Colombier if(argc > 3)
218601a344a2SDavid du Colombier b = number(argv[3], 0, 10);
218701a344a2SDavid du Colombier n = 1000;
218801a344a2SDavid du Colombier if(argc > 4)
218901a344a2SDavid du Colombier n = number(argv[4], 0, 10);
219001a344a2SDavid du Colombier searchtag(dev, a, b, n);
219101a344a2SDavid du Colombier } else if(strcmp(arg, "mvstate") == 0) {
219201a344a2SDavid du Colombier if(argc < 4)
219301a344a2SDavid du Colombier goto bad;
219401a344a2SDavid du Colombier s1 = convstate(argv[2]);
219501a344a2SDavid du Colombier s2 = convstate(argv[3]);
219601a344a2SDavid du Colombier if(s1 < 0 || s2 < 0)
219701a344a2SDavid du Colombier goto bad;
219801a344a2SDavid du Colombier a = -1;
219901a344a2SDavid du Colombier if(argc > 4)
220001a344a2SDavid du Colombier a = number(argv[4], 0, 10);
220101a344a2SDavid du Colombier mvstates(dev, s1, s2, a);
220201a344a2SDavid du Colombier return;
220301a344a2SDavid du Colombier bad:
220401a344a2SDavid du Colombier print("cwcmd mvstate: bad args\n");
220501a344a2SDavid du Colombier } else if(strcmp(arg, "prchain") == 0) {
220601a344a2SDavid du Colombier a = 0;
220701a344a2SDavid du Colombier if(argc > 2)
220801a344a2SDavid du Colombier a = number(argv[2], 0, 10);
220901a344a2SDavid du Colombier s1 = 0;
221001a344a2SDavid du Colombier if(argc > 3)
221101a344a2SDavid du Colombier s1 = number(argv[3], 0, 10);
221201a344a2SDavid du Colombier prchain(dev, a, s1);
221301a344a2SDavid du Colombier } else if(strcmp(arg, "touchsb") == 0)
221401a344a2SDavid du Colombier touchsb(dev);
221501a344a2SDavid du Colombier else if(strcmp(arg, "savecache") == 0)
221601a344a2SDavid du Colombier savecache(dev);
221701a344a2SDavid du Colombier else if(strcmp(arg, "loadcache") == 0) {
221801a344a2SDavid du Colombier s1 = -1;
221901a344a2SDavid du Colombier if(argc > 2)
222001a344a2SDavid du Colombier s1 = number(argv[2], 0, 10);
222101a344a2SDavid du Colombier loadcache(dev, s1);
222201a344a2SDavid du Colombier } else if(strcmp(arg, "morecache") == 0) {
222301a344a2SDavid du Colombier if(argc <= 2) {
222401a344a2SDavid du Colombier print("arg count\n");
222501a344a2SDavid du Colombier return;
222601a344a2SDavid du Colombier }
222701a344a2SDavid du Colombier s1 = number(argv[2], 0, 10);
222801a344a2SDavid du Colombier if(argc > 3)
222901a344a2SDavid du Colombier s2 = number(argv[3], 0, 10);
223001a344a2SDavid du Colombier else
223101a344a2SDavid du Colombier s2 = wormsizeside(dev, s1); /* default to 1 disc side */
223201a344a2SDavid du Colombier morecache(dev, s1, s2);
223301a344a2SDavid du Colombier } else if(strcmp(arg, "blockcmp") == 0) {
223401a344a2SDavid du Colombier if(argc < 4) {
223501a344a2SDavid du Colombier print("cannot arg count\n");
223601a344a2SDavid du Colombier return;
223701a344a2SDavid du Colombier }
223801a344a2SDavid du Colombier s1 = number(argv[2], 0, 10);
223901a344a2SDavid du Colombier s2 = number(argv[3], 0, 10);
224001a344a2SDavid du Colombier blockcmp(dev, s1, s2);
224101a344a2SDavid du Colombier } else if(strcmp(arg, "startdump") == 0) {
224201a344a2SDavid du Colombier if(argc > 2)
224301a344a2SDavid du Colombier cw->nodump = number(argv[2], 0, 10);
224401a344a2SDavid du Colombier cw->nodump = !cw->nodump;
224501a344a2SDavid du Colombier if(cw->nodump)
224601a344a2SDavid du Colombier print("dump stopped\n");
224701a344a2SDavid du Colombier else
224801a344a2SDavid du Colombier print("dump allowed\n");
224901a344a2SDavid du Colombier } else if(strcmp(arg, "allflag") == 0) {
225001a344a2SDavid du Colombier if(argc > 2)
225101a344a2SDavid du Colombier cw->allflag = number(argv[2], 0, 10);
225201a344a2SDavid du Colombier else
225301a344a2SDavid du Colombier cw->allflag = !cw->allflag;
225401a344a2SDavid du Colombier print("allflag = %d; falsehits = %lld\n",
225501a344a2SDavid du Colombier cw->allflag, (Wideoff)cw->falsehits);
225601a344a2SDavid du Colombier } else if(strcmp(arg, "storesb") == 0) {
225701a344a2SDavid du Colombier a = 4168344;
225801a344a2SDavid du Colombier b = 0;
225901a344a2SDavid du Colombier if(argc > 2)
226001a344a2SDavid du Colombier a = number(argv[2], 4168344, 10);
226101a344a2SDavid du Colombier if(argc > 3)
226201a344a2SDavid du Colombier b = number(argv[3], 0, 10);
226301a344a2SDavid du Colombier storesb(dev, a, b);
226401a344a2SDavid du Colombier } else if(strcmp(arg, "test") == 0)
226501a344a2SDavid du Colombier cwtest(dev);
226601a344a2SDavid du Colombier else
226701a344a2SDavid du Colombier print("unknown cwcmd %s\n", arg);
226801a344a2SDavid du Colombier }
2269