shithub: gefs

Download patch

ref: a9b58ffc013624e9a314316d2354fe4b52f9919c
parent: 5d7489fe70cf6163ca96a6e0b9d9bb53557602e3
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Apr 26 11:38:52 EDT 2022

log replay: clean up cache leaks

We were leaking some references into the cache that
would lead to deallocated blocks getting looked up
in newblk(); that caused Some Mess.

fix it so that we can assume new blocks are never
in cache, which will allow fixing cache flushing.

--- a/blk.c
+++ b/blk.c
@@ -23,7 +23,8 @@
 static vlong	blkalloc_lk(Arena*);
 static vlong	blkalloc(int);
 static int	blkdealloc_lk(vlong);
-static Blk*	initblk(vlong, int);
+static Blk*	blkbuf(void);
+static Blk*	initblk(Blk*, vlong, int);
 static int	logop(Arena *, vlong, vlong, int);
 
 static Blk magic;
@@ -118,7 +119,7 @@
 		break;
 	case Tlog:
 	case Tdead:
-		b->data = b->buf + _Loghdsz;
+		b->data = b->buf + Loghdsz;
 		break;
 		break;
 	case Tpivot:
@@ -269,8 +270,9 @@
 		pb = lb;
 		if((o = blkalloc_lk(a)) == -1)
 			return -1;
-		if((lb = initblk(o, Tlog)) == nil)
+		if((lb = blkbuf()) == nil)
 			return -1;
+		initblk(lb, o, Tlog);
 		cacheblk(lb);
 		lb->logsz = Loghashsz;
 		p = lb->data + lb->logsz;
@@ -367,13 +369,14 @@
 		switch(op){
 		case LogEnd:
 			dprint("log@%d: end\n", i);
+			putblk(b);
 			return 0;
 		case LogChain:
 			bp.addr = off & ~0xff;
 			bp.hash = -1;
 			bp.gen = -1;
+			putblk(b);
 			dprint("log@%d: chain %B\n", i, bp);
-			b->logsz = i+n;
 			goto Nextblk;
 			break;
 
@@ -426,9 +429,9 @@
 	 */
 	if((ba = blkalloc_lk(a)) == -1)
 		return -1;
-	if((b = initblk(ba, Tlog)) == nil)
+	if((b = blkbuf()) == nil)
 		return -1;
-	setflag(b, Bdirty);
+	initblk(b, ba, Tlog);
 	b->logsz = Loghashsz;
 
 	p = b->data + b->logsz;
@@ -469,10 +472,7 @@
 		free(log);
 		return -1;
 	}
-	if((b = initblk(ba, Tlog)) == nil){
-		free(log);
-		return -1;
-	}
+	initblk(b, ba, Tlog);
 	for(r = (Arange*)avlmin(a->free); r != nil; r = (Arange*)avlnext(r)){
 		if(n == sz){
 			sz *= 2;
@@ -526,11 +526,15 @@
 					break;
 				}
 			}
+			putblk(b);
 			lock(a);
+			lock(&fs->lrulk);
+			cachedel_lk(bp.addr);
 			if(blkdealloc_lk(ba) == -1){
 				unlock(a);
 				return -1;
 			}
+			unlock(&fs->lrulk);
 			unlock(a);
 		}
 	}
@@ -635,28 +639,33 @@
 }
 
 static Blk*
-initblk(vlong bp, int t)
+blkbuf(void)
 {
 	Blk *b;
 
-	if((b = lookupblk(bp)) == nil){
-		if((b = malloc(sizeof(Blk))) == nil)
-			return nil;
-		setmalloctag(b, getcallerpc(&bp));
-		/*
-		 * If the block is cached,
-		 * then the cache holds a ref
-		 * to the block, so we only
-		 * want to reset the refs
-		 * on an allocation.
-		 */
-		b->ref = 1;
-		b->cnext = nil;
-		b->cprev = nil;
-		b->hnext = nil;
-		b->flag = 0;
-	}
+	if((b = malloc(sizeof(Blk))) == nil)
+		return nil;
+	/*
+	 * If the block is cached,
+	 * then the cache holds a ref
+	 * to the block, so we only
+	 * want to reset the refs
+	 * on an allocation.
+	 */
+	b->ref = 1;
+	b->cnext = nil;
+	b->cprev = nil;
+	b->hnext = nil;
+	b->flag = 0;
 
+	return b;
+}
+
+
+static Blk*
+initblk(Blk *b, vlong bp, int t)
+{
+	assert(lookupblk(bp) == nil);
 	b->type = t;
 	b->bp.addr = bp;
 	b->bp.hash = -1;
@@ -669,7 +678,7 @@
 		break;
 	case Tdead:
 	case Tlog:
-		b->data = b->buf + _Loghdsz;
+		b->data = b->buf + Loghdsz;
 		break;
 	case Tpivot:
 		b->data = b->buf + Pivhdsz;
@@ -699,9 +708,12 @@
 
 	if((bp = blkalloc(t)) == -1)
 		return nil;
-	if((b = initblk(bp, t)) == nil)
+	if((b = blkbuf()) == nil)
 		return nil;
+	initblk(b, bp, t);
 	setmalloctag(b, getcallerpc(&t));
+	cacheblk(b);
+	assert(b->ref == 2);
 	return b;
 }
 
