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

📄 chk.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"all.h"#include	"mem.h"		/* for KZERO for PADDR *//* copied from ../pc/etherif.h; should probably be in all.h */#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))/* augmented Dentry */typedef struct {	Dentry	*d;	Off	qpath;	int	ns;} Extdentry;static	char*	abits;static	long	sizabits;static	char*	qbits;static	long	sizqbits;static	char*	name;static	long	sizname;static	Off	fstart;static	Off	fsize;static	Off	nfiles;static	Off	maxq;static	char*	calloc;static	Device*	dev;static	Off	ndup;static	Off	nused;static	Off	nfdup;static	Off	nqbad;static	Off	nfree;static	Off	nbad;static	int	mod;static	int	flags;static	int	ronly;static	int	cwflag;static	Devsize	sbaddr;static	Devsize	oldblock;static	int	depth;static	int	maxdepth;static	uchar	*lowstack, *startstack;/* local prototypes */static	int	fsck(Dentry*);static	void	ckfreelist(Superb*);static	void	mkfreelist(Superb*);static	void	trfreelist(Superb*);static	void	xaddfree(Device*, Off, Superb*, Iobuf*);static	void	xflush(Device*, Superb*, Iobuf*);static	Dentry*	maked(Off, int, Off);static	void	modd(Off, int, Dentry*);static	void	xread(Off, Off);static	int	amark(Off);static	int	fmark(Off);static	int	ftest(Off);static	void	missing(void);static	void	qmark(Off);static	void*	malloc(ulong);static	Iobuf*	xtag(Off, int, Off);staticvoid*malloc(ulong n){	char *p, *q;	p = (char *)ROUNDUP((ulong)calloc, BY2WD);	q = p+n;	if(PADDR(q) >= conf.mem)		panic("check: mem size");	calloc = q;	memset(p, 0, n);	return p;}/* * check flags */enum{	Crdall	= (1<<0),	/* read all files */	Ctag	= (1<<1),	/* rebuild tags */	Cpfile	= (1<<2),	/* print files */	Cpdir	= (1<<3),	/* print directories */	Cfree	= (1<<4),	/* rebuild free list */	Csetqid	= (1<<5),	/* resequence qids */	Cream	= (1<<6),	/* clear all bad tags */	Cbad	= (1<<7),	/* clear all bad blocks */	Ctouch	= (1<<8),	/* touch old dir and indir */	Ctrim	= (1<<9),   /* trim fsize back to fit when checking free list */};staticstruct{	char*	option;	long	flag;} ckoption[] ={	"rdall",	Crdall,	"tag",		Ctag,	"pfile",	Cpfile,	"pdir",		Cpdir,	"free",		Cfree,	"setqid",	Csetqid,	"ream",		Cream,	"bad",		Cbad,	"touch",	Ctouch,	"trim",		Ctrim,	0,};voidcmd_check(int argc, char *argv[]){	long f, i;	long flag;	Off raddr;	Filsys *fs;	Iobuf *p;	Superb *sb;	Dentry *d;	flag = 0;	for(i=1; i<argc; i++) {		for(f=0; ckoption[f].option; f++)			if(strcmp(argv[i], ckoption[f].option) == 0)				goto found;		print("unknown check option %s\n", argv[i]);		for(f=0; ckoption[f].option; f++)			print("	%s\n", ckoption[f].option);		return;	found:		flag |= ckoption[f].flag;	}	fs = cons.curfs;	dev = fs->dev;	ronly = (dev->type == Devro);	cwflag = (dev->type == Devcw) | (dev->type == Devro);	if(!ronly)		wlock(&mainlock);		/* check */	/*	 * ialloc(0, 1) doesn't actually allocate any storage, and may	 * return the same address each time.  see iobufinit().	 * check assumes that the rest of memory, from ialloc(0, 1)	 * up, is available to it, but does at least check in malloc().	 */	calloc = (char*)ialloc(0, 1) + 100000;	flags = flag;	sizqbits = ((1<<22) + 7) / 8;		/* botch */	qbits = malloc(sizqbits);	sbaddr = superaddr(dev);	raddr = getraddr(dev);	p = xtag(sbaddr, Tsuper, QPSUPER);	if(!p)		goto out;	sb = (Superb*)p->iobuf;	fstart = 2;	cons.noage = 1;	fsize = sb->fsize;	sizabits = (fsize-fstart + 7)/8;	abits = malloc(sizabits);	sizname = 4000;	name = malloc(sizname);	sizname -= NAMELEN+10;	/* for safety */	mod = 0;	nfree = 0;	nfdup = 0;	nused = 0;	nbad = 0;	ndup = 0;	nqbad = 0;	depth = 0;	maxdepth = 0;	if(flags & Ctouch) {		/* round fsize down to start of current side */		int s;		Devsize dsize;		oldblock = 0;		for (s = 0; dsize = wormsizeside(dev, s),		     dsize > 0 && oldblock + dsize < fsize; s++)			oldblock += dsize;		print("oldblock = %lld\n", (Wideoff)oldblock);	}	amark(sbaddr);	if(cwflag) {		amark(sb->roraddr);		amark(sb->next);	}	print("checking filsys: %s\n", fs->name);	nfiles = 0;	maxq = 0;	d = maked(raddr, 0, QPROOT);	if(d) {		amark(raddr);		if(fsck(d))			modd(raddr, 0, d);		depth--;		calloc -= sizeof(Dentry);		if(depth)			print("depth not zero on return\n");	}	if(flags & Cfree) {		if(cwflag)			trfreelist(sb);		else			mkfreelist(sb);	}	if(sb->qidgen < maxq)		print("qid generator low path=%lld maxq=%lld\n",			(Wideoff)sb->qidgen, (Wideoff)maxq);	if(!(flags & Cfree))		ckfreelist(sb);	if(mod) {		sb->qidgen = maxq;		print("file system was modified\n");		settag(p, Tsuper, QPNONE);	}	print("nfiles = %lld\n", (Wideoff)nfiles);	print("fsize  = %lld\n", (Wideoff)fsize);	print("nused  = %lld\n", (Wideoff)nused);	print("ndup   = %lld\n", (Wideoff)ndup);	print("nfree  = %lld\n", (Wideoff)nfree);	print("tfree  = %lld\n", (Wideoff)sb->tfree);	print("nfdup  = %lld\n", (Wideoff)nfdup);	print("nmiss  = %lld\n", (Wideoff)fsize-fstart-nused-nfree);	print("nbad   = %lld\n", (Wideoff)nbad);	print("nqbad  = %lld\n", (Wideoff)nqbad);	print("maxq   = %lld\n", (Wideoff)maxq);	print("base stack=%ld\n", &u->stack[sizeof(u->stack)] - startstack);	print("high stack=%ld of %d\n", &u->stack[sizeof(u->stack)] - lowstack,		MAXSTACK);	/* high-water mark of stack usage */	print("deepest recursion=%d\n", maxdepth-1);	/* one-origin */	if(!cwflag)		missing();out:	cons.noage = 0;	putbuf(p);	if(!ronly)		wunlock(&mainlock);}/* * if *blkp is already allocated and Cbad is set, zero it. * returns *blkp if it's free, else 0. */static Offblkck(Off *blkp, int *flgp){	Off a = *blkp;	if(amark(a)) {		if(flags & Cbad) {			*blkp = 0;			*flgp |= Bmod;		}		a = 0;	}	return a;}/* * if a block address within a Dentry, *blkp, is already allocated * and Cbad is set, zero it. * stores 0 into *resp if already allocated, else stores *blkp. * returns dmod count. */static intdaddrck(Off *blkp, Off *resp){	int dmod = 0;	if(amark(*blkp)) {		if(flags & Cbad) {			*blkp = 0;			dmod++;		}		*resp = 0;	} else		*resp = *blkp;	return dmod;}/* * under Ctouch, read block `a' if it's in range. * returns dmod count. */static inttouch(Off a){	if((flags&Ctouch) && a < oldblock) {		Iobuf *pd = getbuf(dev, a, Bread|Bmod);		if(pd)			putbuf(pd);		return 1;	}	return 0;}/* * if d is a directory, touch it and check all its entries in block a. * if not, under Crdall, read a. * returns dmod count. */static intdirck(Extdentry *ed, Off a){	int k, dmod = 0;	if(ed->d->mode & DDIR) {		dmod += touch(a);		for(k=0; k<DIRPERBUF; k++) {			Dentry *nd = maked(a, k, ed->qpath);			if(nd == nil)				break;			if(fsck(nd)) {				modd(a, k, nd);				dmod++;			}			depth--;			calloc -= sizeof(Dentry);			name[ed->ns] = 0;		}	} else if(flags & Crdall)		xread(a, ed->qpath);	return dmod;}/* * touch a, check a's tag for Tind1, Tind2, etc. * if the tag is right, validate each block number in the indirect block, * and check each block (mostly in case we are reading a huge directory). */static intindirck(Extdentry *ed, Off a, int tag){	int i, dmod = 0;	Iobuf *p1;	if (a == 0)		return dmod;	dmod = touch(a);	if (p1 = xtag(a, tag, ed->qpath)) {		for(i=0; i<INDPERBUF; i++) {			a = blkck(&((Off *)p1->iobuf)[i], &p1->flags);			if (a)				/*				 * check each block named in this				 * indirect(^n) block (a).				 */				if (tag == Tind1)					dmod +=   dirck(ed, a);				else					dmod += indirck(ed, a, tag-1);		}		putbuf(p1);	}	return dmod;}static intindiraddrck(Extdentry *ed, Off *indirp, int tag){	int dmod;	Off a;	dmod = daddrck(indirp, &a);	return dmod + indirck(ed, a, tag);}/* if result is true, *d was modified */staticintfsck(Dentry *d){	int i, dmod;	Extdentry edent;	depth++;	if(depth >= maxdepth) {		maxdepth = depth;		/*		 * On a 386 each recursion costs ~100 bytes (more for		 * directories with indirect blocks).  Base stack usage		 * is about ~320 bytes, leaving room for ~156 recursions		 * (assuming a 16000-byte stack).  Typical checks use		 * around 12 recursions.		 * Alternatives here might be to give the check process		 * a much bigger stack or rewrite it without recursion,		 * but it hardly seems worth expending effort on.		 */		if(maxdepth >= MAXSTACK/(100+10)) {			print("check: max depth exceeded: %s\n", name);			return 0;		}	}	if (lowstack == nil)		startstack = lowstack = (uchar *)&edent;	/* more precise check, assumes downward-growing stack */	if ((uchar *)&edent < lowstack)		lowstack = (uchar *)&edent;	if ((uchar *)&edent < &u->stack[500]) {		print("check: stack nearly full: %s\n", name);		return 0;	}	/* check that entry is allocated */	if(!(d->mode & DALLOC))		return 0;	nfiles++;	/* we stash qpath & ns in an Extdentry for eventual use by dirck() */	memset(&edent, 0, sizeof edent);	edent.d = d;	/* check name */	edent.ns = strlen(name);	i = strlen(d->name);	if(i >= NAMELEN) {		d->name[NAMELEN-1] = 0;		print("%s->name (%s) not terminated\n", name, d->name);		return 0;	}	edent.ns += i;	if(edent.ns >= sizname) {

⌨️ 快捷键说明

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