663 lines · 10.5 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. */ #include	"all.h" #define	DSIZE		546000#define	MAXDEPTH	100 static	char*	abits;static	long	sizabits;static	char*	qbits;static	long	sizqbits;static	char*	name;static	long	sizname;static	long	fstart;static	long	fsize;static	long	nfiles;static	long	maxq;static	char*	fence;static	char*	fencebase;static	Device	dev;static	long	ndup;static	long	nused;static	long	nfdup;static	long	nqbad;static	long	nfree;static	long	nbad;static	int	mod;static	int	flags;static	int	ronly;static	int	cwflag;static	long	sbaddr;static	long	oldblock;static	int	depth;static	int	maxdepth; /* local prototypes */static	int	fsck(Dentry*);static	void	ckfreelist(Superb*);static	void	mkfreelist(Superb*);static	Dentry*	maked(long, int, long);static	void	modd(long, int, Dentry*);static	void	xread(long, long);static	int	amark(long);static	int	fmark(long);static	void	missing(void);static	void	qmark(long);static	void*	zalloc(ulong);static	void*	dalloc(ulong);static	Iobuf*	xtag(long, int, long); staticvoid*zalloc(ulong n){	char *p; 	p = malloc(n);	if(p == 0)		panic("zalloc: out of memory\n");	memset(p, '\0', n);	return p;} staticvoid*dalloc(ulong n){	char *p; 	if(fencebase == 0)		fence = fencebase = zalloc(MAXDEPTH*sizeof(Dentry));	p = fence;	fence += n;	if(fence > fencebase+MAXDEPTH*sizeof(Dentry))		panic("dalloc too much memory\n");	return p;} voidcheck(Filsys *fs, long flag){	Iobuf *p;	Superb *sb;	Dentry *d;	long raddr;	long nqid; 	wlock(&mainlock);	dev = fs->dev;	flags = flag;	fence = fencebase; 	sizname = 4000;	name = zalloc(sizname);	sizname -= NAMELEN+10;	/* for safety */ 	sbaddr = superaddr(dev);	raddr = getraddr(dev);	p = xtag(sbaddr, Tsuper, QPSUPER);	if(!p){		cprint("bad superblock\n");		goto out;	}	sb = (Superb*)p->iobuf;	fstart = 1; 	fsize = sb->fsize;	sizabits = (fsize-fstart + 7)/8;	abits = zalloc(sizabits); 	nqid = sb->qidgen+100;		/* not as much of a botch */	if(nqid > 1024*1024*8)		nqid = 1024*1024*8;	if(nqid < 64*1024)		nqid = 64*1024; 	sizqbits = (nqid+7)/8;	qbits = zalloc(sizqbits); 	mod = 0;	nfree = 0;	nfdup = 0;	nused = 0;	nbad = 0;	ndup = 0;	nqbad = 0;	depth = 0;	maxdepth = 0; 	if(flags & Ctouch) {		oldblock = fsize/DSIZE;		oldblock *= DSIZE;		if(oldblock < 0)			oldblock = 0;		cprint("oldblock = %ld\n", oldblock);	}	if(amark(sbaddr))		{}	if(cwflag) {		if(amark(sb->roraddr))			{}		if(amark(sb->next))			{}	} 	if(!(flags & Cquiet))		cprint("checking file system: %s\n", fs->name);	nfiles = 0;	maxq = 0; 	d = maked(raddr, 0, QPROOT);	if(d) {		if(amark(raddr))			{}		if(fsck(d))			modd(raddr, 0, d);		depth--;		fence -= sizeof(Dentry);		if(depth)			cprint("depth not zero on return\n");	} 	if(flags & Cfree) {		mkfreelist(sb);		sb->qidgen = maxq;		settag(p, Tsuper, QPNONE);	} 	if(sb->qidgen < maxq)		cprint("qid generator low path=%ld maxq=%ld\n",			sb->qidgen, maxq);	if(!(flags & Cfree))		ckfreelist(sb);	if(mod) {		cprint("file system was modified\n");		settag(p, Tsuper, QPNONE);	} 	if(!(flags & Cquiet)){		cprint("%8ld files\n", nfiles);		cprint("%8ld blocks in the file system\n", fsize-fstart);		cprint("%8ld used blocks\n", nused);		cprint("%8ld free blocks\n", sb->tfree);	}	if(!(flags & Cfree)){		if(nfree != sb->tfree)			cprint("%8ld free blocks found\n", nfree);		if(nfdup)			cprint("%8ld blocks duplicated in the free list\n", nfdup);		if(fsize-fstart-nused-nfree)			cprint("%8ld missing blocks\n", fsize-fstart-nused-nfree);	}	if(ndup)		cprint("%8ld address duplications\n", ndup);	if(nbad)		cprint("%8ld bad block addresses\n", nbad);	if(nqbad)		cprint("%8ld bad qids\n", nqbad);	if(!(flags & Cquiet))		cprint("%8ld maximum qid path\n", maxq);	missing(); out:	if(p)		putbuf(p);	free(abits);	free(name);	free(qbits);	wunlock(&mainlock);} staticinttouch(long a){	Iobuf *p; 	if((flags&Ctouch) && a && a < oldblock){		p = getbuf(dev, a, Bread|Bmod);		if(p)			putbuf(p);		return 1;	}	return 0;} staticintcheckdir(long a, long qpath){	Dentry *nd;	int i, ns, dmod; 	ns = strlen(name);	dmod = touch(a);	for(i=0; i<DIRPERBUF; i++) {		nd = maked(a, i, qpath);		if(!nd)			break;		if(fsck(nd)) {			modd(a, i, nd);			dmod++;		}		depth--;		fence -= sizeof(Dentry);		name[ns] = 0;	}	name[ns] = 0;	return dmod;} staticintcheckindir(long a, Dentry *d, long qpath){	Iobuf *p;	int i, dmod; 	dmod = touch(a);	p = xtag(a, Tind1, qpath);	if(!p)		return dmod;	for(i=0; i<INDPERBUF; i++) {		a = ((long*)p->iobuf)[i];		if(!a)			continue;		if(amark(a)) {			if(flags & Cbad) {				((long*)p->iobuf)[i] = 0;				p->flags |= Bmod;			}			continue;		}		if(d->mode & DDIR)			dmod += checkdir(a, qpath);		else if(flags & Crdall)			xread(a, qpath);	}	putbuf(p);	return dmod;} staticintfsck(Dentry *d){	char *s;	Rune r;	Iobuf *p;	int l, i, ns, dmod;	long a, qpath; 	depth++;	if(depth >= maxdepth){		maxdepth = depth;		if(maxdepth >= MAXDEPTH){			cprint("max depth exceeded: %s\n", name);			return 0;		}	}	dmod = 0;	if(!(d->mode & DALLOC))		return 0;	nfiles++; 	ns = strlen(name);	i = strlen(d->name);	if(i >= NAMELEN){		d->name[NAMELEN-1] = 0;		cprint("%s->name (%s) not terminated\n", name, d->name);		return 0;	}	ns += i;	if(ns >= sizname){		cprint("%s->name (%s) name too large\n", name, d->name);		return 0;	}	for (s = d->name; *s; s += l){		l = chartorune(&r, s);		if (r == Runeerror)			for (i = 0; i < l; i++){				s[i] = '_';				cprint("%s->name (%s) bad UTF\n", name, d->name);				dmod++;			}	}	strcat(name, d->name); 	if(d->mode & DDIR){		if(ns > 1)			strcat(name, "/");		if(flags & Cpdir)			cprint("%s\n", name);	} else	if(flags & Cpfile)		cprint("%s\n", name); 	qpath = d->qid.path & ~QPDIR;	qmark(qpath);	if(qpath > maxq)		maxq = qpath;	for(i=0; i<NDBLOCK; i++) {		a = d->dblock[i];		if(!a)			continue;		if(amark(a)) {			d->dblock[i] = 0;			dmod++;			continue;		}		if(d->mode & DDIR)			dmod += checkdir(a, qpath);		else if(flags & Crdall)			xread(a, qpath);	}	a = d->iblock;	if(a && amark(a)) {		d->iblock = 0;		dmod++;	}	else if(a)		dmod += checkindir(a, d, qpath); 	a = d->diblock;	if(a && amark(a)) {		d->diblock = 0;		return dmod + 1;	}	dmod += touch(a);	if(p = xtag(a, Tind2, qpath)){		for(i=0; i<INDPERBUF; i++){			a = ((long*)p->iobuf)[i];			if(!a)				continue;			if(amark(a)) {				if(flags & Cbad) {					((long*)p->iobuf)[i] = 0;					p->flags |= Bmod;				}				continue;			}			dmod += checkindir(a, d, qpath);		}		putbuf(p);	}	return dmod;} staticvoidckfreelist(Superb *sb){	long a, lo, hi;	int n, i;	Iobuf *p;	Fbuf *fb;  	strcpy(name, "free list");	cprint("check %s\n", name);	fb = &sb->fbuf;	a = sbaddr;	p = 0;	lo = 0;	hi = 0;	for(;;) {		n = fb->nfree;		if(n < 0 || n > FEPERBUF) {			cprint("check: nfree bad %ld\n", a);			break;		}		for(i=1; i<n; i++) {			a = fb->free[i];			if(a && !fmark(a)) {				if(!lo || lo > a)					lo = a;				if(!hi || hi < a)					hi = a;			}		}		a = fb->free[0];		if(!a)			break;		if(fmark(a))			break;		if(!lo || lo > a)			lo = a;		if(!hi || hi < a)			hi = a;		if(p)			putbuf(p);		p = xtag(a, Tfree, QPNONE);		if(!p)			break;		fb = (Fbuf*)p->iobuf;	}	if(p)		putbuf(p);	cprint("lo = %ld; hi = %ld\n", lo, hi);} /* * make freelist from scratch */staticvoidmkfreelist(Superb *sb){	long a;	int i, b; 	strcpy(name, "free list");	memset(&sb->fbuf, 0, sizeof(sb->fbuf));	sb->fbuf.nfree = 1;	sb->tfree = 0;	for(a=fsize-fstart-1; a >= 0; a--) {		i = a/8;		if(i < 0 || i >= sizabits)			continue;		b = 1 << (a&7);		if(abits[i] & b)			continue;		addfree(dev, fstart+a, sb);		abits[i] |= b;	}} staticDentry*maked(long a, int s, long qpath){	Iobuf *p;	Dentry *d, *d1; 	p = xtag(a, Tdir, qpath);	if(!p)		return 0;	d = getdir(p, s);	d1 = dalloc(sizeof(Dentry));	memmove(d1, d, sizeof(Dentry));	putbuf(p);	return d1;} staticvoidmodd(long a, int s, Dentry *d1){	Iobuf *p;	Dentry *d; 	if(!(flags & Cbad))		return;

Lines 1–500 of 663.