⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cw.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "all.h"#define	DEBUG		0#define	FIRST		SUPER_ADDR#define	ADDFREE		(100)#define	CACHE_ADDR	SUPER_ADDR#define	MAXAGE		10000#define	CDEV(d)		(d->cw.c)#define	WDEV(d)		(d->cw.w)#define	RDEV(d)		(d->cw.ro)/* cache state */enum{	/* states -- beware these are recorded on the cache */				/*    cache    worm	*/	Cnone = 0,		/*	0	?	*/	Cdirty,			/*	1	0	*/	Cdump,			/*	1	0->1	*/	Cread,			/*	1	1	*/	Cwrite,			/*	2	1	*/	Cdump1,			/* inactive form of dump */	Cerror,	/* opcodes -- these are not recorded */	Onone,	Oread,	Owrite,	Ogrow,	Odump,	Orele,	Ofree,};typedef	struct	Cw	Cw;struct	Cw{	Device*	dev;	Device*	cdev;	Device*	wdev;	Device*	rodev;	Cw*	link;	Filter	ncwio[3];	int	dbucket;	/* last bucket dumped */	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 */voidcmd_dump(int argc, char *argv[]){	Filsys *fs;	fs = cons.curfs;	if(argc > 1)		fs = fsstr(argv[1]);	if(fs == 0) {		print("%s: unknown file system\n", argv[1]);		return;	}	cfsdump(fs);}/* * console command * worm stats */staticvoidcmd_statw(int, char*[]){	Filsys *fs;	Iobuf *p;	Superb *sb;	Cache *h;	Bucket *b;	Centry *c, *ce;	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   =%7W%7W%7W\n", cw->ncwio+0, cw->ncwio+1, cw->ncwio+2);	p = getbuf(dev, cwsaddr(dev), Bread);	if(!p || checktag(p, Tsuper, QPSUPER)) {		print("cwstats: checktag super\n");		if(p) {			putbuf(p);			p = 0;		}	}	if(p) {		sb = (Superb*)p->iobuf;		sbfsize = sb->fsize;		sbcwraddr = sb->cwraddr;		sbroraddr = sb->roraddr;		sblast = sb->last;		sbnext = sb->next;		putbuf(p);	}	p = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres);	if(!p || checktag(p, Tcache, QPSUPER)) {		print("cwstats: checktag c bucket\n");		if(p)			putbuf(p);		return;	}	h = (Cache*)p->iobuf;	hmaddr = h->maddr;	hmsize = h->msize;	print("		maddr  = %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) {		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("		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("		%6lld %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, s2, count;	Cw *cw;	cw = dev->private;	if(cw == 0 || cw->nodump)		return 0;	cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres);	h = (Cache*)cb->iobuf;	msize = h->msize;	maddr = h->maddr;	wmax = h->wmax;	caddr = h->caddr;	putbuf(cb);	for(m=msize; m>=0; m--) {		a = cw->dbucket + 1;		if(a < 0 || a >= msize)			a = 0;		cw->dbucket = a;		p = getbuf(cw->cdev, maddr + a/BKPERBLK, Bread);		b = (Bucket*)p->iobuf + a%BKPERBLK;		ce = b->entry + CEPERBK;		bc = 0;		for(c=b->entry; c<ce; c++)			if(c->state == Cdump) {				if(bc == 0) {					bc = c;					continue;				}				if(c->waddr < cw->daddr) {					if(bc->waddr < cw->daddr &&					   bc->waddr > c->waddr)						bc = c;					continue;				}				if(bc->waddr < cw->daddr ||				   bc->waddr > c->waddr)					bc = c;			}		if(bc) {			c = bc;			goto found;		}		putbuf(p);	}	if(cw->ncopy) {		print("%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;	p1 = getbuf(devnone, Cwdump1, 0);	count = 0;retry:	count++;	if(count > 10)		goto stop;	if(devread(cw->cdev, a, p1->iobuf))		goto stop;	m = c->waddr;	cw->daddr = m;	s1 = devwrite(cw->wdev, m, p1->iobuf);	if(s1) {		p2 = getbuf(devnone, Cwdump2, 0);		s2 = devread(cw->wdev, m, p2->iobuf);		if(s2) {			if(s1 == 0x61 && s2 == 0x60) {				putbuf(p2);				goto retry;			}			goto stop1;		}		if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE))			goto stop1;		putbuf(p2);	}	/*	 * reread and compare	 */	if(conf.dumpreread) {		p2 = getbuf(devnone, Cwdump2, 0);		s1 = devread(cw->wdev, m, p2->iobuf);		if(s1)			goto stop1;		if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) {			print("reread C%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, Bread|Bmod|Bres);		h = (Cache*)cb->iobuf;		if(m > h->wmax)			h->wmax = m;		putbuf(cb);	}	cw->ncopy++;	return 1;stop1:	putbuf(p2);	putbuf(p1);	c->state = Cdump1;	p->flags |= Bmod;	putbuf(p);	return 1;stop:	putbuf(p1);	putbuf(p);	print("stopping dump!!\n");	cw->nodump = 1;	return 0;}voidcwinit1(Device *dev){	Cw *cw;	static int first;	cw = dev->private;	if(cw)		return;	if(first == 0) {		cmd_install("dump", "-- make dump backup to worm", cmd_dump);		cmd_install("statw", "-- cache/worm stats", cmd_statw);		cmd_install("cwcmd", "subcommand -- cache/worm errata", cmd_cwcmd);		roflag = flag_install("ro", "-- ro reads and writes");		first = 1;	}	cw = ialloc(sizeof(Cw), 0);	dev->private = cw;	cw->allflag = 0;	dofilter(cw->ncwio+0, C0a, C0b, 1);	dofilter(cw->ncwio+1, C1a, C1b, 1);	dofilter(cw->ncwio+2, C2a, C2b, 1);	cw->dev = dev;	cw->cdev = CDEV(dev);	cw->wdev = WDEV(dev);	cw->rodev = RDEV(dev);	devinit(cw->cdev);	devinit(cw->wdev);}voidcwinit(Device *dev){	Cw *cw;	Cache *h;	Iobuf *cb, *p;	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;}intcwread(Device *dev, Off b, void *c){	return cwio(dev, b, c, Oread) == Cerror;}intcwwrite(Device *dev, Off b, void *c){	return cwio(dev, b, c, Owrite) == Cerror;}introread(Device *dev, Off b, void *c){	Device *d;	int s;	/*	 * maybe better is to try buffer pool first	 */	d = dev->ro.parent;	if(d == 0 || d->type != Devcw ||	   d->private == 0 || RDEV(d) != dev) {		print("bad rodev %Z\n", dev);		return 1;	}	s = cwio(d, b, 0, Onone);	if(s == Cdump || s == Cdump1 || s == Cread) {		s = cwio(d, b, c, Oread);		if(s == Cdump || s == Cdump1 || s == Cread) {			if(cons.flags & roflag)				print("roread: %Z %lld -> %Z(hit)\n", dev, (Wideoff)b, d);			return 0;		}	}	if(cons.flags & roflag)		print("roread: %Z %lld -> %Z(miss)\n", dev, (Wideoff)b, WDEV(d));	return devread(WDEV(d), b, c);}intcwio(Device *dev, Off addr, void *buf, int opcode){	Iobuf *p, *p1, *p2, *cb;	Cache *h;	Bucket *b;	Centry *c;	Off bn, a1, a2, max, newmax;	int state;	Cw *cw;	cw = dev->private;	cw->ncwio[0].count++;	cw->ncwio[1].count++;	cw->ncwio[2].count++;	cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres);	h = (Cache*)cb->iobuf;	if(toytime() >= h->toytime) {		cb->flags |= Bmod;		h->toytime = toytime() + SECOND(30);		h->time = time();	}	if(addr < 0) {		putbuf(cb);		return Cerror;	}	bn = addr % h->msize;	a1 = h->maddr + bn/BKPERBLK;	a2 = bn*CEPERBK + h->caddr;	max = h->wmax;	putbuf(cb);	newmax = 0;	p = getbuf(cw->cdev, a1, Bread|Bmod);	if(!p || checktag(p, Tbuck, a1))		panic("cwio: checktag c bucket");	b = (Bucket*)p->iobuf + bn%BKPERBLK;	c = getcentry(b, addr);	if(c == 0) {		putbuf(p);		print("%Z disk cache bucket %lld is full\n", cw->cdev, (Wideoff)a1);		return Cerror;	}	a2 += c - b->entry;	state = c->state;	switch(opcode)	{	default:		goto bad;	case Onone:		break;	case Oread:		switch(state) {		default:			goto bad;		case Cread:			if(!devread(cw->cdev, a2, buf))				break;			c->state = Cnone;		case Cnone:			if(devread(cw->wdev, addr, buf)) {				state = Cerror;				break;			}			if(addr > max)				newmax = addr;			if(!devwrite(cw->cdev, a2, buf))				c->state = Cread;			break;		case Cdirty:		case Cdump:		case Cdump1:		case Cwrite:			if(devread(cw->cdev, a2, buf))				state = Cerror;			break;		}		break;	case Owrite:		switch(state) {		default:			goto bad;		case Cdump:		case Cdump1:			/*			 * this is hard part -- a dump block must be			 * sent to the worm if it is rewritten.			 * if this causes an error, there is no			 * place to save the dump1 data. the block			 * is just reclassified as 'dump1' (botch)			 */			p1 = getbuf(devnone, Cwio1, 0);			if(devread(cw->cdev, a2, p1->iobuf)) {				putbuf(p1);				print("cwio: write induced dump error - r cache\n");			casenone:				if(devwrite(cw->cdev, a2, buf)) {					state = Cerror;					break;				}				c->state = Cdump1;				break;			}			if(devwrite(cw->wdev, addr, p1->iobuf)) {				p2 = getbuf(devnone, Cwio2, 0);				if(devread(cw->wdev, addr, p2->iobuf)) {					putbuf(p1);					putbuf(p2);					print("cwio: write induced dump error - r+w worm\n");					goto casenone;				}				if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) {					putbuf(p1);					putbuf(p2);					print("cwio: write induced dump error - w worm\n");					goto casenone;				}				putbuf(p2);			}			putbuf(p1);			c->state = Cread;			if(addr > max)				newmax = addr;			cw->ncopy++;		case Cnone:		case Cread:			if(devwrite(cw->cdev, a2, buf)) {				state = Cerror;				break;			}			c->state = Cwrite;			break;		case Cdirty:		case Cwrite:			if(devwrite(cw->cdev, a2, buf))				state = Cerror;			break;		}		break;	case Ogrow:		if(state != Cnone) {			print("%Z for block %lld cwgrow with state = %s\n",				cw->cdev, (Wideoff)addr, cwnames[state]);			break;		}		c->state = Cdirty;		break;	case Odump:		if(state != Cdirty) {	/* BOTCH */			print("%Z for block %lld cwdump with state = %s\n",				cw->cdev, (Wideoff)addr, cwnames[state]);			break;		}		c->state = Cdump;		cw->ndump++;	/* only called from dump command */		break;	case Orele:		if(state != Cwrite) {			if(state != Cdump1)				print("%Z for block %lld cwrele with state = %s\n",					cw->cdev, (Wideoff)addr, cwnames[state]);			break;		}		c->state = Cnone;		break;	case Ofree:		if(state == Cwrite || state == Cread)			c->state = Cnone;		break;	}	if(DEBUG)		print("cwio: %Z %lld s=%s o=%s ns=%s\n",			dev, (Wideoff)addr, cwnames[state],			cwnames[opcode],			cwnames[c->state]);	putbuf(p);	if(newmax) {		cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bres);		h = (Cache*)cb->iobuf;		if(newmax > h->wmax)			h->wmax = newmax;		putbuf(cb);	}	return state;bad:	print("%Z block %lld cw state = %s; cw opcode = %s",		dev, (Wideoff)addr, cwnames[state], cwnames[opcode]);	return Cerror;}extern Filsys* dev2fs(Device *dev);intcwgrow(Device *dev, Superb *sb, int uid){	char str[NAMELEN];	Iobuf *cb;	Cache *h;	Filsys *filsys;	Off fs, nfs, ws;	cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bmod|Bres);	h = (Cache*)cb->iobuf;	ws = h->wsize;	fs = h->fsize;	if(fs >= ws)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -