ref: 880f8939fdec5e63d0f284dccd7148bbfa4cafb6
parent: 24ad9103062c541fca712b51889cde8297e8a406
author: glenda <[email protected]>
date: Sat Dec 11 13:56:14 EST 2021
cons: refactor fs dumping
--- a/check.c
+++ b/check.c
@@ -25,7 +25,7 @@
}
static int
-badblk(Blk *b, int h, Kvp *lo, Kvp *hi)
+badblk(int fd, Blk *b, int h, Kvp *lo, Kvp *hi)
{
Kvp x, y;
Msg mx, my;
@@ -35,51 +35,51 @@
fail = 0;
if(h < 0){
- fprint(2, "node too deep (loop?\n");
+ fprint(fd, "node too deep (loop?\n");
fail++;
return fail;
}
if(b->type == Tleaf){
if(h != 0){
- fprint(2, "unbalanced leaf\n");
+ fprint(fd, "unbalanced leaf\n");
fail++;
}
if(h != 0 && b->nval < 2){
- fprint(2, "underfilled leaf\n");
+ fprint(fd, "underfilled leaf\n");
fail++;
}
}
if(b->type == Tpivot && b->nval < 2){
- fprint(2, "underfilled pivot\n");
+ fprint(fd, "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);
- showblk(b, "wut", 1);
+ fprint(fd, "out of range keys %P != %P\n", lo, &x);
+ showblk(2, b, "wut", 1);
fail++;
}
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);
+ fprint(fd, "out of range keys %P >= %P\n", &y, hi);
fail++;
}
if(b->type == Tpivot){
if(isfree(x.bp.addr)){
- fprint(2, "freed block in use: %llx\n", x.bp.addr);
+ fprint(fd, "freed block in use: %llx\n", x.bp.addr);
fail++;
}
if((c = getblk(x.bp, 0)) == nil){
- fprint(2, "corrupt block: %r\n");
+ fprint(fd, "corrupt block: %r\n");
fail++;
continue;
}
if(blkfill(c) != x.fill){
- fprint(2, "mismatched block fill\n");
+ fprint(fd, "mismatched block fill\n");
fail++;
}
- if(badblk(c, h - 1, &x, &y))
+ if(badblk(fd, c, h - 1, &x, &y))
fail++;
putblk(c);
}
@@ -88,11 +88,11 @@
case -1:
break;
case 0:
- fprint(2, "duplicate keys %P, %P\n", &x, &y);
+ fprint(fd, "duplicate keys %P, %P\n", &x, &y);
fail++;
break;
case 1:
- fprint(2, "misordered keys %P, %P\n", &x, &y);
+ fprint(fd, "misordered keys %P, %P\n", &x, &y);
fail++;
break;
}
@@ -101,10 +101,10 @@
if(b->type == Tpivot){
getval(b, b->nval-1, &y);
if((c = getblk(x.bp, 0)) == nil){
- fprint(2, "corrupt block: %r\n");
+ fprint(fd, "corrupt block: %r\n");
fail++;
}
- if(c != nil && badblk(c, h - 1, &y, nil))
+ if(c != nil && badblk(fd, c, h - 1, &y, nil))
fail++;
}
if(b->type == Tpivot){
@@ -111,7 +111,7 @@
if(b->nbuf > 0){
getmsg(b, 0, &mx);
if(hi && keycmp(&mx, hi) >= 0){
- fprint(2, "out of range messages %P != %M\n", hi, &mx);
+ fprint(fd, "out of range messages %P != %M\n", hi, &mx);
fail++;
}
}
@@ -124,21 +124,21 @@
break;
case Owstat: /* kvp dirent */
if((my.statop & ~(Owsize|Owname|Owmode|Owmtime)) != 0){
- fprint(2, "invalid stat op %d\n", my.statop);
+ fprint(fd, "invalid stat op %d\n", my.statop);
fail++;
}
break;
default:
- fprint(2, "invalid message op %d\n", my.op);
+ fprint(fd, "invalid message op %d\n", my.op);
fail++;
break;
}
if(hi && keycmp(&y, hi) > 0){
- fprint(2, "out of range keys %P >= %P\n", &y, hi);
+ fprint(fd, "out of range keys %P >= %P\n", &y, hi);
fail++;
}
if(keycmp(&mx, &my) == 1){
- fprint(2, "misordered keys %P, %P\n", &x, &y);
+ fprint(fd, "misordered keys %P, %P\n", &x, &y);
fail++;
break;
}
@@ -174,9 +174,8 @@
return fail;
}
-/* TODO: this will grow into fsck. */
int
-checkfs(void)
+checkfs(int fd)
{
int ok, height;
Blk *b;
@@ -185,7 +184,7 @@
if(badfree())
ok = 0;
if((b = getroot(&fs->snap, &height)) != nil){
- if(badblk(b, height-1, nil, 0))
+ if(badblk(fd, b, height-1, nil, 0))
ok = 0;
putblk(b);
}
@@ -238,29 +237,64 @@
}
void
-showblk(Blk *b, char *m, int recurse)
+showblk(int fd, Blk *b, char *m, int recurse)
{
- fprint(2, "=== %s\n", m);
- rshowblk(2, b, 0, recurse);
+ fprint(fd, "=== %s\n", m);
+ rshowblk(fd, b, 0, recurse);
}
void
-showfs(int fd, char *m)
+showtree(int fd, Tree *t, char *m)
{
Blk *b;
int h;
- fprint(fd, "=== %s %B\n", m, fs->snap.bp);
+ fprint(fd, "=== [%s] %B\n", m, fs->snap.bp);
fprint(fd, "\tht: %d\n", fs->snap.ht);
fprint(fd, "\trt: %B\n", fs->snap.bp);
- b = getroot(&fs->snap, &h);
+ b = getroot(t, &h);
rshowblk(fd, b, 0, 1);
putblk(b);
}
void
-showcache(int fd)
+showfs(int fd, char **ap, int na)
{
+ char *p, *e, *name, kbuf[Kvmax], kvbuf[Kvmax];;
+ Tree t;
+ Key k;
+ Kvp kv;
+
+ name = (na == 0) ? "main" : ap[0];
+ k.k = kbuf;
+ k.k[0] = Ksnap;
+ k.nk = 1+snprint(k.k+1, sizeof(kbuf)-1, "%s", name);
+ if((e = btlookup(&fs->snap, &k, &kv, kvbuf, sizeof(kvbuf))) != nil){
+ fprint(fd, "lookup %K: %s\n", &k, e);
+ return;
+ }
+ if(kv.nv != Rootsz+Ptrsz){
+ fprint(fd, "bad snap %P\n", &kv);
+ return;
+ }
+
+ p = kv.v;
+ t.ht = GBIT32(p); p += 4;
+ t.bp.addr = GBIT64(p); p += 8;
+ t.bp.hash = GBIT64(p); p += 8;
+ t.bp.gen = GBIT64(p);
+ showtree(fd, &t, name);
+}
+
+void
+showsnap(int fd, char **, int)
+{
+ showtree(fd, &fs->snap, "snaps");
+}
+
+void
+showcache(int fd, char**, int)
+{
Bucket *bkt;
Blk *b;
int i;
@@ -278,8 +312,9 @@
}
void
-showpath(Path *p, int np)
+showpath(int fd, Path *p, int np)
{
+#define A(b) (b ? b->bp.addr : -1)
int i;
char *op[] = {
[POmod] = "POmod",
@@ -288,10 +323,9 @@
[POmerge] = "POmerge",
};
- print("path:\n");
-#define A(b) (b ? b->bp.addr : -1)
+ fprint(fd, "path:\n");
for(i = 0; i < np; i++){
- print("\t[%d] ==>\n"
+ fprint(fd, "\t[%d] ==>\n"
"\t\t%s: b(%p)=%llx [%s]\n"
"\t\tnl(%p)=%llx, nr(%p)=%llx\n"
"\t\tidx=%d, midx=%d\n"
@@ -308,12 +342,11 @@
}
void
-showfree(int fd, char *m)
+showfree(int fd, char **, int)
{
Arange *r;
int i;
- print("=== %s\n", m);
for(i = 0; i < fs->narena; i++){
fprint(fd, "arena %d:\n", i);
for(r = (Arange*)avlmin(fs->arenas[i].free); r != nil; r = (Arange*)avlnext(r))
--- a/cons.c
+++ b/cons.c
@@ -6,11 +6,65 @@
#include "dat.h"
#include "fns.h"
+typedef struct Cmd Cmd;
+
+struct Cmd {
+ char *name;
+ char *sub;
+ int minarg;
+ int maxarg;
+ void (*fn)(int, char**, int);
+};
+
+static void
+setdbg(int fd, char **ap, int na)
+{
+ debug = (na == 1) ? atoi(ap[0]) : !debug;
+ fprint(fd, "debug → %d\n", debug);
+}
+
+static void
+syncfs(int fd, char **, int)
+{
+ fprint(fd, "sync\n");
+}
+
+static void
+snapfs(int fd, char **, int)
+{
+ fprint(fd, "snap\n");
+}
+
+static void
+fsckfs(int fd, char**, int)
+{
+ if(checkfs(fd))
+ fprint(fd, "ok\n");
+ else
+ fprint(fd, "broken fs\n");
+}
+
+Cmd cmdtab[] = {
+ {.name="sync", .sub=nil, .minarg=0, .maxarg=0, .fn=syncfs},
+ {.name="snap", .sub=nil, .minarg=1, .maxarg=1, .fn=snapfs},
+ {.name="check", .sub=nil, .minarg=1, .maxarg=1, .fn=fsckfs},
+
+ /* debugging */
+ {.name="show", .sub="cache", .minarg=0, .maxarg=0, .fn=showcache},
+ {.name="show", .sub="fs", .minarg=0, .maxarg=1, .fn=showfs},
+ {.name="show", .sub="snap", .minarg=0, .maxarg=1, .fn=showsnap},
+ {.name="show", .sub="fid", .minarg=0, .maxarg=0, .fn=showfid},
+ {.name="show", .sub="free", .minarg=0, .maxarg=0, .fn=showfree},
+ {.name="debug", .sub=nil, .minarg=1, .maxarg=1, .fn=setdbg},
+ {.name=nil, .sub=nil},
+};
+
void
runcons(int, void *pfd)
{
- char buf[256], *arg[4];
- int fd, n, narg;
+ char buf[256], *f[4], **ap;
+ int i, n, nf, na, fd;
+ Cmd *c;
fd = (uintptr)pfd;
while(1){
@@ -17,36 +71,30 @@
if((n = read(fd, buf, sizeof(buf)-1)) == -1)
break;
buf[n] = 0;
- narg = tokenize(buf, arg, nelem(arg));
- if(narg == 0 || strlen(arg[0]) == 0)
+ nf = tokenize(buf, f, nelem(f));
+ if(nf == 0 || strlen(f[0]) == 0)
continue;
- if(strcmp(arg[0], "show") == 0){
- switch(narg){
- case 1:
- showfs(fd, "show");
- break;
- case 2:
- if(strcmp(arg[1], "fid") == 0){
- showfids(fd);
- break;
- }
- if(strcmp(arg[1], "cache") == 0){
- showcache(fd);
- break;
- }
- if(strcmp(arg[1], "free") == 0){
- showfree(fd, "free");
- break;
- }
- /* wet floor */
- default:
- fprint(fd, "show me yours first\n");
+ for(c = cmdtab; c->name != nil; c++){
+ ap = f;
+ na = nf;
+ if(strcmp(c->name, *ap) != 0)
+ continue;
+ ap++; na--;
+ if(c->sub != nil){
+ if(strcmp(c->sub, *ap) != 0)
+ continue;
+ ap++; na--;
}
- }else if(strcmp(arg[0], "check") == 0)
- checkfs();
- else if(strcmp(arg[0], "dbg") == 0 && narg == 2)
- debug = atoi(arg[1]);
- else
- fprint(fd, "unknown command %s\n", arg[0]);
+ if(na < c->minarg || na > c->maxarg)
+ continue;
+ c->fn(fd, ap, na);
+ break;
+ }
+ if(c->name == nil){
+ fprint(fd, "unknown command '");
+ for(i = 0; i < nf; i++)
+ fprint(fd, " %s", f[i]);
+ fprint(fd, "'\n");
+ }
}
}
--- a/dat.h
+++ b/dat.h
@@ -71,7 +71,6 @@
Kent, /* pqid[8] name[n] => dir[n]: serialized Dir */
Ksnap, /* id[8] => tree[]: snapshot */
Ksnapid, /* qid[8] => tree[]: snapshot for exec, transient */
-
Ksuper, /* qid[8] => pqid[8]: parent dir */
};
@@ -287,7 +286,8 @@
Lock qidlk;
vlong nextqid;
- vlong nextgen; /* unlocked: only touched by mutator thread */
+ Lock genlk;
+ vlong nextgen;
Arena *arenas;
int narena;
--- a/fns.h
+++ b/fns.h
@@ -30,6 +30,7 @@
void finalize(Blk*);
char* fillsuper(Blk*);
char* snapshot(Mount*);
+char* loadsnap(Tree*, char*);
uvlong siphash(void*, usize);
void reamfs(char*);
int loadarena(Arena*, vlong);
@@ -59,13 +60,16 @@
void getmsg(Blk *, int, Msg *);
void initshow(void);
-void showblk(Blk*, char*, int);
-void showpath(Path*, int);
-void showfs(int, char*);
-void showfids(int);
-void showcache(int);
-void showfree(int, char*);
-int checkfs(void);
+void showblk(int, Blk*, char*, int);
+void showpath(int, Path*, int);
+void showtree(int, Tree*, char*);
+
+void showfs(int, char**, int);
+void showsnap(int, char**, int);
+void showfid(int, char**, int);
+void showcache(int, char**, int);
+void showfree(int, char**, int);
+int checkfs(int);
#define dprint(...) \
do{ \
--- a/fs.c
+++ b/fs.c
@@ -121,7 +121,7 @@
}
void
-showfids(int fd)
+showfid(int fd, char**, int)
{
int i;
Fid *f;
--- a/tree.c
+++ b/tree.c
@@ -114,7 +114,7 @@
if(2*b->nval + b->valsz > spc){
dprint("2*%d + %d > %d [ksz: %d, vsz: %d]\n",
2*b->nval, b->valsz, spc, kv->nk, kv->nv);
- showblk(b, "setval overflow", 1);
+ showblk(2, b, "setval overflow", 1);
abort();
}
assert(2*b->nval + b->valsz <= spc);
@@ -468,8 +468,8 @@
p->pullsz += msgsz(&m);
if(m.op != Oinsert){
print("%d(/%d), %d: %M not insert\n", i, b->nval, j, &m);
- showblk(up->b, "parent", 0);
- showblk(p->b, "current", 0);
+ showblk(2, up->b, "parent", 0);
+ showblk(2, p->b, "current", 0);
abort();
}
while(pullmsg(up, j, &v, &m, &full, spc) == 0){
@@ -1176,13 +1176,12 @@
lock(&t->lk);
t->ht += dh;
t->bp = rb->bp;
- fs->nextgen++;
unlock(&t->lk);
freepath(path, npath);
free(path);
- if(!checkfs()){
- showfs(1, "broken");
- showpath(path, npath);
+ if(!checkfs(2)){
+ showtree(2, t, "broken");
+ showpath(2, path, npath);
abort();
}
if(redo)
@@ -1191,7 +1190,7 @@
Error:
freepath(path, npath);
free(path);
- return;
+ return Efs;
}
Blk*
@@ -1419,6 +1418,8 @@
char *e;
mnt->m.op = Oinsert;
+// mnt->m.k[0] = Ksnap;
+// PBIT64(mnt->m.k + 1, fs->nextgen++);
PBIT32(mnt->m.v + 0, mnt->root.ht);
PBIT64(mnt->m.v + 4, mnt->root.bp.addr);
PBIT64(mnt->m.v + 12, mnt->root.bp.hash);