Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/disk/kfs/chk.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"all.h"
2
 
3
#define	DSIZE		546000
4
#define	MAXDEPTH	100
5
 
6
static	char*	abits;
7
static	long	sizabits;
8
static	char*	qbits;
9
static	long	sizqbits;
10
static	char*	name;
11
static	long	sizname;
12
static	long	fstart;
13
static	long	fsize;
14
static	long	nfiles;
15
static	long	maxq;
16
static	char*	fence;
17
static	char*	fencebase;
18
static	Device	dev;
19
static	long	ndup;
20
static	long	nused;
21
static	long	nfdup;
22
static	long	nqbad;
23
static	long	nfree;
24
static	long	nbad;
25
static	int	mod;
26
static	int	flags;
27
static	int	ronly;
28
static	int	cwflag;
29
static	long	sbaddr;
30
static	long	oldblock;
31
static	int	depth;
32
static	int	maxdepth;
33
 
34
/* local prototypes */
35
static	int	fsck(Dentry*);
36
static	void	ckfreelist(Superb*);
37
static	void	mkfreelist(Superb*);
38
static	Dentry*	maked(long, int, long);
39
static	void	modd(long, int, Dentry*);
40
static	void	xread(long, long);
41
static	int	amark(long);
42
static	int	fmark(long);
43
static	void	missing(void);
44
static	void	qmark(long);
45
static	void*	zalloc(ulong);
46
static	void*	dalloc(ulong);
47
static	Iobuf*	xtag(long, int, long);
48
 
49
static
50
void*
51
zalloc(ulong n)
52
{
53
	char *p;
54
 
55
	p = malloc(n);
56
	if(p == 0)
57
		panic("zalloc: out of memory\n");
58
	memset(p, '\0', n);
59
	return p;
60
}
61
 
62
static
63
void*
64
dalloc(ulong n)
65
{
66
	char *p;
67
 
68
	if(fencebase == 0)
69
		fence = fencebase = zalloc(MAXDEPTH*sizeof(Dentry));
70
	p = fence;
71
	fence += n;
72
	if(fence > fencebase+MAXDEPTH*sizeof(Dentry))
73
		panic("dalloc too much memory\n");
74
	return p;
75
}
76
 
77
void
78
check(Filsys *fs, long flag)
79
{
80
	Iobuf *p;
81
	Superb *sb;
82
	Dentry *d;
83
	long raddr;
84
	long nqid;
85
 
86
	wlock(&mainlock);
87
	dev = fs->dev;
88
	flags = flag;
89
	fence = fencebase;
90
 
91
	sizname = 4000;
92
	name = zalloc(sizname);
93
	sizname -= NAMELEN+10;	/* for safety */
94
 
95
	sbaddr = superaddr(dev);
96
	raddr = getraddr(dev);
97
	p = xtag(sbaddr, Tsuper, QPSUPER);
98
	if(!p){
99
		cprint("bad superblock\n");
100
		goto out;
101
	}
102
	sb = (Superb*)p->iobuf;
103
	fstart = 1;
104
 
105
	fsize = sb->fsize;
106
	sizabits = (fsize-fstart + 7)/8;
107
	abits = zalloc(sizabits);
108
 
109
	nqid = sb->qidgen+100;		/* not as much of a botch */
110
	if(nqid > 1024*1024*8)
111
		nqid = 1024*1024*8;
112
	if(nqid < 64*1024)
113
		nqid = 64*1024;
114
 
115
	sizqbits = (nqid+7)/8;
116
	qbits = zalloc(sizqbits);
117
 
118
	mod = 0;
119
	nfree = 0;
120
	nfdup = 0;
121
	nused = 0;
122
	nbad = 0;
123
	ndup = 0;
124
	nqbad = 0;
125
	depth = 0;
126
	maxdepth = 0;
127
 
128
	if(flags & Ctouch) {
129
		oldblock = fsize/DSIZE;
130
		oldblock *= DSIZE;
131
		if(oldblock < 0)
132
			oldblock = 0;
133
		cprint("oldblock = %ld\n", oldblock);
134
	}
135
	if(amark(sbaddr))
136
		{}
137
	if(cwflag) {
138
		if(amark(sb->roraddr))
139
			{}
140
		if(amark(sb->next))
141
			{}
142
	}
143
 
144
	if(!(flags & Cquiet))
145
		cprint("checking file system: %s\n", fs->name);
146
	nfiles = 0;
147
	maxq = 0;
148
 
149
	d = maked(raddr, 0, QPROOT);
150
	if(d) {
151
		if(amark(raddr))
152
			{}
153
		if(fsck(d))
154
			modd(raddr, 0, d);
155
		depth--;
156
		fence -= sizeof(Dentry);
157
		if(depth)
158
			cprint("depth not zero on return\n");
159
	}
160
 
161
	if(flags & Cfree) {
162
		mkfreelist(sb);
163
		sb->qidgen = maxq;
164
		settag(p, Tsuper, QPNONE);
165
	}
166
 
167
	if(sb->qidgen < maxq)
168
		cprint("qid generator low path=%ld maxq=%ld\n",
169
			sb->qidgen, maxq);
170
	if(!(flags & Cfree))
171
		ckfreelist(sb);
172
	if(mod) {
173
		cprint("file system was modified\n");
174
		settag(p, Tsuper, QPNONE);
175
	}
176
 
177
	if(!(flags & Cquiet)){
178
		cprint("%8ld files\n", nfiles);
179
		cprint("%8ld blocks in the file system\n", fsize-fstart);
180
		cprint("%8ld used blocks\n", nused);
181
		cprint("%8ld free blocks\n", sb->tfree);
182
	}
183
	if(!(flags & Cfree)){
184
		if(nfree != sb->tfree)
185
			cprint("%8ld free blocks found\n", nfree);
186
		if(nfdup)
187
			cprint("%8ld blocks duplicated in the free list\n", nfdup);
188
		if(fsize-fstart-nused-nfree)
189
			cprint("%8ld missing blocks\n", fsize-fstart-nused-nfree);
190
	}
191
	if(ndup)
192
		cprint("%8ld address duplications\n", ndup);
193
	if(nbad)
194
		cprint("%8ld bad block addresses\n", nbad);
195
	if(nqbad)
196
		cprint("%8ld bad qids\n", nqbad);
197
	if(!(flags & Cquiet))
198
		cprint("%8ld maximum qid path\n", maxq);
199
	missing();
200
 
201
out:
202
	if(p)
203
		putbuf(p);
204
	free(abits);
205
	free(name);
206
	free(qbits);
207
	wunlock(&mainlock);
208
}
209
 
