shithub: gefs

Download patch

ref: a0a4524bbb03bfa4902c6aa7102d912d403eef6b
parent: b33fa323a1d0194b79f6e1aabb88829767a43ba3
author: Ori Bernstein <[email protected]>
date: Mon Nov 29 10:55:17 EST 2021

tree: apply messages to the right files

--- a/blk.c
+++ b/blk.c
@@ -16,6 +16,8 @@
 static int	blkdealloc_lk(vlong);
 static void	cachedel(vlong);
 
+QLock blklock;
+
 Blk*
 readblk(vlong bp, int flg)
 {
@@ -41,7 +43,7 @@
 	b->bp.addr = bp;
 	b->bp.hash = -1;
 	b->bp.gen = -1;
-	b->ref = 0;	/* caller must increment */
+	b->ref = 1;
 	b->cnext = nil;
 	b->cprev = nil;
 	b->hnext = nil;
@@ -559,12 +561,8 @@
 		 * to the block, so we only
 		 * want to reset the refs
 		 * on an allocation.
-		 *
-		 * cacheblk incrmeents the
-		 * refcount, so we want to
-		 * start off at zero here.
 		 */
-		b->ref = 0;
+		b->ref = 1;
 	}
 	b->type = t;
 	b->flag = Bdirty;
@@ -680,18 +678,31 @@
 {
 	Blk *b;
 
-	if((b = lookupblk(bp.addr)) == nil){
-		if((b = readblk(bp.addr, flg)) == nil)
-			return nil;
-		if(blkhash(b) != bp.hash){
-			werrstr("corrupt block %B: %llx != %llx", bp, blkhash(b), bp.hash);
-			return nil;
-		}
-		b->bp.hash = bp.hash;
-		b->bp.gen = bp.gen;
+	if((b = lookupblk(bp.addr)) != nil)
+		return cacheblk(b);
+
+	qlock(&blklock);
+	if((b = lookupblk(bp.addr)) != nil){
+		cacheblk(b);
+		qunlock(&blklock);
+		return b;
 	}
-	assert(b->bp.addr == bp.addr);
-	return cacheblk(b);
+	if((b = readblk(bp.addr, flg)) == nil){
+		qunlock(&blklock);
+		return nil;
+	}
+	if(blkhash(b) != bp.hash){
+		werrstr("corrupt block %B: %llx != %llx", bp, blkhash(b), bp.hash);
+		qunlock(&blklock);
+		abort();
+		return nil;
+	}
+	b->bp.hash = bp.hash;
+	b->bp.gen = bp.gen;
+	cacheblk(b);
+	qunlock(&blklock);
+
+	return b;
 }
 
 Blk*
@@ -743,6 +754,7 @@
 
 	wlock(b);
 	b->flag |= Bzombie;
+	b->freed = getcallerpc(&b);
 	wunlock(b);
 	dprint("freeing block %B @ %ld, from 0x%p\n", b->bp, b->ref, getcallerpc(&b));
 
--- a/cache.c
+++ b/cache.c
@@ -13,13 +13,10 @@
 	Blk *e, *c;
 	u32int h;
 
-	/* FIXME: better hash. */
-	refblk(b);
 	assert(b->bp.addr != 0);
 	if(b->flag & Bzombie){
-		print("caching zombie: %B, flg=%x\n", b->bp, b->flag);
-		sleep(30*1000);
-//		abort();
+		print("caching zombie: %B, flg=%x, freed=0x%p\n", b->bp, b->flag, b->freed);
+		abort();
 	}
 	h = ihash(b->bp.addr);
 	bkt = &fs->cache[h % fs->cmax];
@@ -121,8 +118,10 @@
 	bkt = &fs->cache[h % fs->cmax];
 	lock(bkt);
 	for(b = bkt->b; b != nil; b = b->hnext)
-		if(b->bp.addr == off)
+		if(b->bp.addr == off){
+ 			refblk(b);
 			break;
+		}
 	unlock(bkt);
 	return b;
 }
--- a/dat.h
+++ b/dat.h
@@ -363,6 +363,7 @@
 
 	u32int	fid;
 	vlong	qpath;
+	long	ref;
 	int	mode;
 	int	iounit;
 
@@ -435,6 +436,8 @@
 
 	vlong	logsz;	/* for allocation log */
 	vlong	lognxt;	/* for allocation log */
+
+	uintptr	freed;	/* debug */
 
 	Bptr	bp;
 	long	ref;
--- a/fs.c
+++ b/fs.c
@@ -149,9 +149,19 @@
 		if(f->fid == fid)
 			break;
 	unlock(&fs->fidtablk);
