shithub: gefs

Download patch

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);