210
static
211
int
212
touch(long a)
213
{
214
	Iobuf *p;
215
 
216
	if((flags&Ctouch) && a && a < oldblock){
217
		p = getbuf(dev, a, Bread|Bmod);
218
		if(p)
219
			putbuf(p);
220
		return 1;
221
	}
222
	return 0;
223
}
224
 
225
static
226
int
227
checkdir(long a, long qpath)
228
{
229
	Dentry *nd;
230
	int i, ns, dmod;
231
 
232
	ns = strlen(name);
233
	dmod = touch(a);
234
	for(i=0; i<DIRPERBUF; i++) {
235
		nd = maked(a, i, qpath);
236
		if(!nd)
237
			break;
238
		if(fsck(nd)) {
239
			modd(a, i, nd);
240
			dmod++;
241
		}
242
		depth--;
243
		fence -= sizeof(Dentry);
244
		name[ns] = 0;
245
	}
246
	name[ns] = 0;
247
	return dmod;
248
}
249
 
250
static
251
int
252
checkindir(long a, Dentry *d, long qpath)
253
{
254
	Iobuf *p;
255
	int i, dmod;
256
 
257
	dmod = touch(a);
258
	p = xtag(a, Tind1, qpath);
259
	if(!p)
260
		return dmod;
261
	for(i=0; i<INDPERBUF; i++) {
262
		a = ((long*)p->iobuf)[i];
263
		if(!a)
264
			continue;
265
		if(amark(a)) {
266
			if(flags & Cbad) {
267
				((long*)p->iobuf)[i] = 0;
268
				p->flags |= Bmod;
269
			}
270
			continue;
271
		}
272
		if(d->mode & DDIR)
273
			dmod += checkdir(a, qpath);
274
		else if(flags & Crdall)
275
			xread(a, qpath);
276
	}
277
	putbuf(p);
278
	return dmod;
279
}
280
 