+	ainc(&f->ref);
 	return f;
 }
 
+void
+putfid(Fid *f)
+{
+	if(adec(&f->ref) == 0){
+		clunkdent(f->dent);
+		free(f);
+	}
+}
+
 Fid*
 dupfid(int new, Fid *f)
 {
@@ -164,6 +174,7 @@
 
 	*n = *f;
 	n->fid = new;
+	n->ref = 2; /* one for dup, one for clunk */
 	n->mode = -1;
 	n->next = nil;
 
@@ -198,16 +209,13 @@
 	pf = &fs->fidtab[h];
 	for(f = fs->fidtab[h]; f != nil; f = f->next){
 		if(f == fid){
+			assert(adec(&f->ref) != 0);
 			*pf = f->next;
-			goto Found;
+			break;
 		}
 		pf = &f->next;
 	}
-	abort();
-Found:
-	clunkdent(fid->dent);
 	unlock(&fs->fidtablk);
-	free(fid);
 }
 
 void
@@ -453,6 +461,7 @@
 		p = packstr(&err, p, e, m->wname[i]);
 		if(err){
 			rerror(m, "bad walk: %r");
+			putfid(o);
 			return;
 		}
 		k.k = kbuf;
@@ -462,6 +471,7 @@
 		}
 		if(kv2dir(&kv, &d) == -1){
 			rerror(m, Efs);
+			putfid(o);
 			return;
 		}
 		prev = d.qid.path;
@@ -470,14 +480,17 @@
 	r.nwqid = i;
 	if(i == 0 && m->nwname != 0){
 		rerror(m, estr);
+		putfid(o);
 		return;
 	}
 	f = o;
 	if(m->fid != m->newfid && i == m->nwname){
 		if((f = dupfid(m->newfid, o)) == nil){
-			rerror(m, "%r");
+			rerror(m, Emem);
+			putfid(o);
 			return;
 		}
+		putfid(o);
 	}
 	if(i > 0){
 		dent = getdent(f->root.bp.addr, up, &d);
@@ -485,6 +498,7 @@
 			if(m->fid != m->newfid)
 				clunkfid(f);
 			rerror(m, Enomem);
+			putfid(f);
 			return;
 		}
 		if(i == m->nwname){
@@ -493,6 +507,7 @@
 		}
 	}
 	respond(m, &r);
+	putfid(f);
 }
 
 void
@@ -510,10 +525,12 @@
 	}
 	if((err = btlookup(&fs->root, f->dent, &kv, kvbuf, sizeof(kvbuf))) != nil){
 		rerror(m, err);
+		putfid(f);
 		return;
 	}
 	if((n = kv2statbuf(&kv, buf, sizeof(buf))) == -1){
 		rerror(m, "stat: %r");
+		putfid(f);
 		return;
 	}
 	r.type = Rstat;
@@ -520,6 +537,7 @@
 	r.stat = (uchar*)buf;
 	r.nstat = n;
 	respond(m, &r);
+	putfid(f);
 }
 
 void
@@ -550,6 +568,7 @@
 	clunkfid(f);
 	r.type = Rclunk;
 	respond(m, &r);
+	putfid(f);
 }
 
 void
@@ -596,11 +615,13 @@
 	mb.op = Oinsert;
 	mb.statop = 0;
 	if(dir2kv(f->qpath, &d, &mb, buf, sizeof(buf)) == -1){
-		rerror(m, "%r");
+		rerror(m, Efs);
+		putfid(f);
 		return;
 	}
 	if(btupsert(&fs->root, &mb, 1) == -1){
 		rerror(m, "%r");
+		putfid(f);
 		return;
 	}
 	dent = getdent(f->root.bp.addr, f->qpath, &d);
@@ -608,6 +629,7 @@
 		if(m->fid != m->newfid)
 			clunkfid(f);
 		rerror(m, Enomem);
+		putfid(f);
 		return;
 	}
 
@@ -616,6 +638,7 @@
 		unlock(f);
 		clunkdent(dent);
 		rerror(m, Einuse);
+		putfid(f);
 		return;
 	}
 	f->mode = m->mode;
@@ -631,6 +654,7 @@
 	r.qid = d.qid;
 	r.iounit = f->iounit;
 	respond(m, &r);
+	putfid(f);
 }
 
 void
@@ -654,6 +678,7 @@
 	if(btupsert(&fs->root, &mb, 1) == -1){
 		runlock(f->dent);
 		rerror(m, "remove: %r");
+		putfid(f);
 		return;
 	}
 	runlock(f->dent);
@@ -661,6 +686,7 @@
 
 	r.type = Rremove;
 	respond(m, &r);
