shithub: gefs

Download patch

ref: 386c056a3d6f6a10c01b5327907d3a640aa44964
parent: 6aa266e6af166f528bce7316c59d80761284e663
author: Ori Bernstein <[email protected]>
date: Tue Oct 26 10:47:30 EDT 2021

check: better dump formatting, misc fixes.

--- a/blk.c
+++ b/blk.c
@@ -16,7 +16,6 @@
 static vlong	blkalloc_lk(Arena*);
 static int	blkdealloc_lk(vlong);
 static void	cachedel(vlong);
-static Blk	*lookupblk(vlong);
 
 Blk*
 readblk(vlong bp, int flg)
@@ -25,7 +24,7 @@
 	vlong off, rem, n;
 
 	assert(bp != -1);
-	if((b = malloc(sizeof(Blk))) == nil)
+	if((b = mallocz(sizeof(Blk), 1)) == nil)
 		return nil;
 	off = bp;
 	rem = Blksz;
@@ -586,28 +585,11 @@
 	b->cprev = nil;
 	b->hnext = nil;
 
+	print("new block %B from %p, flag=%x\n", b->bp, getcallerpc(&t), b->flag);
 	return cacheblk(b);
 }
 
-static Blk*
-lookupblk(vlong off)
-{
-	Bucket *bkt;
-	u32int h;
-	Blk *b;
 
-	h = ihash(off);
-
-	bkt = &fs->cache[h % fs->cmax];
-	lock(bkt);
-	for(b = bkt->b; b != nil; b = b->hnext)
-		if(b->bp.addr == off)
-			break;
-	unlock(bkt);
-	return b;
-}
-
-
 int
 syncblk(Blk *b)
 {
@@ -761,18 +743,11 @@
 {
 	Arena *a;
 
-	/* we can have patterns like:
-	 *   b = getblk();
-         *   use(b);
-         *   freeblk(b);
-         *   unref(b);
-         */
-	if(b->ref != 1 && ((b->flag & Bcached) && b->ref != 2)){
-		fprint(2, "warning: dangling refs: %B @ %ld\n", b->bp, b->ref);
-		wlock(b);
-		b->flag |= Bzombie;
-		wunlock(b);
-	}
+	wlock(b);
+	b->flag |= Bzombie;
+	wunlock(b);
+	fprint(2, "freeing block %B @ %ld, from 0x%p\n", b->bp, b->ref, getcallerpc(&b));
+
 	assert((b->flag & Bqueued) == 0);
 	a = getarena(b->bp.addr);
 	lock(a);
--- a/cache.c
+++ b/cache.c
@@ -16,7 +16,10 @@
 	/* FIXME: better hash. */
 	refblk(b);
 	assert(b->bp.addr != 0);
-	assert(!(b->flag & Bzombie));
+	if(b->flag & Bzombie){
+		print("caching zombie: %B, flg=%x\n", b->bp, b->flag);
+		abort();
+	}
 	h = ihash(b->bp.addr);
 	bkt = &fs->cache[h % fs->cmax];
 	lock(bkt);
@@ -70,7 +73,7 @@
 }
 
 static void
-cachedel(vlong del)
+cachedel_(vlong del)
 {
 	Bucket *bkt;
 	Blk *b, **p;
@@ -104,3 +107,22 @@
 		fs->chead = b;
 	unlock(&fs->lrulk);
 }
+
+Blk*
+lookupblk(vlong off)
+{
+	Bucket *bkt;
+	u32int h;
+	Blk *b;
+
+	h = ihash(off);
+
+	bkt = &fs->cache[h % fs->cmax];
+	lock(bkt);
+	for(b = bkt->b; b != nil; b = b->hnext)
+		if(b->bp.addr == off)
+			break;
+	unlock(bkt);
+	return b;
+}
+
--- a/check.c
+++ b/check.c
@@ -212,7 +212,8 @@
 		if(bkt->b != nil)
 			fprint(fd, "bkt%d\n", i);
 		for(b = bkt->b; b != nil; b = b->hnext)
-			fprint(fd, "\t%p[ref=%ld, t=%d] => %B\n", b, b->ref, b->type, b->bp);
+			if(b->ref != 1)
+				fprint(fd, "\t%p[ref=%ld, t=%d] => %B\n", b, b->ref, b->type, b->bp);
 		unlock(bkt);
 	}
 }