281
static
282
int
283
fsck(Dentry *d)
284
{
285
	char *s;
286
	Rune r;
287
	Iobuf *p;
288
	int l, i, ns, dmod;
289
	long a, qpath;
290
 
291
	depth++;
292
	if(depth >= maxdepth){
293
		maxdepth = depth;
294
		if(maxdepth >= MAXDEPTH){
295
			cprint("max depth exceeded: %s\n", name);
296
			return 0;
297
		}
298
	}
299
	dmod = 0;
300
	if(!(d->mode & DALLOC))
301
		return 0;
302
	nfiles++;
303
 
304
	ns = strlen(name);
305
	i = strlen(d->name);
306
	if(i >= NAMELEN){
307
		d->name[NAMELEN-1] = 0;
308
		cprint("%s->name (%s) not terminated\n", name, d->name);
309
		return 0;
310
	}
311
	ns += i;
312
	if(ns >= sizname){
313
		cprint("%s->name (%s) name too large\n", name, d->name);
314
		return 0;
315
	}
316
	for (s = d->name; *s; s += l){
317
		l = chartorune(&r, s);
318
		if (r == Runeerror)
319
			for (i = 0; i < l; i++){
320
				s[i] = '_';
321
				cprint("%s->name (%s) bad UTF\n", name, d->name);
322
				dmod++;
323
			}
324
	}
325
	strcat(name, d->name);
326
 
327
	if(d->mode & DDIR){
328
		if(ns > 1)
329
			strcat(name, "/");
330
		if(flags & Cpdir)
331
			cprint("%s\n", name);
332
	} else
333
	if(flags & Cpfile)
334
		cprint("%s\n", name);
335
 
336
	qpath = d->qid.path & ~QPDIR;
337
	qmark(qpath);
338
	if(qpath > maxq)
339
		maxq = qpath;
340
	for(i=0; i<NDBLOCK; i++) {
341
		a = d->dblock[i];
342
		if(!a)
343
			continue;
344
		if(amark(a)) {
345
			d->dblock[i] = 0;
346
			dmod++;
347
			continue;
348
		}
349
		if(d->mode & DDIR)
350
			dmod += checkdir(a, qpath);
351
		else if(flags & Crdall)
352
			xread(a, qpath);
353
	}
354
	a = d->iblock;
355
	if(a && amark(a)) {
356
		d->iblock = 0;
357
		dmod++;
358
	}
359
	else if(a)
360
		dmod += checkindir(a, d, qpath);
361
 
362
	a = d->diblock;
363
	if(a && amark(a)) {
364
		d->diblock = 0;
365
		return dmod + 1;
366
	}
367
	dmod += touch(a);
368
	if(p = xtag(a, Tind2, qpath)){
369
		for(i=0; i<INDPERBUF; i++){
370
			a = ((long*)p->iobuf)[i];
371
			if(!a)
372
				continue;
373
			if(amark(a)) {
374
				if(flags & Cbad) {
375
					((long*)p->iobuf)[i] = 0;
376
					p->flags |= Bmod;
377
				}
378
				continue;
379
			}
380
			dmod += checkindir(a, d, qpath);
381
		}
382
		putbuf(p);
383
	}
384
	return dmod;
385
}
386
 
387
static
388
void
389
ckfreelist(Superb *sb)
390
{
391
	long a, lo, hi;
392
	int n, i;
393
	Iobuf *p;
394
	Fbuf *fb;
395
 
396
 
397
	strcpy(name, "free list");
398
	cprint("check %s\n", name);
399
	fb = &sb->fbuf;
400
	a = sbaddr;
401
	p = 0;
402
	lo = 0;
403
	hi = 0;
404
	for(;;) {
405
		n = fb->nfree;
406
		if(n < 0 || n > FEPERBUF) {
407
			cprint("check: nfree bad %ld\n", a);
408
			break;
409
		}
410
		for(i=1; i<n; i++) {
411
			a = fb->free[i];
412
			if(a && !fmark(a)) {
413
				if(!lo || lo > a)
414
					lo = a;
415
				if(!hi || hi < a)
416
					hi = a;
417
			}
418
		}
419
		a = fb->free[0];
420
		if(!a)
421
			break;
422
		if(fmark(a))
423
			break;
424
		if(!lo || lo > a)
425
			lo = a;
426
		if(!hi || hi < a)
427
			hi = a;
428
		if(p)
429
			putbuf(p);
430
		p = xtag(a, Tfree, QPNONE);
431
		if(!p)
432
			break;
433
		fb = (Fbuf*)p->iobuf;
434
	}
435
	if(p)
436
		putbuf(p);
437
	cprint("lo = %ld; hi = %ld\n", lo, hi);
438
}
439
 
440
/*
441
 * make freelist from scratch
442
 */
443
static
444
void
445
mkfreelist(Superb *sb)
446
{
447
	long a;
448
	int i, b;
449
 
450
	strcpy(name, "free list");
451
	memset(&sb->fbuf, 0, sizeof(sb->fbuf));
452
	sb->fbuf.nfree = 1;
453
	sb->tfree = 0;
454
	for(a=fsize-fstart-1; a >= 0; a--) {
455
		i = a/8;
456
		if(i < 0 || i >= sizabits)
457
			continue;
458
		b = 1 << (a&7);
459
		if(abits[i] & b)
460
			continue;
461
		addfree(dev, fstart+a, sb);
462
		abits[i] |= b;
463
	}
464
}
465
 