@@ -769,9 +781,6 @@
 	Blk *b;
 	int i;
 
-	if((b = lookupblk(bp.addr)) != nil)
-		return cacheblk(b);
-
 	i = ihash(bp.addr) % nelem(fs->blklk);
 	qlock(&fs->blklk[i]);
 	if((b = lookupblk(bp.addr)) != nil){
@@ -826,7 +835,7 @@
 {
 	if(b == nil || adec(&b->ref) != 0)
 		return;
-	assert(checkflag(b, Bcached));
+	assert(!checkflag(b, Bcached));
 	assert(checkflag(b, Bfreed) || !checkflag(b, Bdirty));
 	free(b);
 }
@@ -865,8 +874,10 @@
 
 	a = getarena(bp.addr);
 	lock(a);
+	lock(&fs->lrulk);
+	cachedel_lk(bp.addr);
 	blkdealloc_lk(bp.addr);
-	cachedel(bp.addr);
+	unlock(&fs->lrulk);
 	unlock(a);
 }
 
--- a/cache.c
+++ b/cache.c
@@ -6,7 +6,7 @@
 #include "dat.h"
 #include "fns.h"
 
-static void
+void
 cachedel_lk(vlong del)
 {
 	Bucket *bkt;
@@ -58,6 +58,8 @@
 	for(e = bkt->b; e != nil; e = e->hnext){
 		if(b == e)
 			goto Found;
+		if(b->bp.addr == e->bp.addr)
+			print("b: %p, e: %p\n", getmalloctag(b), getmalloctag(e));
 		assert(b->bp.addr != e->bp.addr);
 	}
 	b->hnext = bkt->b;
@@ -93,14 +95,6 @@
 Cached:
 	unlock(&fs->lrulk);
 	return b;
-}
-
-void
-cachedel(vlong del)
-{
-	lock(&fs->lrulk);
-	cachedel_lk(del);
-	unlock(&fs->lrulk);
 }
 
 Blk*
--- a/dat.h
+++ b/dat.h
@@ -65,13 +65,13 @@
 
 	Pivhdsz		= 10,
 	Leafhdsz	= 6,
-	_Loghdsz		= 2,
+	Loghdsz		= 2,
 	Loghashsz	= 8,
 	Rootsz		= 4+Ptrsz,	/* root pointer */
 	Pivsz		= Blksz - Pivhdsz,
 	Bufspc		= (Blksz - Pivhdsz) / 2,
 	Pivspc		= Blksz - Pivhdsz - Bufspc,
-	Logspc		= Blksz - _Loghdsz,
+	Logspc		= Blksz - Loghdsz,
 	Leafspc 	= Blksz - Leafhdsz,
 	Msgmax  	= 1 + (Kvmax > Kpmax ? Kvmax : Kpmax)
 };
--- a/fns.h
+++ b/fns.h
@@ -17,7 +17,7 @@
 Blk*	getblk(Bptr, int);
 Blk*	refblk(Blk*);
 Blk*	cacheblk(Blk*);
-void	cachedel(vlong);
+void	cachedel_lk(vlong);
 Blk*	lookupblk(vlong);
 Arena*	getarena(vlong);
 void	putblk(Blk*);
--- a/ream.c
+++ b/ream.c
@@ -97,7 +97,7 @@
 	b->type = Tlog;
 	b->bp.addr = addr;
 	b->logsz = 32;
-	b->data = b->buf + _Loghdsz;
+	b->data = b->buf + Loghdsz;
 	setflag(b, Bdirty);
 
 	p = b->data + Loghashsz;