ref: a742b7cb40538d0bdd5d4420a3478f7c7d60f157
parent: 3b3c0cd02a24e834336f2b11bcd02a49274cfc02
author: Ori Bernstein <[email protected]>
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"