xref: /plan9/sys/src/cmd/disk/kfs/chk.c (revision 7611b47f1229c7132642a0d31563e92d74d44f86)
13e12c5d1SDavid du Colombier #include	"all.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier #define	DSIZE		546000
43e12c5d1SDavid du Colombier #define	MAXDEPTH	100
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier static	char*	abits;
73e12c5d1SDavid du Colombier static	long	sizabits;
83e12c5d1SDavid du Colombier static	char*	qbits;
93e12c5d1SDavid du Colombier static	long	sizqbits;
103e12c5d1SDavid du Colombier static	char*	name;
113e12c5d1SDavid du Colombier static	long	sizname;
123e12c5d1SDavid du Colombier static	long	fstart;
133e12c5d1SDavid du Colombier static	long	fsize;
143e12c5d1SDavid du Colombier static	long	nfiles;
153e12c5d1SDavid du Colombier static	long	maxq;
167dd7cddfSDavid du Colombier static	char*	fence;
177dd7cddfSDavid du Colombier static	char*	fencebase;
183e12c5d1SDavid du Colombier static	Device	dev;
193e12c5d1SDavid du Colombier static	long	ndup;
203e12c5d1SDavid du Colombier static	long	nused;
213e12c5d1SDavid du Colombier static	long	nfdup;
223e12c5d1SDavid du Colombier static	long	nqbad;
233e12c5d1SDavid du Colombier static	long	nfree;
243e12c5d1SDavid du Colombier static	long	nbad;
253e12c5d1SDavid du Colombier static	int	mod;
263e12c5d1SDavid du Colombier static	int	flags;
273e12c5d1SDavid du Colombier static	int	ronly;
283e12c5d1SDavid du Colombier static	int	cwflag;
293e12c5d1SDavid du Colombier static	long	sbaddr;
303e12c5d1SDavid du Colombier static	long	oldblock;
313e12c5d1SDavid du Colombier static	int	depth;
323e12c5d1SDavid du Colombier static	int	maxdepth;
333e12c5d1SDavid du Colombier 
343e12c5d1SDavid du Colombier /* local prototypes */
353e12c5d1SDavid du Colombier static	int	fsck(Dentry*);
363e12c5d1SDavid du Colombier static	void	ckfreelist(Superb*);
373e12c5d1SDavid du Colombier static	void	mkfreelist(Superb*);
383e12c5d1SDavid du Colombier static	Dentry*	maked(long, int, long);
393e12c5d1SDavid du Colombier static	void	modd(long, int, Dentry*);
403e12c5d1SDavid du Colombier static	void	xread(long, long);
413e12c5d1SDavid du Colombier static	int	amark(long);
423e12c5d1SDavid du Colombier static	int	fmark(long);
433e12c5d1SDavid du Colombier static	void	missing(void);
443e12c5d1SDavid du Colombier static	void	qmark(long);
453e12c5d1SDavid du Colombier static	void*	zalloc(ulong);
463e12c5d1SDavid du Colombier static	void*	dalloc(ulong);
473e12c5d1SDavid du Colombier static	Iobuf*	xtag(long, int, long);
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier static
503e12c5d1SDavid du Colombier void*
zalloc(ulong n)513e12c5d1SDavid du Colombier zalloc(ulong n)
523e12c5d1SDavid du Colombier {
533e12c5d1SDavid du Colombier 	char *p;
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier 	p = malloc(n);
563e12c5d1SDavid du Colombier 	if(p == 0)
573e12c5d1SDavid du Colombier 		panic("zalloc: out of memory\n");
583e12c5d1SDavid du Colombier 	memset(p, '\0', n);
593e12c5d1SDavid du Colombier 	return p;
603e12c5d1SDavid du Colombier }
613e12c5d1SDavid du Colombier 
623e12c5d1SDavid du Colombier static
633e12c5d1SDavid du Colombier void*
dalloc(ulong n)643e12c5d1SDavid du Colombier dalloc(ulong n)
653e12c5d1SDavid du Colombier {
663e12c5d1SDavid du Colombier 	char *p;
673e12c5d1SDavid du Colombier 
687dd7cddfSDavid du Colombier 	if(fencebase == 0)
697dd7cddfSDavid du Colombier 		fence = fencebase = zalloc(MAXDEPTH*sizeof(Dentry));
707dd7cddfSDavid du Colombier 	p = fence;
717dd7cddfSDavid du Colombier 	fence += n;
727dd7cddfSDavid du Colombier 	if(fence > fencebase+MAXDEPTH*sizeof(Dentry))
733e12c5d1SDavid du Colombier 		panic("dalloc too much memory\n");
743e12c5d1SDavid du Colombier 	return p;
753e12c5d1SDavid du Colombier }
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier void
check(Filsys * fs,long flag)783e12c5d1SDavid du Colombier check(Filsys *fs, long flag)
793e12c5d1SDavid du Colombier {
803e12c5d1SDavid du Colombier 	Iobuf *p;
813e12c5d1SDavid du Colombier 	Superb *sb;
823e12c5d1SDavid du Colombier 	Dentry *d;
833e12c5d1SDavid du Colombier 	long raddr;
849a747e4fSDavid du Colombier 	long nqid;
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier 	wlock(&mainlock);
873e12c5d1SDavid du Colombier 	dev = fs->dev;
883e12c5d1SDavid du Colombier 	flags = flag;
897dd7cddfSDavid du Colombier 	fence = fencebase;
903e12c5d1SDavid du Colombier 
913e12c5d1SDavid du Colombier 	sizname = 4000;
923e12c5d1SDavid du Colombier 	name = zalloc(sizname);
933e12c5d1SDavid du Colombier 	sizname -= NAMELEN+10;	/* for safety */
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier 	sbaddr = superaddr(dev);
963e12c5d1SDavid du Colombier 	raddr = getraddr(dev);
973e12c5d1SDavid du Colombier 	p = xtag(sbaddr, Tsuper, QPSUPER);
983e12c5d1SDavid du Colombier 	if(!p){
993e12c5d1SDavid du Colombier 		cprint("bad superblock\n");
1003e12c5d1SDavid du Colombier 		goto out;
1013e12c5d1SDavid du Colombier 	}
1023e12c5d1SDavid du Colombier 	sb = (Superb*)p->iobuf;
1033e12c5d1SDavid du Colombier 	fstart = 1;
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier 	fsize = sb->fsize;
1063e12c5d1SDavid du Colombier 	sizabits = (fsize-fstart + 7)/8;
1073e12c5d1SDavid du Colombier 	abits = zalloc(sizabits);
1083e12c5d1SDavid du Colombier 
1099a747e4fSDavid du Colombier 	nqid = sb->qidgen+100;		/* not as much of a botch */
1109a747e4fSDavid du Colombier 	if(nqid > 1024*1024*8)
1119a747e4fSDavid du Colombier 		nqid = 1024*1024*8;
1129a747e4fSDavid du Colombier 	if(nqid < 64*1024)
1139a747e4fSDavid du Colombier 		nqid = 64*1024;
1149a747e4fSDavid du Colombier 
1159a747e4fSDavid du Colombier 	sizqbits = (nqid+7)/8;
1169a747e4fSDavid du Colombier 	qbits = zalloc(sizqbits);
1179a747e4fSDavid du Colombier 
1183e12c5d1SDavid du Colombier 	mod = 0;
1193e12c5d1SDavid du Colombier 	nfree = 0;
1203e12c5d1SDavid du Colombier 	nfdup = 0;
1213e12c5d1SDavid du Colombier 	nused = 0;
1223e12c5d1SDavid du Colombier 	nbad = 0;
1233e12c5d1SDavid du Colombier 	ndup = 0;
1243e12c5d1SDavid du Colombier 	nqbad = 0;
1253e12c5d1SDavid du Colombier 	depth = 0;
1263e12c5d1SDavid du Colombier 	maxdepth = 0;
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier 	if(flags & Ctouch) {
1293e12c5d1SDavid du Colombier 		oldblock = fsize/DSIZE;
1303e12c5d1SDavid du Colombier 		oldblock *= DSIZE;
1313e12c5d1SDavid du Colombier 		if(oldblock < 0)
1323e12c5d1SDavid du Colombier 			oldblock = 0;
1333e12c5d1SDavid du Colombier 		cprint("oldblock = %ld\n", oldblock);
1343e12c5d1SDavid du Colombier 	}
1353e12c5d1SDavid du Colombier 	if(amark(sbaddr))
1369a747e4fSDavid du Colombier 		{}
1373e12c5d1SDavid du Colombier 	if(cwflag) {
1383e12c5d1SDavid du Colombier 		if(amark(sb->roraddr))
1399a747e4fSDavid du Colombier 			{}
1403e12c5d1SDavid du Colombier 		if(amark(sb->next))
1419a747e4fSDavid du Colombier 			{}
1423e12c5d1SDavid du Colombier 	}
1433e12c5d1SDavid du Colombier 
1443e12c5d1SDavid du Colombier 	if(!(flags & Cquiet))
1453e12c5d1SDavid du Colombier 		cprint("checking file system: %s\n", fs->name);
1463e12c5d1SDavid du Colombier 	nfiles = 0;
1473e12c5d1SDavid du Colombier 	maxq = 0;
1483e12c5d1SDavid du Colombier 
1493e12c5d1SDavid du Colombier 	d = maked(raddr, 0, QPROOT);
1503e12c5d1SDavid du Colombier 	if(d) {
1513e12c5d1SDavid du Colombier 		if(amark(raddr))
1529a747e4fSDavid du Colombier 			{}
1533e12c5d1SDavid du Colombier 		if(fsck(d))
1543e12c5d1SDavid du Colombier 			modd(raddr, 0, d);
1553e12c5d1SDavid du Colombier 		depth--;
1567dd7cddfSDavid du Colombier 		fence -= sizeof(Dentry);
1573e12c5d1SDavid du Colombier 		if(depth)
1583e12c5d1SDavid du Colombier 			cprint("depth not zero on return\n");
1593e12c5d1SDavid du Colombier 	}
1603e12c5d1SDavid du Colombier 
1613e12c5d1SDavid du Colombier 	if(flags & Cfree) {
1623e12c5d1SDavid du Colombier 		mkfreelist(sb);
1633e12c5d1SDavid du Colombier 		sb->qidgen = maxq;
1643e12c5d1SDavid du Colombier 		settag(p, Tsuper, QPNONE);
1653e12c5d1SDavid du Colombier 	}
1663e12c5d1SDavid du Colombier 
1673e12c5d1SDavid du Colombier 	if(sb->qidgen < maxq)
1683e12c5d1SDavid du Colombier 		cprint("qid generator low path=%ld maxq=%ld\n",
1693e12c5d1SDavid du Colombier 			sb->qidgen, maxq);
1703e12c5d1SDavid du Colombier 	if(!(flags & Cfree))
1713e12c5d1SDavid du Colombier 		ckfreelist(sb);
1723e12c5d1SDavid du Colombier 	if(mod) {
1733e12c5d1SDavid du Colombier 		cprint("file system was modified\n");
1743e12c5d1SDavid du Colombier 		settag(p, Tsuper, QPNONE);
1753e12c5d1SDavid du Colombier 	}
1763e12c5d1SDavid du Colombier 
1773e12c5d1SDavid du Colombier 	if(!(flags & Cquiet)){
1783e12c5d1SDavid du Colombier 		cprint("%8ld files\n", nfiles);
1793e12c5d1SDavid du Colombier 		cprint("%8ld blocks in the file system\n", fsize-fstart);
1803e12c5d1SDavid du Colombier 		cprint("%8ld used blocks\n", nused);
1813e12c5d1SDavid du Colombier 		cprint("%8ld free blocks\n", sb->tfree);
1823e12c5d1SDavid du Colombier 	}
1833e12c5d1SDavid du Colombier 	if(!(flags & Cfree)){
1843e12c5d1SDavid du Colombier 		if(nfree != sb->tfree)
1853e12c5d1SDavid du Colombier 			cprint("%8ld free blocks found\n", nfree);
1863e12c5d1SDavid du Colombier 		if(nfdup)
1873e12c5d1SDavid du Colombier 			cprint("%8ld blocks duplicated in the free list\n", nfdup);
1883e12c5d1SDavid du Colombier 		if(fsize-fstart-nused-nfree)
1893e12c5d1SDavid du Colombier 			cprint("%8ld missing blocks\n", fsize-fstart-nused-nfree);
1903e12c5d1SDavid du Colombier 	}
1913e12c5d1SDavid du Colombier 	if(ndup)
1923e12c5d1SDavid du Colombier 		cprint("%8ld address duplications\n", ndup);
1933e12c5d1SDavid du Colombier 	if(nbad)
1943e12c5d1SDavid du Colombier 		cprint("%8ld bad block addresses\n", nbad);
1953e12c5d1SDavid du Colombier 	if(nqbad)
1963e12c5d1SDavid du Colombier 		cprint("%8ld bad qids\n", nqbad);
1973e12c5d1SDavid du Colombier 	if(!(flags & Cquiet))
1983e12c5d1SDavid du Colombier 		cprint("%8ld maximum qid path\n", maxq);
1993e12c5d1SDavid du Colombier 	missing();
2003e12c5d1SDavid du Colombier 
2013e12c5d1SDavid du Colombier out:
2023e12c5d1SDavid du Colombier 	if(p)
2033e12c5d1SDavid du Colombier 		putbuf(p);
2043e12c5d1SDavid du Colombier 	free(abits);
2053e12c5d1SDavid du Colombier 	free(name);
2063e12c5d1SDavid du Colombier 	free(qbits);
2073e12c5d1SDavid du Colombier 	wunlock(&mainlock);
2083e12c5d1SDavid du Colombier }
2093e12c5d1SDavid du Colombier 
2103e12c5d1SDavid du Colombier static
2113e12c5d1SDavid du Colombier int
touch(long a)2123e12c5d1SDavid du Colombier touch(long a)
2133e12c5d1SDavid du Colombier {
2143e12c5d1SDavid du Colombier 	Iobuf *p;
2153e12c5d1SDavid du Colombier 
2163e12c5d1SDavid du Colombier 	if((flags&Ctouch) && a && a < oldblock){
2173e12c5d1SDavid du Colombier 		p = getbuf(dev, a, Bread|Bmod);
2183e12c5d1SDavid du Colombier 		if(p)
2193e12c5d1SDavid du Colombier 			putbuf(p);
2203e12c5d1SDavid du Colombier 		return 1;
2213e12c5d1SDavid du Colombier 	}
2223e12c5d1SDavid du Colombier 	return 0;
2233e12c5d1SDavid du Colombier }
2243e12c5d1SDavid du Colombier 
2253e12c5d1SDavid du Colombier static
2263e12c5d1SDavid du Colombier int
checkdir(long a,long qpath)2273e12c5d1SDavid du Colombier checkdir(long a, long qpath)
2283e12c5d1SDavid du Colombier {
2293e12c5d1SDavid du Colombier 	Dentry *nd;
2303e12c5d1SDavid du Colombier 	int i, ns, dmod;
2313e12c5d1SDavid du Colombier 
2323e12c5d1SDavid du Colombier 	ns = strlen(name);
2333e12c5d1SDavid du Colombier 	dmod = touch(a);
2343e12c5d1SDavid du Colombier 	for(i=0; i<DIRPERBUF; i++) {
2353e12c5d1SDavid du Colombier 		nd = maked(a, i, qpath);
2363e12c5d1SDavid du Colombier 		if(!nd)
2373e12c5d1SDavid du Colombier 			break;
2383e12c5d1SDavid du Colombier 		if(fsck(nd)) {
2393e12c5d1SDavid du Colombier 			modd(a, i, nd);
2403e12c5d1SDavid du Colombier 			dmod++;
2413e12c5d1SDavid du Colombier 		}
2423e12c5d1SDavid du Colombier 		depth--;
2437dd7cddfSDavid du Colombier 		fence -= sizeof(Dentry);
2443e12c5d1SDavid du Colombier 		name[ns] = 0;
2453e12c5d1SDavid du Colombier 	}
2463e12c5d1SDavid du Colombier 	name[ns] = 0;
2473e12c5d1SDavid du Colombier 	return dmod;
2483e12c5d1SDavid du Colombier }
2493e12c5d1SDavid du Colombier 
2503e12c5d1SDavid du Colombier static
2513e12c5d1SDavid du Colombier int
checkindir(long a,Dentry * d,long qpath)2523e12c5d1SDavid du Colombier checkindir(long a, Dentry *d, long qpath)
2533e12c5d1SDavid du Colombier {
2543e12c5d1SDavid du Colombier 	Iobuf *p;
2553e12c5d1SDavid du Colombier 	int i, dmod;
2563e12c5d1SDavid du Colombier 
2573e12c5d1SDavid du Colombier 	dmod = touch(a);
2583e12c5d1SDavid du Colombier 	p = xtag(a, Tind1, qpath);
2593e12c5d1SDavid du Colombier 	if(!p)
2603e12c5d1SDavid du Colombier 		return dmod;
2613e12c5d1SDavid du Colombier 	for(i=0; i<INDPERBUF; i++) {
2623e12c5d1SDavid du Colombier 		a = ((long*)p->iobuf)[i];
2633e12c5d1SDavid du Colombier 		if(!a)
2643e12c5d1SDavid du Colombier 			continue;
2653e12c5d1SDavid du Colombier 		if(amark(a)) {
2663e12c5d1SDavid du Colombier 			if(flags & Cbad) {
2673e12c5d1SDavid du Colombier 				((long*)p->iobuf)[i] = 0;
2683e12c5d1SDavid du Colombier 				p->flags |= Bmod;
2693e12c5d1SDavid du Colombier 			}
2703e12c5d1SDavid du Colombier 			continue;
2713e12c5d1SDavid du Colombier 		}
2723e12c5d1SDavid du Colombier 		if(d->mode & DDIR)
2733e12c5d1SDavid du Colombier 			dmod += checkdir(a, qpath);
2743e12c5d1SDavid du Colombier 		else if(flags & Crdall)
2753e12c5d1SDavid du Colombier 			xread(a, qpath);
2763e12c5d1SDavid du Colombier 	}
2773e12c5d1SDavid du Colombier 	putbuf(p);
2783e12c5d1SDavid du Colombier 	return dmod;
2793e12c5d1SDavid du Colombier }
2803e12c5d1SDavid du Colombier 
2813e12c5d1SDavid du Colombier static
2823e12c5d1SDavid du Colombier int
fsck(Dentry * d)2833e12c5d1SDavid du Colombier fsck(Dentry *d)
2843e12c5d1SDavid du Colombier {
285*7611b47fSDavid du Colombier 	char *s;
286*7611b47fSDavid du Colombier 	Rune r;
2873e12c5d1SDavid du Colombier 	Iobuf *p;
288*7611b47fSDavid du Colombier 	int l, i, ns, dmod;
2893e12c5d1SDavid du Colombier 	long a, qpath;
2903e12c5d1SDavid du Colombier 
2913e12c5d1SDavid du Colombier 	depth++;
2923e12c5d1SDavid du Colombier 	if(depth >= maxdepth){
2933e12c5d1SDavid du Colombier 		maxdepth = depth;
2943e12c5d1SDavid du Colombier 		if(maxdepth >= MAXDEPTH){
2953e12c5d1SDavid du Colombier 			cprint("max depth exceeded: %s\n", name);
2963e12c5d1SDavid du Colombier 			return 0;
2973e12c5d1SDavid du Colombier 		}
2983e12c5d1SDavid du Colombier 	}
2993e12c5d1SDavid du Colombier 	dmod = 0;
3003e12c5d1SDavid du Colombier 	if(!(d->mode & DALLOC))
3013e12c5d1SDavid du Colombier 		return 0;
3023e12c5d1SDavid du Colombier 	nfiles++;
3033e12c5d1SDavid du Colombier 
3043e12c5d1SDavid du Colombier 	ns = strlen(name);
3053e12c5d1SDavid du Colombier 	i = strlen(d->name);
3063e12c5d1SDavid du Colombier 	if(i >= NAMELEN){
3073e12c5d1SDavid du Colombier 		d->name[NAMELEN-1] = 0;
3083e12c5d1SDavid du Colombier 		cprint("%s->name (%s) not terminated\n", name, d->name);
3093e12c5d1SDavid du Colombier 		return 0;
3103e12c5d1SDavid du Colombier 	}
3113e12c5d1SDavid du Colombier 	ns += i;
3123e12c5d1SDavid du Colombier 	if(ns >= sizname){
3133e12c5d1SDavid du Colombier 		cprint("%s->name (%s) name too large\n", name, d->name);
3143e12c5d1SDavid du Colombier 		return 0;
3153e12c5d1SDavid du Colombier 	}
316*7611b47fSDavid du Colombier 	for (s = d->name; *s; s += l){
317*7611b47fSDavid du Colombier 		l = chartorune(&r, s);
318*7611b47fSDavid du Colombier 		if (r == Runeerror)
319*7611b47fSDavid du Colombier 			for (i = 0; i < l; i++){
320*7611b47fSDavid du Colombier 				s[i] = '_';
321*7611b47fSDavid du Colombier 				cprint("%s->name (%s) bad UTF\n", name, d->name);
322*7611b47fSDavid du Colombier 				dmod++;
323*7611b47fSDavid du Colombier 			}
324*7611b47fSDavid du Colombier 	}
3253e12c5d1SDavid du Colombier 	strcat(name, d->name);
3263e12c5d1SDavid du Colombier 
3273e12c5d1SDavid du Colombier 	if(d->mode & DDIR){
3283e12c5d1SDavid du Colombier 		if(ns > 1)
3293e12c5d1SDavid du Colombier 			strcat(name, "/");
3303e12c5d1SDavid du Colombier 		if(flags & Cpdir)
3313e12c5d1SDavid du Colombier 			cprint("%s\n", name);
3323e12c5d1SDavid du Colombier 	} else
3333e12c5d1SDavid du Colombier 	if(flags & Cpfile)
3343e12c5d1SDavid du Colombier 		cprint("%s\n", name);
3353e12c5d1SDavid du Colombier 
3363e12c5d1SDavid du Colombier 	qpath = d->qid.path & ~QPDIR;
3373e12c5d1SDavid du Colombier 	qmark(qpath);
3383e12c5d1SDavid du Colombier 	if(qpath > maxq)
3393e12c5d1SDavid du Colombier 		maxq = qpath;
3403e12c5d1SDavid du Colombier 	for(i=0; i<NDBLOCK; i++) {
3413e12c5d1SDavid du Colombier 		a = d->dblock[i];
3423e12c5d1SDavid du Colombier 		if(!a)
3433e12c5d1SDavid du Colombier 			continue;
3443e12c5d1SDavid du Colombier 		if(amark(a)) {
3453e12c5d1SDavid du Colombier 			d->dblock[i] = 0;
3463e12c5d1SDavid du Colombier 			dmod++;
3473e12c5d1SDavid du Colombier 			continue;
3483e12c5d1SDavid du Colombier 		}
3493e12c5d1SDavid du Colombier 		if(d->mode & DDIR)
3503e12c5d1SDavid du Colombier 			dmod += checkdir(a, qpath);
3513e12c5d1SDavid du Colombier 		else if(flags & Crdall)
3523e12c5d1SDavid du Colombier 			xread(a, qpath);
3533e12c5d1SDavid du Colombier 	}
3543e12c5d1SDavid du Colombier 	a = d->iblock;
3553e12c5d1SDavid du Colombier 	if(a && amark(a)) {
3563e12c5d1SDavid du Colombier 		d->iblock = 0;
3573e12c5d1SDavid du Colombier 		dmod++;
3583e12c5d1SDavid du Colombier 	}
3593e12c5d1SDavid du Colombier 	else if(a)
3603e12c5d1SDavid du Colombier 		dmod += checkindir(a, d, qpath);
3613e12c5d1SDavid du Colombier 
3623e12c5d1SDavid du Colombier 	a = d->diblock;
3633e12c5d1SDavid du Colombier 	if(a && amark(a)) {
3643e12c5d1SDavid du Colombier 		d->diblock = 0;
3653e12c5d1SDavid du Colombier 		return dmod + 1;
3663e12c5d1SDavid du Colombier 	}
3673e12c5d1SDavid du Colombier 	dmod += touch(a);
3683e12c5d1SDavid du Colombier 	if(p = xtag(a, Tind2, qpath)){
3693e12c5d1SDavid du Colombier 		for(i=0; i<INDPERBUF; i++){
3703e12c5d1SDavid du Colombier 			a = ((long*)p->iobuf)[i];
3713e12c5d1SDavid du Colombier 			if(!a)
3723e12c5d1SDavid du Colombier 				continue;
3733e12c5d1SDavid du Colombier 			if(amark(a)) {
3743e12c5d1SDavid du Colombier 				if(flags & Cbad) {
3753e12c5d1SDavid du Colombier 					((long*)p->iobuf)[i] = 0;
3763e12c5d1SDavid du Colombier 					p->flags |= Bmod;
3773e12c5d1SDavid du Colombier 				}
3783e12c5d1SDavid du Colombier 				continue;
3793e12c5d1SDavid du Colombier 			}
3803e12c5d1SDavid du Colombier 			dmod += checkindir(a, d, qpath);
3813e12c5d1SDavid du Colombier 		}
3823e12c5d1SDavid du Colombier 		putbuf(p);
3833e12c5d1SDavid du Colombier 	}
3843e12c5d1SDavid du Colombier 	return dmod;
3853e12c5d1SDavid du Colombier }
3863e12c5d1SDavid du Colombier 
3873e12c5d1SDavid du Colombier static
3883e12c5d1SDavid du Colombier void
ckfreelist(Superb * sb)3893e12c5d1SDavid du Colombier ckfreelist(Superb *sb)
3903e12c5d1SDavid du Colombier {
3913e12c5d1SDavid du Colombier 	long a, lo, hi;
3923e12c5d1SDavid du Colombier 	int n, i;
3933e12c5d1SDavid du Colombier 	Iobuf *p;
3943e12c5d1SDavid du Colombier 	Fbuf *fb;
3953e12c5d1SDavid du Colombier 
3963e12c5d1SDavid du Colombier 
3973e12c5d1SDavid du Colombier 	strcpy(name, "free list");
3983e12c5d1SDavid du Colombier 	cprint("check %s\n", name);
3993e12c5d1SDavid du Colombier 	fb = &sb->fbuf;
4003e12c5d1SDavid du Colombier 	a = sbaddr;
4013e12c5d1SDavid du Colombier 	p = 0;
4023e12c5d1SDavid du Colombier 	lo = 0;
4033e12c5d1SDavid du Colombier 	hi = 0;
4043e12c5d1SDavid du Colombier 	for(;;) {
4053e12c5d1SDavid du Colombier 		n = fb->nfree;
4063e12c5d1SDavid du Colombier 		if(n < 0 || n > FEPERBUF) {
4073e12c5d1SDavid du Colombier 			cprint("check: nfree bad %ld\n", a);
4083e12c5d1SDavid du Colombier 			break;
4093e12c5d1SDavid du Colombier 		}
4103e12c5d1SDavid du Colombier 		for(i=1; i<n; i++) {
4113e12c5d1SDavid du Colombier 			a = fb->free[i];
4123e12c5d1SDavid du Colombier 			if(a && !fmark(a)) {
4133e12c5d1SDavid du Colombier 				if(!lo || lo > a)
4143e12c5d1SDavid du Colombier 					lo = a;
4153e12c5d1SDavid du Colombier 				if(!hi || hi < a)
4163e12c5d1SDavid du Colombier 					hi = a;
4173e12c5d1SDavid du Colombier 			}
4183e12c5d1SDavid du Colombier 		}
4193e12c5d1SDavid du Colombier 		a = fb->free[0];
4203e12c5d1SDavid du Colombier 		if(!a)
4213e12c5d1SDavid du Colombier 			break;
4223e12c5d1SDavid du Colombier 		if(fmark(a))
4233e12c5d1SDavid du Colombier 			break;
4243e12c5d1SDavid du Colombier 		if(!lo || lo > a)
4253e12c5d1SDavid du Colombier 			lo = a;
4263e12c5d1SDavid du Colombier 		if(!hi || hi < a)
4273e12c5d1SDavid du Colombier 			hi = a;
4283e12c5d1SDavid du Colombier 		if(p)
4293e12c5d1SDavid du Colombier 			putbuf(p);
4303e12c5d1SDavid du Colombier 		p = xtag(a, Tfree, QPNONE);
4313e12c5d1SDavid du Colombier 		if(!p)
4323e12c5d1SDavid du Colombier 			break;
4333e12c5d1SDavid du Colombier 		fb = (Fbuf*)p->iobuf;
4343e12c5d1SDavid du Colombier 	}
4353e12c5d1SDavid du Colombier 	if(p)
4363e12c5d1SDavid du Colombier 		putbuf(p);
4373e12c5d1SDavid du Colombier 	cprint("lo = %ld; hi = %ld\n", lo, hi);
4383e12c5d1SDavid du Colombier }
4393e12c5d1SDavid du Colombier 
4403e12c5d1SDavid du Colombier /*
4413e12c5d1SDavid du Colombier  * make freelist from scratch
4423e12c5d1SDavid du Colombier  */
4433e12c5d1SDavid du Colombier static
4443e12c5d1SDavid du Colombier void
mkfreelist(Superb * sb)4453e12c5d1SDavid du Colombier mkfreelist(Superb *sb)
4463e12c5d1SDavid du Colombier {
4473e12c5d1SDavid du Colombier 	long a;
4483e12c5d1SDavid du Colombier 	int i, b;
4493e12c5d1SDavid du Colombier 
4503e12c5d1SDavid du Colombier 	strcpy(name, "free list");
4513e12c5d1SDavid du Colombier 	memset(&sb->fbuf, 0, sizeof(sb->fbuf));
4523e12c5d1SDavid du Colombier 	sb->fbuf.nfree = 1;
4533e12c5d1SDavid du Colombier 	sb->tfree = 0;
4543e12c5d1SDavid du Colombier 	for(a=fsize-fstart-1; a >= 0; a--) {
4553e12c5d1SDavid du Colombier 		i = a/8;
4563e12c5d1SDavid du Colombier 		if(i < 0 || i >= sizabits)
4573e12c5d1SDavid du Colombier 			continue;
4583e12c5d1SDavid du Colombier 		b = 1 << (a&7);
4593e12c5d1SDavid du Colombier 		if(abits[i] & b)
4603e12c5d1SDavid du Colombier 			continue;
4613e12c5d1SDavid du Colombier 		addfree(dev, fstart+a, sb);
4623e12c5d1SDavid du Colombier 		abits[i] |= b;
4633e12c5d1SDavid du Colombier 	}
4643e12c5d1SDavid du Colombier }
4653e12c5d1SDavid du Colombier 
4663e12c5d1SDavid du Colombier static
4673e12c5d1SDavid du Colombier Dentry*
maked(long a,int s,long qpath)4683e12c5d1SDavid du Colombier maked(long a, int s, long qpath)
4693e12c5d1SDavid du Colombier {
4703e12c5d1SDavid du Colombier 	Iobuf *p;
4713e12c5d1SDavid du Colombier 	Dentry *d, *d1;
4723e12c5d1SDavid du Colombier 
4733e12c5d1SDavid du Colombier 	p = xtag(a, Tdir, qpath);
4743e12c5d1SDavid du Colombier 	if(!p)
4753e12c5d1SDavid du Colombier 		return 0;
4763e12c5d1SDavid du Colombier 	d = getdir(p, s);
4773e12c5d1SDavid du Colombier 	d1 = dalloc(sizeof(Dentry));
478bd389b36SDavid du Colombier 	memmove(d1, d, sizeof(Dentry));
4793e12c5d1SDavid du Colombier 	putbuf(p);
4803e12c5d1SDavid du Colombier 	return d1;
4813e12c5d1SDavid du Colombier }
4823e12c5d1SDavid du Colombier 
4833e12c5d1SDavid du Colombier static
4843e12c5d1SDavid du Colombier void
modd(long a,int s,Dentry * d1)4853e12c5d1SDavid du Colombier modd(long a, int s, Dentry *d1)
4863e12c5d1SDavid du Colombier {
4873e12c5d1SDavid du Colombier 	Iobuf *p;
4883e12c5d1SDavid du Colombier 	Dentry *d;
4893e12c5d1SDavid du Colombier 
4903e12c5d1SDavid du Colombier 	if(!(flags & Cbad))
4913e12c5d1SDavid du Colombier 		return;
4923e12c5d1SDavid du Colombier 	p = getbuf(dev, a, Bread);
4933e12c5d1SDavid du Colombier 	d = getdir(p, s);
4943e12c5d1SDavid du Colombier 	if(!d) {
4953e12c5d1SDavid du Colombier 		if(p)
4963e12c5d1SDavid du Colombier 			putbuf(p);
4973e12c5d1SDavid du Colombier 		return;
4983e12c5d1SDavid du Colombier 	}
499bd389b36SDavid du Colombier 	memmove(d, d1, sizeof(Dentry));
5003e12c5d1SDavid du Colombier 	p->flags |= Bmod;
5013e12c5d1SDavid du Colombier 	putbuf(p);
5023e12c5d1SDavid du Colombier }
5033e12c5d1SDavid du Colombier 
5043e12c5d1SDavid du Colombier static
5053e12c5d1SDavid du Colombier void
xread(long a,long qpath)5063e12c5d1SDavid du Colombier xread(long a, long qpath)
5073e12c5d1SDavid du Colombier {
5083e12c5d1SDavid du Colombier 	Iobuf *p;
5093e12c5d1SDavid du Colombier 
5103e12c5d1SDavid du Colombier 	p = xtag(a, Tfile, qpath);
5113e12c5d1SDavid du Colombier 	if(p)
5123e12c5d1SDavid du Colombier 		putbuf(p);
5133e12c5d1SDavid du Colombier }
5143e12c5d1SDavid du Colombier 
5153e12c5d1SDavid du Colombier static
5163e12c5d1SDavid du Colombier Iobuf*
xtag(long a,int tag,long qpath)5173e12c5d1SDavid du Colombier xtag(long a, int tag, long qpath)
5183e12c5d1SDavid du Colombier {
5193e12c5d1SDavid du Colombier 	Iobuf *p;
5203e12c5d1SDavid du Colombier 
5213e12c5d1SDavid du Colombier 	if(a == 0)
5223e12c5d1SDavid du Colombier 		return 0;
5233e12c5d1SDavid du Colombier 	p = getbuf(dev, a, Bread);
5243e12c5d1SDavid du Colombier 	if(!p) {
5253e12c5d1SDavid du Colombier 		cprint("check: \"%s\": xtag: p null\n", name);
5263e12c5d1SDavid du Colombier 		if(flags & (Cream|Ctag)) {
5273e12c5d1SDavid du Colombier 			p = getbuf(dev, a, Bmod);
5283e12c5d1SDavid du Colombier 			if(p) {
5293e12c5d1SDavid du Colombier 				memset(p->iobuf, 0, RBUFSIZE);
5303e12c5d1SDavid du Colombier 				settag(p, tag, qpath);
5313e12c5d1SDavid du Colombier 				mod++;
5323e12c5d1SDavid du Colombier 				return p;
5333e12c5d1SDavid du Colombier 			}
5343e12c5d1SDavid du Colombier 		}
5353e12c5d1SDavid du Colombier 		return 0;
5363e12c5d1SDavid du Colombier 	}
5373e12c5d1SDavid du Colombier 	if(checktag(p, tag, qpath)) {
5383e12c5d1SDavid du Colombier 		cprint("check: \"%s\": xtag: checktag\n", name);
5393e12c5d1SDavid du Colombier 		if(flags & Cream)
5403e12c5d1SDavid du Colombier 			memset(p->iobuf, 0, RBUFSIZE);
5413e12c5d1SDavid du Colombier 		if(flags & (Cream|Ctag)) {
5423e12c5d1SDavid du Colombier 			settag(p, tag, qpath);
5433e12c5d1SDavid du Colombier 			mod++;
5443e12c5d1SDavid du Colombier 		}
5453e12c5d1SDavid du Colombier 		return p;
5463e12c5d1SDavid du Colombier 	}
5473e12c5d1SDavid du Colombier 	return p;
5483e12c5d1SDavid du Colombier }
5493e12c5d1SDavid du Colombier 
5503e12c5d1SDavid du Colombier static
5513e12c5d1SDavid du Colombier int
amark(long a)5523e12c5d1SDavid du Colombier amark(long a)
5533e12c5d1SDavid du Colombier {
5543e12c5d1SDavid du Colombier 	long i;
5553e12c5d1SDavid du Colombier 	int b;
5563e12c5d1SDavid du Colombier 
5573e12c5d1SDavid du Colombier 	if(a < fstart || a >= fsize) {
5583e12c5d1SDavid du Colombier 		cprint("check: \"%s\": range %ld\n",
5593e12c5d1SDavid du Colombier 			name, a);
5603e12c5d1SDavid du Colombier 		nbad++;
5613e12c5d1SDavid du Colombier 		return 1;
5623e12c5d1SDavid du Colombier 	}
5633e12c5d1SDavid du Colombier 	a -= fstart;
5643e12c5d1SDavid du Colombier 	i = a/8;
5653e12c5d1SDavid du Colombier 	b = 1 << (a&7);
5663e12c5d1SDavid du Colombier 	if(abits[i] & b) {
5673e12c5d1SDavid du Colombier 		if(!ronly) {
5683e12c5d1SDavid du Colombier 			if(ndup < 10)
5693e12c5d1SDavid du Colombier 				cprint("check: \"%s\": address dup %ld\n",
5703e12c5d1SDavid du Colombier 					name, fstart+a);
5713e12c5d1SDavid du Colombier 			else
5723e12c5d1SDavid du Colombier 			if(ndup == 10)
5733e12c5d1SDavid du Colombier 				cprint("...");
5743e12c5d1SDavid du Colombier 		}
5753e12c5d1SDavid du Colombier 		ndup++;
5763e12c5d1SDavid du Colombier 		return 0;	/* really?? */
5773e12c5d1SDavid du Colombier 	}
5783e12c5d1SDavid du Colombier 	abits[i] |= b;
5793e12c5d1SDavid du Colombier 	nused++;
5803e12c5d1SDavid du Colombier 	return 0;
5813e12c5d1SDavid du Colombier }
5823e12c5d1SDavid du Colombier 
5833e12c5d1SDavid du Colombier static
5843e12c5d1SDavid du Colombier int
fmark(long a)5853e12c5d1SDavid du Colombier fmark(long a)
5863e12c5d1SDavid du Colombier {
5873e12c5d1SDavid du Colombier 	long i;
5883e12c5d1SDavid du Colombier 	int b;
5893e12c5d1SDavid du Colombier 
5903e12c5d1SDavid du Colombier 	if(a < fstart || a >= fsize) {
5913e12c5d1SDavid du Colombier 		cprint("check: \"%s\": range %ld\n",
5923e12c5d1SDavid du Colombier 			name, a);
5933e12c5d1SDavid du Colombier 		nbad++;
5943e12c5d1SDavid du Colombier 		return 1;
5953e12c5d1SDavid du Colombier 	}
5963e12c5d1SDavid du Colombier 	a -= fstart;
5973e12c5d1SDavid du Colombier 	i = a/8;
5983e12c5d1SDavid du Colombier 	b = 1 << (a&7);
5993e12c5d1SDavid du Colombier 	if(abits[i] & b) {
6003e12c5d1SDavid du Colombier 		cprint("check: \"%s\": address dup %ld\n",
6013e12c5d1SDavid du Colombier 			name, fstart+a);
6023e12c5d1SDavid du Colombier 		nfdup++;
6033e12c5d1SDavid du Colombier 		return 1;
6043e12c5d1SDavid du Colombier 	}
6053e12c5d1SDavid du Colombier 	abits[i] |= b;
6063e12c5d1SDavid du Colombier 	nfree++;
6073e12c5d1SDavid du Colombier 	return 0;
6083e12c5d1SDavid du Colombier }
6093e12c5d1SDavid du Colombier 
6103e12c5d1SDavid du Colombier static
6113e12c5d1SDavid du Colombier void
missing(void)6123e12c5d1SDavid du Colombier missing(void)
6133e12c5d1SDavid du Colombier {
6143e12c5d1SDavid du Colombier 	long a, i;
6153e12c5d1SDavid du Colombier 	int b, n;
6163e12c5d1SDavid du Colombier 
6173e12c5d1SDavid du Colombier 	n = 0;
6183e12c5d1SDavid du Colombier 	for(a=fsize-fstart-1; a>=0; a--) {
6193e12c5d1SDavid du Colombier 		i = a/8;
6203e12c5d1SDavid du Colombier 		b = 1 << (a&7);
6213e12c5d1SDavid du Colombier 		if(!(abits[i] & b)) {
6223e12c5d1SDavid du Colombier 			cprint("missing: %ld\n", fstart+a);
6233e12c5d1SDavid du Colombier 			n++;
6243e12c5d1SDavid du Colombier 		}
6253e12c5d1SDavid du Colombier 		if(n > 10) {
6263e12c5d1SDavid du Colombier 			cprint(" ...\n");
6273e12c5d1SDavid du Colombier 			break;
6283e12c5d1SDavid du Colombier 		}
6293e12c5d1SDavid du Colombier 	}
6303e12c5d1SDavid du Colombier }
6313e12c5d1SDavid du Colombier 
6323e12c5d1SDavid du Colombier static
6333e12c5d1SDavid du Colombier void
qmark(long qpath)6343e12c5d1SDavid du Colombier qmark(long qpath)
6353e12c5d1SDavid du Colombier {
6363e12c5d1SDavid du Colombier 	int i, b;
6373e12c5d1SDavid du Colombier 
6383e12c5d1SDavid du Colombier 	i = qpath/8;
6393e12c5d1SDavid du Colombier 	b = 1 << (qpath&7);
6403e12c5d1SDavid du Colombier 	if(i < 0 || i >= sizqbits) {
6413e12c5d1SDavid du Colombier 		nqbad++;
6423e12c5d1SDavid du Colombier 		if(nqbad < 20)
6433e12c5d1SDavid du Colombier 			cprint("check: \"%s\": qid out of range %lux\n",
6443e12c5d1SDavid du Colombier 				name, qpath);
6453e12c5d1SDavid du Colombier 		return;
6463e12c5d1SDavid du Colombier 	}
6473e12c5d1SDavid du Colombier 	if((qbits[i] & b) && !ronly) {
6483e12c5d1SDavid du Colombier 		nqbad++;
6493e12c5d1SDavid du Colombier 		if(nqbad < 20)
6503e12c5d1SDavid du Colombier 			cprint("check: \"%s\": qid dup %lux\n",
6513e12c5d1SDavid du Colombier 				name, qpath);
6523e12c5d1SDavid du Colombier 	}
6533e12c5d1SDavid du Colombier 	qbits[i] |= b;
6543e12c5d1SDavid du Colombier }
655