shithub: gefs

Download patch

ref: a742b7cb40538d0bdd5d4420a3478f7c7d60f157
parent: 3b3c0cd02a24e834336f2b11bcd02a49274cfc02
author: Ori Bernstein <ori@eigenstate.org>
date: Sun May 1 17:52:11 EDT 2022

cache: fix cache discipline

Only blocks in the LRU list are candidates for
eviction from the cache. Since we need dirty
blocks to stay in the cache, they do not go into
the LRU list until they are synced.

	new -> cached|dirty -> cached|lru -> free

--- a/blk.c
+++ b/blk.c
@@ -76,7 +76,7 @@
 	vlong off, rem, n;
 
 	assert(bp != -1);
-	if((b = malloc(sizeof(Blk))) == nil)
+	if((b = blkbuf()) == nil)
 		return nil;
 	off = bp;
 	rem = Blksz;
@@ -291,6 +291,7 @@
 				putblk(pb);
 				return -1;
 			}
+			lrubump(pb);
 			putblk(pb);
 		}
 		*tl = lb;
@@ -438,7 +439,7 @@
 	PBIT64(p, (uvlong)LogEnd);
 	finalize(b);
 	if(syncblk(b) == -1){
-		free(b);
+		putblk(b);
 		return -1;
 	}
 
@@ -528,13 +529,11 @@
 			}
 			putblk(b);
 			lock(a);
-			lock(&fs->lrulk);
-			cachedel_lk(bp.addr);
+			cachedel(bp.addr);
 			if(blkdealloc_lk(ba) == -1){
 				unlock(a);
 				return -1;
 			}
-			unlock(&fs->lrulk);
 			unlock(a);
 		}
 	}
@@ -785,6 +784,7 @@
 	qlock(&fs->blklk[i]);
 	if((b = lookupblk(bp.addr)) != nil){
 		cacheblk(b);
+		lrubump(b);
 		qunlock(&fs->blklk[i]);
 		return b;
 	}
@@ -803,6 +803,7 @@
 	b->bp.hash = h;
 	b->bp.gen = bp.gen;
 	cacheblk(b);
+	lrubump(b);
 	qunlock(&fs->blklk[i]);
 
 	return b;
@@ -874,10 +875,8 @@
 
 	a = getarena(bp.addr);
 	lock(a);
-	lock(&fs->lrulk);
-	cachedel_lk(bp.addr);
+	cachedel(bp.addr);
 	blkdealloc_lk(bp.addr);
-	unlock(&fs->lrulk);
 	unlock(a);
 }
 
@@ -1034,6 +1033,7 @@
 				fprint(2, "write: %r");
 				abort();
 			}
+			lrubump(b);
 		}
 		putblk(b);
 	}
--- a/cache.c
+++ b/cache.c
@@ -6,7 +6,7 @@
 #include "dat.h"
 #include "fns.h"
 
-void
+static void
 cachedel_lk(vlong del)
 {
 	Bucket *bkt;
@@ -22,14 +22,12 @@
 			break;
 		p = &b->hnext;
 	}
-	if(b == nil){
-		unlock(bkt);
-		return;
-	}
-	*p = b->hnext;
 	unlock(bkt);
+	if(b == nil)
+		return;
+	assert(checkflag(b, Bcached));
 
-	assert(b != fs->chead || b != fs->ctail);
+	*p = b->hnext;
 	if(b->cnext != nil)
 		b->cnext->cprev = b->cprev;
 	if(b->cprev != nil)
@@ -40,17 +38,26 @@
 		fs->chead = b->cnext;
 	b->cnext = nil;
 	b->cprev = nil;
-	clrflag(b, Bcached);
 	fs->ccount--;
+
+	clrflag(b, Bcached);
 	putblk(b);
 }
 
+void
+cachedel(vlong del)
+{
+	lock(&fs->lrulk);
+	cachedel_lk(del);
+	unlock(&fs->lrulk);
+}
+
 Blk*
 cacheblk(Blk *b)
 {
 	Bucket *bkt;
-	Blk *e, *c;
 	u32int h;
+	Blk *e;
 
 	h = ihash(b->bp.addr);
 	bkt = &fs->cache[h % fs->cmax];
@@ -58,18 +65,33 @@
 	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;
 	bkt->b = b;
+	if(!checkflag(b, Bcached)){
+		setflag(b, Bcached);
+		refblk(b);
+		fs->ccount++;
+	}
 Found:
 	unlock(bkt);
+	return b;
+}
 
+Blk*
+lrubump(Blk *b)
+{
+	Blk *c;
+
 	lock(&fs->lrulk);
+	if(checkflag(b, Bcached) == 0){
+		assert(b->cnext == nil);
+		assert(b->cprev == nil);
+		goto Done;
+	}
 	if(b == fs->chead)
-		goto Cached;
+		fs->chead = b->cnext;
 
 	if(b == fs->ctail)
 		fs->ctail = b->cprev;
@@ -84,15 +106,12 @@
 	b->cnext = fs->chead;
 	b->cprev = nil;
 	fs->chead = b;
-	if(!checkflag(b, Bcached)){
-		setflag(b, Bcached);
-		fs->ccount++;
-		refblk(b);
-	}
-	for(c = fs->ctail; c != nil && fs->ccount >= fs->cmax; c = fs->ctail)
+	for(c = fs->ctail; c != b && fs->ccount >= fs->cmax; c = fs->ctail){
+		assert(c != fs->chead);
 		cachedel_lk(c->bp.addr);
+	}
 
-Cached:
+Done:
 	unlock(&fs->lrulk);
 	return b;
 }
--- a/fns.h
+++ b/fns.h
@@ -17,7 +17,8 @@
 Blk*	getblk(Bptr, int);
 Blk*	refblk(Blk*);
 Blk*	cacheblk(Blk*);
-void	cachedel_lk(vlong);
+Blk*	lrubump(Blk*);
+void	cachedel(vlong);
 Blk*	lookupblk(vlong);
 Arena*	getarena(vlong);
 void	putblk(Blk*);
--- a/fs.c
+++ b/fs.c
@@ -2,6 +2,7 @@
 #include <libc.h>
 #include <auth.h>
 #include <fcall.h>
+#include <pool.h>
 #include <avl.h>
 
 #include "dat.h"