17 static char* fencebase;
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);
57 panic("zalloc: out of memory\n");
69 fence = fencebase = zalloc(MAXDEPTH*sizeof(Dentry));
72 if(fence > fencebase+MAXDEPTH*sizeof(Dentry))
73 panic("dalloc too much memory\n");
78 check(Filsys *fs, long flag)
92 name = zalloc(sizname);
93 sizname -= NAMELEN+10; /* for safety */
95 sbaddr = superaddr(dev);
96 raddr = getraddr(dev);
97 p = xtag(sbaddr, Tsuper, QPSUPER);
99 cprint("bad superblock\n");
102 sb = (Superb*)p->iobuf;
106 sizabits = (fsize-fstart + 7)/8;
107 abits = zalloc(sizabits);
109 nqid = sb->qidgen+100; /* not as much of a botch */
110 if(nqid > 1024*1024*8)
115 sizqbits = (nqid+7)/8;
116 qbits = zalloc(sizqbits);
129 oldblock = fsize/DSIZE;
133 cprint("oldblock = %ld\n", oldblock);
138 if(amark(sb->roraddr))
144 if(!(flags & Cquiet))
145 cprint("checking file system: %s\n", fs->name);
149 d = maked(raddr, 0, QPROOT);
156 fence -= sizeof(Dentry);
158 cprint("depth not zero on return\n");
164 settag(p, Tsuper, QPNONE);
167 if(sb->qidgen < maxq)
168 cprint("qid generator low path=%ld maxq=%ld\n",
173 cprint("file system was modified\n");
174 settag(p, Tsuper, QPNONE);
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);
183 if(!(flags & Cfree)){
184 if(nfree != sb->tfree)
185 cprint("%8ld free blocks found\n", nfree);
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);
192 cprint("%8ld address duplications\n", ndup);
194 cprint("%8ld bad block addresses\n", nbad);
196 cprint("%8ld bad qids\n", nqbad);
197 if(!(flags & Cquiet))
198 cprint("%8ld maximum qid path\n", maxq);
216 if((flags&Ctouch) && a && a < oldblock){
217 p = getbuf(dev, a, Bread|Bmod);
227 checkdir(long a, long qpath)
234 for(i=0; i<DIRPERBUF; i++) {
235 nd = maked(a, i, qpath);
243 fence -= sizeof(Dentry);
252 checkindir(long a, Dentry *d, long qpath)
258 p = xtag(a, Tind1, qpath);
261 for(i=0; i<INDPERBUF; i++) {
262 a = ((long*)p->iobuf)[i];
267 ((long*)p->iobuf)[i] = 0;
273 dmod += checkdir(a, qpath);
274 else if(flags & Crdall)
292 if(depth >= maxdepth){
294 if(maxdepth >= MAXDEPTH){
295 cprint("max depth exceeded: %s\n", name);
300 if(!(d->mode & DALLOC))
307 d->name[NAMELEN-1] = 0;
308 cprint("%s->name (%s) not terminated\n", name, d->name);
313 cprint("%s->name (%s) name too large\n", name, d->name);
316 for (s = d->name; *s; s += l){
317 l = chartorune(&r, s);
319 for (i = 0; i < l; i++){
321 cprint("%s->name (%s) bad UTF\n", name, d->name);
325 strcat(name, d->name);
331 cprint("%s\n", name);
334 cprint("%s\n", name);
336 qpath = d->qid.path & ~QPDIR;
340 for(i=0; i<NDBLOCK; i++) {
350 dmod += checkdir(a, qpath);
351 else if(flags & Crdall)
360 dmod += checkindir(a, d, qpath);
368 if(p = xtag(a, Tind2, qpath)){
369 for(i=0; i<INDPERBUF; i++){
370 a = ((long*)p->iobuf)[i];
375 ((long*)p->iobuf)[i] = 0;
380 dmod += checkindir(a, d, qpath);
389 ckfreelist(Superb *sb)
397 strcpy(name, "free list");
398 cprint("check %s\n", name);
406 if(n < 0 || n > FEPERBUF) {
407 cprint("check: nfree bad %ld\n", a);
430 p = xtag(a, Tfree, QPNONE);
433 fb = (Fbuf*)p->iobuf;
437 cprint("lo = %ld; hi = %ld\n", lo, hi);
441 * make freelist from scratch
445 mkfreelist(Superb *sb)
450 strcpy(name, "free list");
451 memset(&sb->fbuf, 0, sizeof(sb->fbuf));
454 for(a=fsize-fstart-1; a >= 0; a--) {
456 if(i < 0 || i >= sizabits)
461 addfree(dev, fstart+a, sb);
468 maked(long a, int s, long qpath)
473 p = xtag(a, Tdir, qpath);
477 d1 = dalloc(sizeof(Dentry));
478 memmove(d1, d, sizeof(Dentry));
485 modd(long a, int s, Dentry *d1)
492 p = getbuf(dev, a, Bread);
499 memmove(d, d1, sizeof(Dentry));
506 xread(long a, long qpath)
510 p = xtag(a, Tfile, qpath);
517 xtag(long a, int tag, long qpath)
523 p = getbuf(dev, a, Bread);
525 cprint("check: \"%s\": xtag: p null\n", name);
526 if(flags & (Cream|Ctag)) {
527 p = getbuf(dev, a, Bmod);
529 memset(p->iobuf, 0, RBUFSIZE);
530 settag(p, tag, qpath);
537 if(checktag(p, tag, qpath)) {
538 cprint("check: \"%s\": xtag: checktag\n", name);
540 memset(p->iobuf, 0, RBUFSIZE);
541 if(flags & (Cream|Ctag)) {
542 settag(p, tag, qpath);
557 if(a < fstart || a >= fsize) {
558 cprint("check: \"%s\": range %ld\n",
569 cprint("check: \"%s\": address dup %ld\n",
576 return 0; /* really?? */
590 if(a < fstart || a >= fsize) {
591 cprint("check: \"%s\": range %ld\n",
600 cprint("check: \"%s\": address dup %ld\n",
618 for(a=fsize-fstart-1; a>=0; a--) {
621 if(!(abits[i] & b)) {
622 cprint("missing: %ld\n", fstart+a);
640 if(i < 0 || i >= sizqbits) {
643 cprint("check: \"%s\": qid out of range %lux\n",
647 if((qbits[i] & b) && !ronly) {
650 cprint("check: \"%s\": qid dup %lux\n",