--- /dev/null
+++ b/dump.c
@@ -1,0 +1,168 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <avl.h>
+#include <fcall.h>
+#include <ctype.h>
+
+#include "dat.h"
+#include "fns.h"
+
+static int
+showkey(Fmt *fmt, Key *k)
+{
+	int n;
+
+	/*
+	 * dent: pqid[8] qid[8] -- a directory entry key.
+	 * ptr:  off[8] hash[8] -- a key for an Dir block.
+	 * dir:  fixed statbuf header, user ids
+	 */
+	switch(k->k[0]){
+	case Kdat:	/* qid[8] off[8] => ptr[16]:	pointer to data page */
+		n = fmtprint(fmt, "dat qid:%llx off:%llx", GBIT64(k->k+1), GBIT64(k->k+9));
+		break;
+	case Kent:	/* pqid[8] name[n] => dir[n]:	serialized Dir */
+		n = fmtprint(fmt, "ent dir:%llx, name:\"%.*s\")", GBIT64(k->k+1), k->nk-11, k->k+11);
+		break;
+	case Ksnap:	/* name[n] => dent[16] ptr[16]:	snapshot root */
+		n = fmtprint(fmt, "snap dent:%llx ptr:%llx", GBIT64(k->k+1), GBIT64(k->k+9));
+		break;
+	case Ksuper:	/* qid[8] => pqid[8]:		parent dir */
+		n = fmtprint(fmt, "up parent:%llx ptr:%llx", GBIT64(k->k+1), GBIT64(k->k+9));
+		break;
+	default:
+		n = fmtprint(fmt, "%.*H", k->nk, k->k);
+		break;
+	}
+	return n;
+}
+
+static int
+showval(Fmt *fmt, Kvp *v, int op)
+{
+	char *p;
+	Dir d;
+	int n;
+
+	n = 0;
+	switch(v->k[0]){
+	case Kdat:	/* qid[8] off[8] => ptr[16]:	pointer to data page */
+		n = fmtprint(fmt, "blk:%llx, hash:%llx", GBIT64(v->v), GBIT64(v->v+8));
+		break;
+	case Kent:	/* pqid[8] name[n] => dir[n]:	serialized Dir */
+		switch(op&0xf){
+		case Onop:
+		case Oinsert:
+			if(kv2dir(v, &d) == -1)
+				n = fmtprint(fmt, "bad dir");
+			else
+				n = fmtprint(fmt, "[qid=(%lld,%lud,%d), %lo, t=%lud,%lud, l=%lld]",
+					d.qid.path, d.qid.vers, d.qid.type,
+					d.mode, d.atime, d.mtime, d.length);
+			break;
+		case Odelete:
+			n = fmtprint(fmt, "delete");
+		case Owstat:
+			p = v->v;
+			if(op & Owmtime){
+				n += fmtprint(fmt, "mtime:%llx ", GBIT64(p));
+				p += 8;
+			}
+			if(op & Owsize){
+				n += fmtprint(fmt, "size:%llx ", GBIT64(p));
+				p += 8;
+			}
+			if(op & Owmode){
+				n += fmtprint(fmt, "mode:%o ", GBIT32(p));
+				p += 4;
+			}
+			if(p != v->v + v->nv)
+				abort();
+		}
+		break;
+	case Ksnap:	/* name[n] => dent[16] ptr[16]:	snapshot root */
+		n = fmtprint(fmt, "blk:%llx, hash:%llx", GBIT64(v->v), GBIT64(v->v+8));
+		break;
+	case Ksuper:	/* qid[8] => pqid[8]:		parent dir */
+		n = fmtprint(fmt, "parent: %llx", GBIT64(v->v));
+		break;
+	default:
+		n = fmtprint(fmt, "%.*H", v->nk, v->k);
+		break;
+	}
+	return n;
+
+}
+
+int
+Bconv(Fmt *fmt)
+{
+	Bptr bp;
+
+	bp = va_arg(fmt->args, Bptr);
+	return fmtprint(fmt, "(%llx,%llx,%llx)", bp.addr, bp.hash, bp.gen);
+}
+
+int
+Mconv(Fmt *fmt)
+{
+	char *opname[] = {
+	[Oinsert]	"Oinsert",
+	[Odelete]	"Odelete",
+	[Owstat]	"Owstat",
+	};
+	Msg *m;
+	int n;
+
+	m = va_arg(fmt->args, Msg*);
+	n = fmtprint(fmt, "Msg(%s, ", opname[m->op&0xf]);
+	n += showkey(fmt, m);
+	n += fmtprint(fmt, ") => (");
+	n += showval(fmt, m, m->op);
+	n += fmtprint(fmt, ")");
+	return n;
+}
+
+int
+Pconv(Fmt *fmt)
+{
+	Kvp *kv;
+	int n;
+
+	kv = va_arg(fmt->args, Kvp*);
+	n = fmtprint(fmt, "Kvp(");
+	n += showkey(fmt, kv);
+	n += fmtprint(fmt, ") => (");
+	if(kv->type == Vinl)
+		n += showval(fmt, kv, Onop);
+	else
+		n += fmtprint(fmt, "(%B,%ud))", kv->bp, kv->fill);
+	n += fmtprint(fmt, ")");
+	return n;
+}
+
+int
+Kconv(Fmt *fmt)
+{
+	Key *k;
+	int n;
+
+	k = va_arg(fmt->args, Key*);
+	n = fmtprint(fmt, "Key(");
+	n += showkey(fmt, k);
+	n += fmtprint(fmt, ")");
+	return n;
+}
+
+int
+Rconv(Fmt *fmt)
+{
+	Arange *r;
+
+	r = va_arg(fmt->args, Arange*);
+	if(r == nil)
+		return fmtprint(fmt, "<Arange:nil>");
+	else
+		return fmtprint(fmt, "Arange(%lld+%lld)", r->off, r->len);
+}
--- a/fns.h
+++ b/fns.h
@@ -14,6 +14,7 @@
 Blk*	getblk(Bptr, int);
 Blk*	refblk(Blk*);
 Blk*	cacheblk(Blk*);
