2277 lines · 42.4 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * cached-worm device */#include "all.h" #define	CDEV(d)		((d)->cw.c)#define	WDEV(d)		((d)->cw.w)#define	RDEV(d)		((d)->cw.ro) enum {	DEBUG		= 0,	FIRST		= SUPER_ADDR, 	ADDFREE		= 100,	CACHE_ADDR	= SUPER_ADDR,	MAXAGE		= 10000,}; /* 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; 	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 dirs */	int	allflag;	/* global flag to recur on modified dirs */	Off	falsehits;	/* times recur found modified blocks */	struct {		char	name[500];		char	namepad[NAMELEN+10];	};}; static char* cwnames[] ={	[Cnone]		"none",	[Cdirty]	"dirty",	[Cdump]		"dump",	[Cread]		"read",	[Cwrite]	"write",	[Cdump1]	"dump1",	[Cerror]	"error", 	[Onone]		"none",	[Oread]		"read",	[Owrite]	"write",	[Ogrow]		"grow",	[Odump]		"dump",	[Orele]		"rele",}; int oldcachefmt = 1; Centry*	getcentry(Bucket*, Off);int	cwio(Device*, Off, void*, int);void	cmd_cwcmd(int, char*[]); /* * console command * initiate a dump */voidcmd_dump(int argc, char *argv[]){	Filsys *fs; 	fs = cons.curfs;	if(argc > 1)		fs = fsstr(argv[1]);	if(fs == 0) {		print("%s: unknown file system\n", argv[1]);		return;	}	cfsdump(fs);} /* * console command * worm stats */static voidcmd_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("\tfilesys %s\n", fs->name);//	print("\tnio   =%7W%7W%7W\n", cw->ncwio+0, cw->ncwio+1, cw->ncwio+2);	p = getbuf(dev, cwsaddr(dev), Brd);	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, Brd|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("\t\tmaddr  = %8lld\n", (Wideoff)hmaddr);	print("\t\tmsize  = %8lld\n", (Wideoff)hmsize);	print("\t\tcaddr  = %8lld\n", (Wideoff)h->caddr);	print("\t\tcsize  = %8lld\n", (Wideoff)h->csize);	print("\t\tsbaddr = %8lld\n", (Wideoff)h->sbaddr);	print("\t\tcraddr = %8lld %8lld\n",		(Wideoff)h->cwraddr, (Wideoff)sbcwraddr);	print("\t\troaddr = %8lld %8lld\n",		(Wideoff)h->roraddr, (Wideoff)sbroraddr);	/* print stats in terms of (first-)disc sides */	dsize = wormsizeside(dev, 0);	if (dsize < 1) {		if (DEBUG)			print("wormsizeside returned size %lld for %Z side 0\n",				(Wideoff)dsize, dev);		dsize = h->wsize;	/* it's probably a fake worm */		if (dsize < 1)			dsize = 1000;	/* don't divide by zero */	}	dsizepct = dsize/100;	print("\t\tfsize  = %8lld %8lld %2lld+%2lld%%\n", (Wideoff)h->fsize,		(Wideoff)sbfsize, (Wideoff)h->fsize/dsize,		(Wideoff)(h->fsize%dsize)/dsizepct);	print("\t\tslast  =          %8lld\n", (Wideoff)sblast);	print("\t\tsnext  =          %8lld\n", (Wideoff)sbnext);	print("\t\twmax   = %8lld          %2lld+%2lld%%\n",		(Wideoff)h->wmax, (Wideoff)h->wmax/dsize,		(Wideoff)(h->wmax%dsize)/dsizepct);	print("\t\twsize  = %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, Brd);		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("\t\t%6lld %s\n", (Wideoff)state[s], cwnames[s]);	print("\t\tcache %2lld%% full\n", ((Wideoff)bw*100)/CEPERBK);} intdumpblock(Device *dev){	Iobuf *p, *cb, *p1, *p2;	Cache *h;	Centry *c, *ce, *bc;	Bucket *b;	Off m, a, msize, maddr, wmax, caddr;	int s1, s2, count;	Cw *cw; 	cw = dev->private;	if(cw == 0 || cw->nodump)		return 0; 	cb = getbuf(cw->cdev, CACHE_ADDR, Brd|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, Brd);		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:	if (oldcachefmt)		a = a*CEPERBK + (c - b->entry) + caddr;	else		a += (c - b->entry)*msize + caddr;	p1 = getbuf(devnone, Cwdump1, 0);	count = 0; retry:	count++;	if(count > 10 || devread(cw->cdev, a, p1->iobuf))		goto stop;	m = c->waddr;	cw->daddr = m;	s1 = devwrite(cw->wdev, m, p1->iobuf);	if(s1) {		p2 = getbuf(devnone, Cwdump2, 0);		s2 = devread(cw->wdev, m, p2->iobuf);		if(s2) {			if(s1 == 0x61 && s2 == 0x60) {				putbuf(p2);				goto retry;			}			goto stop1;		}		if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE))			goto stop1;		putbuf(p2);	}	/*	 * reread and compare	 */	if(conf.dumpreread) {		p2 = getbuf(devnone, Cwdump2, 0);		s1 = devread(cw->wdev, m, p2->iobuf);		if(s1)			goto stop1;		if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) {			print("reread C%lld W%lld didnt compare\n",				(Wideoff)a, (Wideoff)m);			goto stop1;		}		putbuf(p2);	} 	putbuf(p1);	c->state = Cread;	p->flags |= Bmod;	putbuf(p); 	if(m > wmax) {		cb = getbuf(cw->cdev, CACHE_ADDR, Brd|Bmod|Bres);		h = (Cache*)cb->iobuf;		if(m > h->wmax)			h->wmax = m;		putbuf(cb);	}	cw->ncopy++;	return 1; stop1:	putbuf(p2);	putbuf(p1);	c->state = Cdump1;	p->flags |= Bmod;	putbuf(p);	return 1; stop:	putbuf(p1);	putbuf(p);	print("stopping dump!!\n");	cw->nodump = 1;	return 0;} voidcwinit1(Device *dev){	Cw *cw;	static int first; 	cw = dev->private;	if(cw)		return; 	if(first == 0) {		cmd_install("dump", "-- make dump backup to worm", cmd_dump);		cmd_install("statw", "-- cache/worm stats", cmd_statw);		cmd_install("cwcmd", "subcommand -- cache/worm errata", cmd_cwcmd);		roflag = flag_install("ro", "-- ro reads and writes");		first = 1;	}	cw = malloc(sizeof(Cw));	dev->private = cw; 	cw->allflag = 0; 	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, Brd|Bmod|Bres);	h = (Cache*)cb->iobuf;	h->toytime = toytime() + SECOND(30);	h->time = time(nil);	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, Brd);		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, Brd|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, Brd|Bres);		ra = ((Cache*)cb->iobuf)->cwraddr;		break; 	case Devro:		cb = getbuf(CDEV(dev->ro.parent), CACHE_ADDR, Brd|Bres);		ra = ((Cache*)cb->iobuf)->roraddr;		break;	}	putbuf(cb);	return ra;} Devsizecwsize(Device *dev){	Iobuf *cb;	Devsize fs; 	cb = getbuf(CDEV(dev), CACHE_ADDR, Brd|Bres);	fs = ((Cache*)cb->iobuf)->fsize;

Lines 1–500 of 2277.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t