2269 lines · 41.7 KB · C
RawDownload
#include "all.h"#include "mem.h"		// for Ticks. #define dprint(...)#define dpprint(...)	//print(__VA_ARGS__) #define	FIRST		SUPER_ADDR #define	ADDFREE		(100)#define	CACHE_ADDR	SUPER_ADDR#define	MAXAGE		10000 #define	CDEV(d)		(d->cw.c)#define	WDEV(d)		(d->cw.w)#define	RDEV(d)		(d->cw.ro) /* cache state */enum{	/* states -- beware these are recorded on the cache */				/*    cache    worm	*/	Cnone = 0,		/*	0	?	*/	Cdirty,			/*	1	0	*/	Cdump,			/*	1	0->1	*/	Cread,			/*	1	1	*/	Cwrite,			/*	2	1	*/	Cdump1,			/* inactive form of dump */	Cerror, 	/* opcodes -- these are not recorded */	Onone,	Oread,	Owrite,	Ogrow,	Odump,	Orele,	Ofree,}; typedef	struct	Cw	Cw;struct	Cw{	Device*	dev;	Device*	cdev;	Device*	wdev;	Device*	rodev;	Cw*	link; 	Filter	ncwio;	int	dbucket;	/* last bucket dumped */	Off	daddr;		/* last block dumped */	Off	ncopy;	int	nodump;/* * following are cached variables for dumps */	Off	fsize;	Off	ndump;	int	depth;	int	all;		/* local flag to recur on modified directories */	int	allflag;	/* global flag to recur on modified directories */	Off	falsehits;	/* times recur found modified blocks */	struct	{		char	name[500];		char	namepad[NAMELEN+10];	};}; staticchar*	cwnames[] ={	[Cnone]		"none",	[Cdirty]	"dirty",	[Cdump]		"dump",	[Cread]		"read",	[Cwrite]	"write",	[Cdump1]	"dump1",	[Cerror]	"error", 	[Onone]		"none",	[Oread]		"read",	[Owrite]	"write",	[Ogrow]		"grow",	[Odump]		"dump",	[Orele]		"rele",}; Centry*	getcentry(Bucket*, Off);int	cwio(Device*, Off, void*, int);void	cmd_cwcmd(int, char*[]); /* * console command * initiate a dump */extern Timet nextdump(Timet); voidcmd_dump(int argc, char *argv[]){	Filsys *fs; 	fs = cons.curfs;	if(argc > 1)		fs = fsstr(argv[1]);	if(fs == 0) {		print("%s: unknown file system\n", argv[1]);		return;	}	cfsdump(fs);	nextdump(time());} voidcmd_dumpctl(int argc, char *argv[]){	char *s; 	if(argc == 2){		if(strcmp(argv[1], "on") == 0)			conf.nodump = 0;		else			conf.nodump = 1;	}	s = "on\0off"+conf.nodump*3;	print("automatic dumps are %s\n", s);} /* * console command * worm stats */staticvoidcmd_statw(int, char*[]){	Filsys *fs;	Iobuf *p;	Superb *sb;	Cache *h;	Bucket *b;	Centry *c, *ce;	Off m, nw, bw, state[Onone];	Off sbfsize, sbcwraddr, sbroraddr, sblast, sbnext;	Off hmsize, hmaddr, dsize, dsizepct;	Device *dev;	Cw *cw;	int s; 	fs = cons.curfs;	dev = fs->dev;	if(dev->type != Devcw) {		print("curfs not type cw\n");		return;	} 	cw = dev->private;	if(cw == 0) {		print("curfs not inited\n");		return;	} 	print("cwstats %s\n", fs->name); 	sbfsize = 0;	sbcwraddr = 0;	sbroraddr = 0;	sblast = 0;	sbnext = 0; 	print("	filesys %s\n", fs->name);	print("	nio   =%W\n", &cw->ncwio);	p = getbuf(dev, cwsaddr(dev), Bread);	if(!p || checktag(p, Tsuper, QPSUPER)) {		print("cwstats: checktag super\n");		if(p) {			putbuf(p);			p = 0;		}	}	if(p) {		sb = (Superb*)p->iobuf;		sbfsize = sb->fsize;		sbcwraddr = sb->cwraddr;		sbroraddr = sb->roraddr;		sblast = sb->last;		sbnext = sb->next;		putbuf(p);	} 	p = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres);	if(!p || checktag(p, Tcache, QPSUPER)) {		print("cwstats: checktag c bucket\n");		if(p)			putbuf(p);		return;	}	h = (Cache*)p->iobuf;	hmaddr = h->maddr;	hmsize = h->msize; 	print("		maddr  = %8lld\n", (Wideoff)hmaddr);	print("		msize  = %8lld\n", (Wideoff)hmsize);	print("		caddr  = %8lld\n", (Wideoff)h->caddr);	print("		csize  = %8lld\n", (Wideoff)h->csize);	print("		sbaddr = %8lld\n", (Wideoff)h->sbaddr);	print("		craddr = %8lld %8lld\n", (Wideoff)h->cwraddr, (Wideoff)sbcwraddr);	print("		roaddr = %8lld %8lld\n", (Wideoff)h->roraddr, (Wideoff)sbroraddr);	/* print stats in terms of (first-)disc sides */	dsize = wormsizeside(dev, 0);	if (dsize < 1) {		dprint("wormsizeside sz %lld for %Z side 0\n", (Wideoff)dsize, dev);		dsize = h->wsize;	/* it's probably a fake worm */		if (dsize < 1)			dsize = 1000;	/* don't divide by zero */	}	dsizepct = dsize/100;	print("		fsize  = %8lld %8lld %2lld+%2lld%%\n", (Wideoff)h->fsize,				(Wideoff)sbfsize, (Wideoff)h->fsize/dsize,				(Wideoff)(h->fsize%dsize)/dsizepct);	print("		slast  =          %8lld\n", (Wideoff)sblast);	print("		snext  =          %8lld\n", (Wideoff)sbnext);	print("		wmax   = %8lld          %2lld+%2lld%%\n", (Wideoff)h->wmax,				(Wideoff)h->wmax/dsize,				(Wideoff)(h->wmax%dsize)/dsizepct);	print("		wsize  = %8lld          %2lld+%2lld%%\n", (Wideoff)h->wsize,				(Wideoff)h->wsize/dsize,				(Wideoff)(h->wsize%dsize)/dsizepct);	putbuf(p); 	bw = 0;	/* max filled bucket */	memset(state, 0, sizeof(state));	for(m=0; m<hmsize; m++) {		p = getbuf(cw->cdev, hmaddr + m/BKPERBLK, Bread);		if(!p || checktag(p, Tbuck, hmaddr + m/BKPERBLK)) {			print("cwstats: checktag c bucket\n");			if(p)				putbuf(p);			return;		}		b = (Bucket*)p->iobuf + m%BKPERBLK;		ce = b->entry + CEPERBK;		nw = 0;		for(c=b->entry; c<ce; c++) {			s = c->state;			state[s]++;			if(s != Cnone && s != Cread)				nw++;		}		putbuf(p);		if(nw > bw)			bw = nw;	} 	for(s=Cnone; s<=Cerror; s++)		print("		%8lld %s\n", (Wideoff)state[s], cwnames[s]);	print("		cache %2lld%% full\n", ((Wideoff)bw*100)/CEPERBK);} intdumpblock(Device *dev){	Iobuf *p, *cb, *p1, *p2;	Cache *h;	Centry *c, *ce, *bc;	Bucket *b;	Off m, a, msize, maddr, wmax, caddr;	int s1, count;	Cw *cw; 	cw = dev->private;	if(cw == 0 || cw->nodump)		return 0; 	cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres);	h = (Cache*)cb->iobuf;	msize = h->msize;	maddr = h->maddr;	wmax = h->wmax;	caddr = h->caddr;	putbuf(cb); 	for(m=msize; m>=0; m--) {		a = cw->dbucket + 1;		if(a < 0 || a >= msize)			a = 0;		cw->dbucket = a;		p = getbuf(cw->cdev, maddr + a/BKPERBLK, Bread);		b = (Bucket*)p->iobuf + a%BKPERBLK;		ce = b->entry + CEPERBK;		bc = 0;		for(c=b->entry; c<ce; c++)			if(c->state == Cdump) {				if(bc == 0) {					bc = c;					continue;				}				if(c->waddr < cw->daddr) {					if(bc->waddr < cw->daddr &&					   bc->waddr > c->waddr)						bc = c;					continue;				}				if(bc->waddr < cw->daddr ||				   bc->waddr > c->waddr)					bc = c;			}		if(bc) {			c = bc;			goto found;		}		putbuf(p);	}	if(cw->ncopy) {		print("%lld blocks copied to worm\n", (Wideoff)cw->ncopy);		cw->ncopy = 0;	}	cw->nodump = 1;	return 0; found://///	a = a*CEPERBK + (c - b->entry) + caddr;	a = a + (c - b->entry)*msize + caddr;	p1 = getbuf(devnone, Cwdump1, 0);	count = 0; retry:	count++;	if(count > 10)		goto stop;	dpprint("dumpblock %lld\n", a);	if(devread(cw->cdev, a, p1->iobuf))		goto stop;	m = c->waddr;	cw->daddr = m;	s1 = devwrite(cw->wdev, m, p1->iobuf);	if(s1)		goto retry;	/*	 * reread and compare	 */	if(conf.dumpreread) {		p2 = getbuf(devnone, Cwdump2, 0);		s1 = devread(cw->wdev, m, p2->iobuf);		if(s1)			goto stop1;		if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) {			print("reread C%lld W%lld didnt compare\n", (Wideoff)a, (Wideoff)m);			goto stop1;		}		putbuf(p2);	} 	putbuf(p1);	if(conf.fastworm)		c->state = Cnone;	else		c->state = Cread;	p->flags |= Bmod;	putbuf(p); 	if(m > wmax) {		cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bres);		h = (Cache*)cb->iobuf;		if(m > h->wmax)			h->wmax = m;		putbuf(cb);	}	cw->ncopy++;	return 1; stop1:	putbuf(p2);	putbuf(p1);	c->state = Cdump1;	p->flags |= Bmod;	putbuf(p);	return 1; stop:	putbuf(p1);	putbuf(p);	print("stopping dump!!\n");	cw->nodump = 1;	return 0;} voidcwinit1(Device *dev){	Cw *cw;	static int first; 	cw = dev->private;	if(cw)		return; 	if(first++ == 0){		cmd_install("dump", "-- make dump backup to worm", cmd_dump);		cmd_install("dumpctl", "[on|off] -- automatic dumps", cmd_dumpctl);		cmd_install("statw", "-- cache/worm stats", cmd_statw);		cmd_install("cwcmd", "subcommand -- cache/worm errata", cmd_cwcmd);		roflag = flag_install("ro", "-- ro reads and writes");	}	cw = ialloc(sizeof(Cw), 0);	dev->private = cw; 	cw->allflag = 0;	dofilter(&cw->ncwio); 	cw->dev = dev;	cw->cdev = CDEV(dev);	cw->wdev = WDEV(dev);	cw->rodev = RDEV(dev); 	devinit(cw->cdev);	devinit(cw->wdev);} voidcwinit(Device *dev){	Cw *cw;	Cache *h;	Iobuf *cb, *p;	Off l, m; 	cwinit1(dev); 	cw = dev->private;	l = devsize(cw->wdev);	cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bres);	h = (Cache*)cb->iobuf;	h->toytime = toytime() + SECOND(30);	h->time = time();	m = h->wsize;	if(l != m) {		print("wdev changed size %lld to %lld\n", (Wideoff)m, (Wideoff)l);		h->wsize = l;		cb->flags |= Bmod;	} 	for(m=0; m<h->msize; m++) {		p = getbuf(cw->cdev, h->maddr + m/BKPERBLK, Bread);		if(!p || checktag(p, Tbuck, h->maddr + m/BKPERBLK))			panic("cwinit: checktag c bucket");		putbuf(p);	}	putbuf(cb);} Offcwsaddr(Device *dev){	Iobuf *cb;	Off sa; 	cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres);	sa = ((Cache*)cb->iobuf)->sbaddr;	putbuf(cb);	return sa;} Offcwraddr(Device *dev){	Iobuf *cb;	Off ra; 	switch(dev->type) {	default:		print("unknown dev in cwraddr %Z\n", dev);		return 1; 	case Devcw:		cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres);		ra = ((Cache*)cb->iobuf)->cwraddr;		break; 	case Devro:		cb = getbuf(CDEV(dev->ro.parent), CACHE_ADDR, Bread|Bres);		ra = ((Cache*)cb->iobuf)->roraddr;		break;	}	putbuf(cb);	return ra;} Devsizecwsize(Device *dev){	Iobuf *cb;	Devsize fs; 	cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres);	fs = ((Cache*)cb->iobuf)->fsize;	putbuf(cb);	return fs;}

Lines 1–500 of 2269.