466
static
467
Dentry*
468
maked(long a, int s, long qpath)
469
{
470
	Iobuf *p;
471
	Dentry *d, *d1;
472
 
473
	p = xtag(a, Tdir, qpath);
474
	if(!p)
475
		return 0;
476
	d = getdir(p, s);
477
	d1 = dalloc(sizeof(Dentry));
478
	memmove(d1, d, sizeof(Dentry));
479
	putbuf(p);
480
	return d1;
481
}
482
 
483
static
484
void
485
modd(long a, int s, Dentry *d1)
486
{
487
	Iobuf *p;
488
	Dentry *d;
489
 
490
	if(!(flags & Cbad))
491
		return;
492
	p = getbuf(dev, a, Bread);
493
	d = getdir(p, s);
494
	if(!d) {
495
		if(p)
496
			putbuf(p);
497
		return;
498
	}
499
	memmove(d, d1, sizeof(Dentry));
500
	p->flags |= Bmod;
501
	putbuf(p);
502
}
503
 
504
static
505
void
506
xread(long a, long qpath)
507
{
508
	Iobuf *p;
509
 
510
	p = xtag(a, Tfile, qpath);
511
	if(p)
512
		putbuf(p);
513
}
514
 
515
static
516
Iobuf*
517
xtag(long a, int tag, long qpath)
518
{
519
	Iobuf *p;
520
 
521
	if(a == 0)
522
		return 0;
523
	p = getbuf(dev, a, Bread);
524
	if(!p) {
525
		cprint("check: \"%s\": xtag: p null\n", name);
526
		if(flags & (Cream|Ctag)) {
527
			p = getbuf(dev, a, Bmod);
528
			if(p) {
529
				memset(p->iobuf, 0, RBUFSIZE);
530
				settag(p, tag, qpath);
531
				mod++;
532
				return p;
533
			}
534
		}
535
		return 0;
536
	}
537
	if(checktag(p, tag, qpath)) {
538
		cprint("check: \"%s\": xtag: checktag\n", name);
539
		if(flags & Cream)
540
			memset(p->iobuf, 0, RBUFSIZE);
541
		if(flags & (Cream|Ctag)) {
542
			settag(p, tag, qpath);
543
			mod++;
544
		}
545
		return p;
546
	}
547
	return p;
548
}
549
 
550
static
551
int
552
amark(long a)
553
{
554
	long i;
555
	int b;
556
 
557
	if(a < fstart || a >= fsize) {
558
		cprint("check: \"%s\": range %ld\n",
559
			name, a);
560
		nbad++;
561
		return 1;
562
	}
563
	a -= fstart;
564
	i = a/8;
565
	b = 1 << (a&7);
566
	if(abits[i] & b) {
567
		if(!ronly) {
568
			if(ndup < 10)
569
				cprint("check: \"%s\": address dup %ld\n",
570
					name, fstart+a);
571
			else
572
			if(ndup == 10)
573
				cprint("...");
574
		}
575
		ndup++;
576
		return 0;	/* really?? */
577
	}
578
	abits[i] |= b;
579
	nused++;
580
	return 0;
581
}
582
 
583
static
584
int
585
fmark(long a)
586
{
587
	long i;
588
	int b;
589
 
590
	if(a < fstart || a >= fsize) {
591
		cprint("check: \"%s\": range %ld\n",
592
			name, a);
593
		nbad++;
594
		return 1;
595
	}
596
	a -= fstart;
597
	i = a/8;
598
	b = 1 << (a&7);
599
	if(abits[i] & b) {
600
		cprint("check: \"%s\": address dup %ld\n",
601
			name, fstart+a);
602
		nfdup++;
603
		return 1;
604
	}
605
	abits[i] |= b;
606
	nfree++;
607
	return 0;
608
}
609
 
610
static
611
void
612
missing(void)
613
{
614
	long a, i;
615
	int b, n;
616
 
617
	n = 0;
618
	for(a=fsize-fstart-1; a>=0; a--) {
619
		i = a/8;
620
		b = 1 << (a&7);
621
		if(!(abits[i] & b)) {
622
			cprint("missing: %ld\n", fstart+a);
623
			n++;
624
		}
625
		if(n > 10) {
626
			cprint(" ...\n");
627
			break;
628
		}
629
	}
630
}
631
 
632
static
633
void
634
qmark(long qpath)
635
{
636
	int i, b;
637
 
638
	i = qpath/8;
639
	b = 1 << (qpath&7);
640
	if(i < 0 || i >= sizqbits) {
641
		nqbad++;
642
		if(nqbad < 20)
643
			cprint("check: \"%s\": qid out of range %lux\n",
644
				name, qpath);
645
		return;
646
	}
647
	if((qbits[i] & b) && !ronly) {
648
		nqbad++;
649
		if(nqbad < 20)
650
			cprint("check: \"%s\": qid dup %lux\n",
651
				name, qpath);
652
	}
653
	qbits[i] |= b;
654
}