+	putfid(f);
 }
 
 int
@@ -685,14 +711,17 @@
 	}
 	if((e = fslookup(f, f->dent, &kv, buf, sizeof(buf), 0)) != nil){
 		rerror(m, e);
+		putfid(f);
 		return;
 	}
 	if(kv2dir(&kv, &d) == -1){
 		rerror(m, Efs);
+		putfid(f);
 		return;
 	}
 	if(fsaccess(&d, m->mode) == -1){
 		rerror(m, Eperm);
+		putfid(f);
 		return;
 	}
 	wlock(f->dent);
@@ -706,15 +735,16 @@
 	if(f->mode != -1){
 		rerror(m, Einuse);
 		unlock(f);
+		putfid(f);
 		return;
 	}
 	f->mode = m->mode;
-	if((f->mode & 0x7) == OEXEC){
-		lock(&fs->root.lk);
-		f->root = fs->root;
+//	if((f->mode & 0x7) == OEXEC){
+//		lock(&fs->root.lk);
+//		f->root = fs->root;
 //		refblk(fs->root.bp);
-		unlock(&fs->root.lk);
-	}
+//		unlock(&fs->root.lk);
+//	}
 	if(f->mode & OTRUNC){
 		wlock(f->dent);
 //		freeb(f->dent, 0, dent->length);
@@ -723,6 +753,7 @@
 	}
 	unlock(f);
 	respond(m, &r);
+	putfid(f);
 }
 
 char*
@@ -812,7 +843,6 @@
 
 	e = fslookup(f, &k, &kv, kvbuf, sizeof(kvbuf), 0);
 	if(e != nil && e != Eexist){
-		fprint(2, "!!! error: %s", e);
 		werrstr(e);
 		return -1;
 	}
@@ -857,7 +887,7 @@
 	while(c != 0){
 		n = readb(f, p, o, c, e->length);
 		if(n == -1){
-			fprint(2, "read: %r\n");
+			fprint(2, "read %K [%Q]@%lld+%lld: %r\n", &e->Key, e->qid, o, c);
 			runlock(e);
 			return Efs;
 		}
@@ -887,6 +917,7 @@
 	r.count = 0;
 	if((r.data = malloc(m->count)) == nil){
 		rerror(m, Emem);
+		putfid(f);
 		return;
 	}
 	if(f->dent->qid.type & QTDIR)
@@ -895,11 +926,12 @@
 		e = fsreadfile(m, f, &r);
 	if(e != nil){
 		rerror(m, e);
+		putfid(f);
 		return;
-	}else{
-		respond(m, &r);
-		free(r.data);
 	}
+	respond(m, &r);
+	free(r.data);
+	putfid(f);
 }
 
 int
@@ -924,14 +956,11 @@
 		return -1;
 	if(fb < sz && (fo != 0 || n != Blksz)){
 		dprint("\tappending to block %B\n", b->bp);
-		if(fslookup(f, m, &kv, buf, sizeof(buf), 0) != nil){
+		if(fslookup(f, m, &kv, buf, sizeof(buf), 0) != nil)
 			return -1;
-		}
 		bp = unpackbp(kv.v);
-
-		if((t = getblk(bp, GBraw)) == nil){
+		if((t = getblk(bp, GBraw)) == nil)
 			return -1;
-		}
 		memcpy(b->buf, t->buf, Blksz);
 		freeblk(t);
 		putblk(t);
@@ -965,6 +994,7 @@
 	if((f->mode&0x7) != OWRITE){
 		dprint("f->mode: %x\n", f->mode);
 		rerror(m, Einuse);
+		putfid(f);
 		return;
 	}
 
@@ -984,6 +1014,8 @@
 			// FIXME: free pages
 			wunlock(f->dent);
 			rerror(m, "%r");
+			putfid(f);
+			abort();
 			return;
 		}
 		p += n;
@@ -1005,7 +1037,9 @@
 	}
 	if(btupsert(&fs->root, kv, i+1) == -1){
 		fprint(2, "upsert: %r\n");
+		putfid(f);
 		abort();
+		return;
 	}
 	wunlock(f->dent);
 
@@ -1012,6 +1046,7 @@
 	r.type = Rwrite;
 	r.count = m->count;
 	respond(m, &r);
+	putfid(f);
 }
 
 void
--- a/ream.c
+++ b/ream.c
@@ -101,8 +101,8 @@
 		sysfatal("ream: disk too small");
 	if((s = mallocz(sizeof(Blk), 1)) == nil)
 		sysfatal("ream: %r");
+	refblk(s);
 