+Blk*	lookupblk(vlong);
 Blk*	readblk(vlong, int);
 Arena*	getarena(vlong);
 void	putblk(Blk*);
@@ -86,6 +87,13 @@
 
 char	*packbp(char*, Bptr*);
 Bptr	unpackbp(char*);
+
+/* fmt */
+int	Bconv(Fmt*);
+int	Mconv(Fmt*);
+int	Pconv(Fmt*);
+int	Rconv(Fmt*);
+int	Kconv(Fmt*);
 
 /* scratch */
 void	setmsg(Blk *, int, Msg *);
--- a/fs.c
+++ b/fs.c
@@ -71,7 +71,7 @@
 	lock(&fs->dtablk);
 	for(e = fs->dtab[h]; e != nil; e = e->next){
 		if(e->qid.path == d->qid.path && e->rootb == root){
-			dprint("found %p\n", e);
+			dprint("found %p [%K]\n", e, &e->Key);
 			ainc(&e->ref);
 			unlock(&fs->dtablk);
 			return e;
@@ -95,6 +95,7 @@
 	e->nk = ek - e->buf;
 	e->next = fs->dtab[h];
 	fs->dtab[h] = e;
+	dprint("created %p [%K]\n", e, &e->Key);
 
 	unlock(&fs->dtablk);
 	return e;
@@ -108,7 +109,6 @@
 
 	if(adec(&de->ref) == 0){
 		h = (ihash(de->qid.path) ^ ihash(de->rootb)) % Ndtab;
-dprint("freeing dent, hash=%d, p=0x%p\n", h, de);
 		lock(&fs->dtablk);
 		pe = &fs->dtab[h];
 		for(e = fs->dtab[h]; e != nil; e = e->next){
@@ -430,7 +430,7 @@
 fswalk(Fmsg *m)
 {
 	char *p, *e, *estr, kbuf[Maxent];
-	int i, err;
+	int i, nwalk, err;
 	vlong up, prev;
 	Fid *o, *f;
 	Dent *dent;
@@ -450,6 +450,7 @@
 	}
 	err = 0;
 	estr = nil;
+	nwalk = 0;
 	up = o->qpath;
 	prev = o->qpath;
 	r.type = Rwalk;
@@ -469,13 +470,15 @@
 		k.nk = p - kbuf;
 //showfs("walking");
 //dprint("looking up %K\n", &k);
-		if((estr = fslookup(o, &k, &kv, &b, 0)) != nil)
+		if((estr = fslookup(o, &k, &kv, &b, 0)) != nil){
 			break;
+		}
 		if(kv2dir(&kv, &d) == -1){
 			rerror(m, Efs);
 			putblk(b);
 			return;
 		}
+		nwalk = i;
 		prev = d.qid.path;
 		putblk(b);
 		r.wqid[r.nwqid] = d.qid;
@@ -486,7 +489,7 @@
 		return;
 	}
 	f = o;
-	if(m->fid != m->newfid){
+	if(m->fid != m->newfid && i == m->nwname){
 		if((f = dupfid(m->newfid, o)) == nil){
 			rerror(m, "%r");
 			return;
@@ -493,7 +496,8 @@
 		}
 	}
 	if(i > 0){
-		d.name = m->wname[i-1];
+		d.name = m->wname[nwalk];
+		d.qid = m->wqid[nwalk];
 		dent = getdent(f->root.bp.addr, up, &d);
 		if(dent == nil){
 			if(m->fid != m->newfid)
@@ -501,8 +505,10 @@
 			rerror(m, Enomem);
 			return;
 		}
-		f->qpath = r.wqid[r.nwqid-1].path;
-		f->dent = dent;
+		if(i == m->nwname){
+			f->qpath = r.wqid[i-1].path;
+			f->dent = dent;
+		}
 	}
 	respond(m, &r);
 }
@@ -510,7 +516,7 @@
 void
 fsstat(Fmsg *m)
 {
-	char buf[STATMAX];
+	char *err, buf[STATMAX];
 	Fcall r;
 	Fid *f;
 	Kvp kv;
@@ -521,8 +527,9 @@
 		rerror(m, "no such fid");
 		return;
 	}
-	if(btlookup(&fs->root, f->dent, &kv, &b) != nil){
-		rerror(m, Eexist);
+	print("stat %K\n", &f->dent->Key);
+	if((err = btlookup(&fs->root, f->dent, &kv, &b)) != nil){
+		rerror(m, err);
 		return;
 	}
 	if((n = kv2statbuf(&kv, buf, sizeof(buf))) == -1){
@@ -1006,7 +1013,9 @@
 		if(n == -1){
 			// badwrite(f, i);
 			// FIXME: free pages
+			wunlock(f->dent);
 			rerror(m, "%r");
+			return;
 		}
 		p += n;
 		o += n;
@@ -1024,7 +1033,10 @@
 		PBIT64(kv[i].v, m->offset+m->count);
 		f->dent->length = m->offset+m->count;
 	}
-	btupsert(&fs->root, kv, i+1);
+	if(btupsert(&fs->root, kv, i+1) == -1){
+		fprint(2, "upsert: %r\n");
+		abort();
+	}
 	wunlock(f->dent);
 
 	r.type = Rwrite;
--- a/main.c
+++ b/main.c
@@ -3,7 +3,6 @@
 #include <bio.h>
 #include <avl.h>
 #include <fcall.h>
-#include <ctype.h>
 
 #include "dat.h"
 #include "fns.h"
@@ -14,13 +13,17 @@
 int	debug;
 char	*srvname = "gefs";
 
-static int
-Bconv(Fmt *fmt)
+void
+initfs(vlong cachesz)
 {
-	Bptr bp;
+	if((fs = mallocz(sizeof(Gefs), 1)) == nil)
+		sysfatal("malloc: %r");
 
-	bp = va_arg(fmt->args, Bptr);
-	return fmtprint(fmt, "(%llx,%llx,%llx)", bp.addr, bp.hash, bp.gen);
+	fs->cmax = cachesz/Blksz;
+	if(fs->cmax >= (2*GiB)/sizeof(Bucket))
+		sysfatal("cache too big");
+	if((fs->cache = mallocz(fs->cmax*sizeof(Bucket), 1)) == nil)
+		sysfatal("malloc: %r");
 }
 
 void
@@ -39,94 +42,6 @@
 	}
 }
 
-static int
-Mconv(Fmt *fmt)
-{
-	char *opname[] = {
-	[Oinsert]	"Oinsert",
-	[Odelete]	"Odelete",
-	[Owstat]	"Owstat",
-	};
-	Msg *m;
-
-	m = va_arg(fmt->args, Msg*);
-	return fmtprint(fmt, "Msg(%s, [%d]%.*X,[%d]%.*X)",
-		opname[m->op&0xf],
-		m->nk, m->nk, m->k,
-		m->nv, m->nv, m->v);
-}
-
-static int
-Pconv(Fmt *fmt)
-{
-	Kvp *kv;
-
-	kv = va_arg(fmt->args, Kvp*);
-	if(kv->type == Vinl)
-		return fmtprint(fmt, "Kvp([%d]%.*X,[%d]%.*X)",
-			kv->nk, kv->nk, kv->k,
-			kv->nv, kv->nv, kv->v);
-	else
-		return fmtprint(fmt, "Kvp([%d]%.*X,(%B,%ud))",
-			kv->nk, kv->nk, kv->k, kv->bp, kv->fill);
-}
-
-static int
-Rconv(Fmt *fmt)
-{
-	Arange *r;
-
-	r = va_arg(fmt->args, Arange*);
-	if(r == nil)
-		return fmtprint(fmt, "<Arange:nil>");
-	else
-		return fmtprint(fmt, "Arange(%lld+%lld)", r->off, r->len);
-}
-
-static int
-Kconv(Fmt *fmt)
-{
-	Key *k;
-
-	k = va_arg(fmt->args, Key*);
-	return fmtprint(fmt, "Key([%d]%.*X)", k->nk, k->nk, k->k);
-}
-
-static int
-Xconv(Fmt *fmt)
-{
-	char *s, *e;
-	int n, i;
-
-	n = 0;
-	i = fmt->prec;
-	s = va_arg(fmt->args, char*);
-	e = s + fmt->prec;
-	for(; s != e; s++){
-		if(i % 4 == 0 && i != 0)
-			n += fmtprint(fmt, ":");
-		i--;
-		if(isalnum(*s))
-			n += fmtrune(fmt, *s);
-		else
-			n += fmtprint(fmt, "%02x", *s&0xff);
-	}
-	return n;
-}
-
-void
-initfs(vlong cachesz)
-{
-	if((fs = mallocz(sizeof(Gefs), 1)) == nil)
-		sysfatal("malloc: %r");
-
-	fs->cmax = cachesz/Blksz;
-	if(fs->cmax >= (2*GiB)/sizeof(Bucket))
-		sysfatal("cache too big");
-	if((fs->cache = mallocz(fs->cmax*sizeof(Bucket), 1)) == nil)
-		sysfatal("malloc: %r");
-}
-
 int
 postfd(char *name, char *suff)
 {
@@ -189,12 +104,12 @@
 	initfs(cachesz);
 	initshow();
 	quotefmtinstall();
+	fmtinstall('H', encodefmt);
 	fmtinstall('B', Bconv);
 	fmtinstall('M', Mconv);
 	fmtinstall('P', Pconv);
 	fmtinstall('K', Kconv);
 	fmtinstall('R', Rconv);
-	fmtinstall('X', Xconv);
 	fmtinstall('F', fcallfmt);
 	if(ream){
 		reamfs(argv[0]);
--- a/mkfile
+++ b/mkfile
@@ -6,6 +6,7 @@
 	cache.$O\
 	check.$O\
 	cons.$O\
+	dump.$O\
 	fs.$O\
 	hash.$O\
 	load.$O\
--- a/tree.c
+++ b/tree.c
@@ -579,8 +579,10 @@
 	case Owstat:
 		p = m->v;
 		idx = blksearch(b, m, &kv, &same);
-		if(idx == -1 || !same)
+		if(idx == -1 || !same){
+			fprint(2, "missing keyval %P [idx=%d, same=%d]\n", &kv, idx, same);
 			abort();
+		}
 		/* bump version */
 		v = GBIT32(kv.v+8);
 		PBIT32(kv.v+8, v+1);