ref: f0563cbdbce1777d5672fee507acac7ab0d6dbc0
dir: /check.c/
#include <u.h> #include <libc.h> #include <fcall.h> #include <avl.h> #include "dat.h" #include "fns.h" char spc[128]; static int isfree(vlong bp) { Arange *r, q; Arena *a; q.off = bp; q.len = Blksz; a = getarena(bp); r = (Arange*)avllookup(a->free, &q, -1); if(r == nil) return 0; return bp < (r->off + r->len); } static int badblk(Blk *b, int h, Kvp *lo, Kvp *hi) { Kvp x, y; int i, r; Blk *c; int fail; fail = 0; if(b->type == Tleaf){ if(h != 0){ fprint(2, "unbalanced leaf\n"); fail++; } if(h != 0 && b->nval < 2){ fprint(2, "underfilled leaf\n"); fail++; } } if(b->type == Tpivot && b->nval < 2){ fprint(2, "underfilled pivot\n"); fail++; } getval(b, 0, &x); if(lo && keycmp(lo, &x) != 0) fprint(2, "out of range keys %P != %P\n", lo, &x); for(i = 1; i < b->nval; i++){ getval(b, i, &y); if(hi && keycmp(&y, hi) >= 0){ fprint(2, "out of range keys %P >= %P\n", &y, hi); fail++; } if(b->type == Tpivot){ if(isfree(x.bp)){ fprint(2, "freed block in use: %llx\n", x.bp); fail++; } if((c = getblk(x.bp, x.bh)) == nil){ fprint(2, "corrupt block: %r\n"); fail++; continue; } if(blkfill(c) != x.fill){ fprint(2, "mismatched block fill\n"); fail++; } if(badblk(c, h - 1, &x, &y)) fail++; } r = keycmp(&x, &y); switch(r){ case -1: break; case 0: fprint(2, "duplicate keys %P, %P\n", &x, &y); fail++; break; case 1: fprint(2, "misordered keys %P, %P\n", &x, &y); fail++; break; } x = y; } return fail; } static int badfree(void) { Arange *r, *n; int i, fail; fail = 0; for(i = 0; i < fs->narena; i++){ r = (Arange*)avlmin(fs->arenas[i].free); for(n = (Arange*)avlnext(r); n != nil; n = (Arange*)avlnext(n)){ if(r->off >= n->off){ fprint(2, "misordered length %llx >= %llx\n", r->off, n->off); fail++; } if(r->off+r->len >= n->off){ fprint(2, "overlaping range %llx+%llx >= %llx\n", r->off, r->len, n->off); abort(); fail++; } r = n; } } return fail; } /* TODO: this will grow into fsck. */ int checkfs(void) { int ok, height; Blk *b; ok = 1; if(badfree()) ok = 0; if((b = getroot(&height)) != nil){ if(badblk(b, height-1, nil, 0)) ok = 0; putblk(b); } return ok; } void rshowblk(int fd, Blk *b, int indent, int recurse) { Blk *c; int i; Kvp kv; Msg m; if(indent > sizeof(spc)/4) indent = sizeof(spc)/4; if(b == nil){ fprint(fd, "NIL\n"); return; } if(b->type == Tpivot){ for(i = 0; i < b->nbuf; i++){ getmsg(b, i, &m); fprint(fd, "%.*s|%M\n", 4*indent, spc, &m); } } for(i = 0; i < b->nval; i++){ getval(b, i, &kv); fprint(fd, "%.*s|%P\n", 4*indent, spc, &kv); if(b->type == Tpivot){ if((c = getblk(kv.bp, kv.bh)) == nil) sysfatal("failed load: %r"); if(recurse) rshowblk(fd, c, indent + 1, 1); putblk(c); } } } void initshow(void) { int i; memset(spc, ' ', sizeof(spc)); for(i = 0; i < sizeof(spc); i += 4) spc[i] = '|'; } void showblk(Blk *b, char *m, int recurse) { fprint(2, "=== %s\n", m); rshowblk(2, b, 0, recurse); } void fshowfs(int fd, char *m) { int h; fprint(fd, "=== %s\n", m); fprint(fd, "fs->height: %d\n", fs->height); rshowblk(fd, getroot(&h), 0, 1); } void showfs(char *m) { if(debug) fshowfs(2, m); } void showpath(Path *p, int np) { int i; for(i = 0; i < np; i++){ print("==> b=%p, n=%p, idx=%d\n", p[i].b, p[i].n, p[i].idx); print("\tclear=(%d, %d):%d\n", p[i].lo, p[i].hi, p[i].sz); print("\tl=%p, r=%p, n=%p, split=%d\n", p[i].l, p[i].r, p[i].n, p[i].split); } } void showfree(char *m) { Arange *r; int i; if(!debug) return; print("=== %s\n", m); for(i = 0; i < fs->narena; i++){ print("arena %d:\n", i); for(r = (Arange*)avlmin(fs->arenas[i].free); r != nil; r = (Arange*)avlnext(r)) print("\t%llx+%llx\n", r->off, r->len); } }