-
 	sz = d->length;
 	sz = sz - (sz % Blksz) - Blksz;
 	fs->narena = sz / (128*GiB);
@@ -145,6 +145,7 @@
 	 */
 	if((r = newblk(Tleaf)) == nil)
 		sysfatal("ream: allocate root: %r");
+	refblk(r);
 	initroot(r);
 	finalize(r);
 	syncblk(r);
--- a/tree.c
+++ b/tree.c
@@ -186,20 +186,31 @@
 bufsearch(Blk *b, Key *k, Msg *m, int *same)
 {
 	int lo, hi, mid, r;
+	Msg cmp;
 
 	r = -1;
 	lo = 0;
-	hi = b->nbuf - 1;
-	while(lo <= hi){
+	hi = b->nbuf;
+	while(lo < hi){
 		mid = (hi + lo) / 2;
-		getmsg(b, mid, m);
-		r = keycmp(k, m);
+		getmsg(b, mid, &cmp);
+		r = keycmp(k, &cmp);
 		if(r < 0)
-			hi = mid - 1;
+			hi = mid;
 		else
 			lo = mid + 1;
 	}
+	/*
+	 * we can have duplicate messages, and we
+	 * want to point to the first of them:
+	 * scan backwards.
+	 */
 	lo--;
+	for(; lo > 0; lo--){
+		getmsg(b, lo-1, &cmp);
+		if(keycmp(k, &cmp) != 0)
+			break;
+	}
 	if(lo >= 0){
 		getmsg(b, lo, m);
 		r = keycmp(k, m);
@@ -351,11 +362,13 @@
 {
 	switch(m->op){
 	case Odelete:
+		assert(keycmp(r, m) == 0);
 		return 0;
 	case Oinsert:
 		cpkvp(r, m, buf, nbuf);
 		return 1;
 	case Owstat:
+		assert(keycmp(r, m) == 0);
 		statupdate(r, m);
 		return 1;
 	}
@@ -429,13 +442,14 @@
 				print("%d(/%d), %d: %M not insert\n", i, b->nval, j, &m);
 				abort();
 			}
+			cpkvp(&v, &m, buf, sizeof(buf));
 			spc -= valsz(&m);
 			goto Copy;
 		case 0:
 			i++;
 			while(j < up->hi){
-		Copy:
 				ok = apply(&v, &m, buf, sizeof(buf));
+		Copy:
 				j++;
 				p->pullsz += msgsz(&m);
 				if(j >= up->hi || pullmsg(up, j, &v, &m, &full, spc) != 0)
@@ -620,13 +634,14 @@
 				print("%d(/%d), %d: %M not insert\n", i, b->nval, j, &m);
 				abort();
 			}
+			cpkvp(&v, &m, buf, sizeof(buf));
 			spc -= valsz(&m);
 			goto Copy;
 		case 0:
 			i++;
 			while(j < up->hi){
-		Copy:
 				ok = apply(&v, &m, buf, sizeof(buf));
+		Copy:
 				p->pullsz += msgsz(&m);
 				j++;
 				if(j == up->hi || pullmsg(up, j, &v, &m, &full, spc) != 0)
@@ -1210,21 +1225,27 @@
 	if((p = calloc(h, sizeof(Blk*))) == nil)
 		return Emem;
 	err = Eexist;
+	ok = 0;
 	p[0] = refblk(b);
 	for(i = 1; i < h; i++){
 		if(blksearch(p[i-1], k, r, nil) == -1)
-			goto Out;
+			break;
 		if((p[i] = getblk(r->bp, 0)) == nil)
 			return Efs;
 	}
-	blksearch(p[h-1], k, r, &ok);
+	if(p[h-1] != nil)
+		blksearch(p[h-1], k, r, &ok);
 	if(ok)
 		cpkvp(r, r, buf, nbuf);
-	for(i = h - 2; i >= 0; i--){
+	for(i = h-2; i >= 0; i--){
+		if(p[i] == nil)
+			continue;
 		j = bufsearch(p[i], k, &m, &same);
-		if(!same)
+		if(j < 0 || !same)
 			continue;
-		for(; j < p[i]->nbuf; j++){
+		assert(ok || m.op == Oinsert);
+		ok = apply(r, &m, buf, nbuf);
+		for(j++; j < p[i]->nbuf; j++){
 			getmsg(p[i], j, &m);
 			if(keycmp(k, &m) != 0)
 				break;
@@ -1233,7 +1254,6 @@
 	}
 	if(ok)
 		err = nil;
-Out:
 	for(i = 0; i < h; i++)
 		if(p[i] != nil)
 			putblk(p[i]);