ref: 6d81e5b3fab334a63318d4ed88eccc89971ddeea
parent: 14d1179c21b1c93e696ac7ff23dc65b109ca9e3f
author: Ori Bernstein <ori@eigenstate.org>
date: Wed Oct 11 11:20:25 EDT 2023
blk: avoid removing blocks from cache prematurely the Bfreed flag could be set on a block before the block was freed; when putting things back into the cache and resurrecting them, this could lead to a stale block being left, because lrubot would lead cache entry becoming unreachable.
--- a/blk.c
+++ b/blk.c
@@ -939,7 +939,7 @@
}
void
-freeblk(Tree *t, Bptr bp)
+freeblk(Tree *t, Blk *b, Bptr bp)
{
Bfree *f;
ulong ge;
@@ -952,6 +952,10 @@
if((f = malloc(sizeof(Bfree))) == nil)
return;
f->bp = bp;
+ if(b != nil)
+ f->b = holdblk(b);
+ else
+ f->b = nil;
ge = agetl(&fs->epoch);
f->next = fs->limbo[ge];
@@ -1002,6 +1006,10 @@
qe.b = nil;
qe.qgen = agetv(&fs->qgen);
qput(a->sync, qe);
+ if(p->b != nil){
+ setflag(p->b, Bfreed);
+ dropblk(p->b);
+ }
free(p);
p = n;
}
@@ -1134,8 +1142,7 @@
rwakeupall(&fs->syncrz);
qunlock(&fs->synclk);
}else{
- if(checkflag(qe.b, Bfreed))
- continue;
+ if(checkflag(qe.b, Bfreed) == 0)
if(syncblk(qe.b) == -1){
ainc(&fs->broken);
fprint(2, "write: %r\n");
--- a/cache.c
+++ b/cache.c
@@ -67,8 +67,6 @@
fs->ctail->cnext = b;
if(fs->chead == nil)
fs->chead = b;
- b->bp.addr = -1;
- b->bp.hash = -1;
b->cprev = fs->ctail;
fs->ctail = b;
rwakeup(&fs->lrurz);
@@ -84,9 +82,11 @@
assert(b->magic == Magic);
h = ihash(b->bp.addr);
bkt = &fs->bcache[h % fs->cmax];
+ qlock(&fs->lrulk);
lock(bkt);
if(checkflag(b, Bcached)){
unlock(bkt);
+ qunlock(&fs->lrulk);
return;
}
assert(b->hnext == nil);
@@ -97,10 +97,11 @@
b->hnext = bkt->b;
bkt->b = b;
unlock(bkt);
+ qunlock(&fs->lrulk);
}
void
-cachedel(vlong addr)
+cachedel_lk(vlong addr)
{
Bucket *bkt;
Blk *b, **p;
@@ -125,25 +126,30 @@
}
unlock(bkt);
}
+void
+cachedel(vlong addr)
+{
+ qlock(&fs->lrulk);
+ cachedel_lk(addr);
+ qunlock(&fs->lrulk);
+}
Blk*
-cacheget(vlong off)
+cacheget(vlong addr)
{
Bucket *bkt;
u32int h;
Blk *b;
- h = ihash(off);
-
+ h = ihash(addr);
bkt = &fs->bcache[h % fs->cmax];
-
qlock(&fs->lrulk);
lock(bkt);
for(b = bkt->b; b != nil; b = b->hnext){
- if(b->bp.addr == off){
- holdblk(b);
+ if(b->bp.addr == addr){
+ holdblk(b);
lrudel(b);
- b->lasthold = getcallerpc(&off);
+ b->lasthold = getcallerpc(&addr);
break;
}
}
@@ -168,9 +174,10 @@
b = fs->ctail;
assert(b->magic == Magic);
assert(b->ref == 0);
- cachedel(b->bp.addr);
+ if(checkflag(b, Bcached))
+ cachedel_lk(b->bp.addr);
+ if(checkflag(b, Bcached)) print("%B cached %#p freed %#p\n", b->bp, b->cached, b->freed);
lrudel(b);
- if(checkflag(b, Bcached)) print("cached %B freed %#p\n", b->bp, b->freed);
assert(!checkflag(b, Bcached));
b->flag = 0;
b->lasthold = 0;
--- a/fns.h
+++ b/fns.h
@@ -53,7 +53,7 @@
void epochend(int);
void epochclean(void);
void freesync(void);
-void freeblk(Tree*, Bptr);
+void freeblk(Tree*, Blk*, Bptr);
int dlappend(Dlist *dl, Bptr);
int killblk(Tree*, Bptr);
int blkdealloc(vlong);
--- a/fs.c
+++ b/fs.c
@@ -376,7 +376,7 @@
memcpy(b->buf, t->buf, Blksz);
dropblk(t);
}
- freeblk(f->mnt->root, bp);
+ freeblk(f->mnt->root, nil, bp);
}else if(e != Esrch){
werrstr("%s", e);
return -1;
@@ -1994,7 +1994,7 @@
n = writeb(f, &kv[i], &bp[i], p, o, c, f->dent->length);
if(n == -1){
for(j = 0; j < i; j++)
- freeblk(f->mnt->root, bp[i]);
+ freeblk(f->mnt->root, nil, bp[i]);
wunlock(f->dent);
fprint(2, "%r");
putfid(f);
--- a/snap.c
+++ b/snap.c
@@ -115,7 +115,7 @@
}
Found:
h = ihash(gen) ^ ihash(bgen);
- p = &fs->dlcache[h % nelem(fs->dlcache)];
+ p = &fs->dlcache[h % fs->dlcmax];
dl->chain = *p;
*p = dl;
return dl;
@@ -161,8 +161,7 @@
}
}
bp = b->deadp;
- freeblk(&fs->snap, b->bp);
- setflag(b, Bfreed);
+ freeblk(&fs->snap, b, b->bp);
dropblk(b);
}
return nil;
--- a/tree.c
+++ b/tree.c
@@ -497,7 +497,7 @@
while(j < up->hi){
if(m.op == Oclearb){
bp = unpackbp(v.v, v.nv);
- freeblk(t, bp);
+ freeblk(t, nil, bp);
}
ok = apply(&v, &m, buf, sizeof(buf));
Copy:
@@ -636,8 +636,8 @@
l = newblk(t, b->type);
r = newblk(t, b->type);
if(l == nil || r == nil){
- freeblk(t, l->bp);
- freeblk(t, r->bp);
+ freeblk(t, l, l->bp);
+ freeblk(t, r, r->bp);
return -1;
}
@@ -735,8 +735,8 @@
l = newblk(t, b->type);
r = newblk(t, b->type);
if(l == nil || r == nil){
- freeblk(t, l->bp);
- freeblk(t, r->bp);
+ freeblk(t, l, l->bp);
+ freeblk(t, r, r->bp);
return -1;
}
d = l;
@@ -870,8 +870,8 @@
l = newblk(t, a->type);
r = newblk(t, a->type);
if(l == nil || r == nil){
- freeblk(t, l->bp);
- freeblk(t, r->bp);
+ freeblk(t, l, l->bp);
+ freeblk(t, r, r->bp);
return -1;
}
d = l;
@@ -1085,14 +1085,10 @@
Path *p;
for(p = path; p != path + npath; p++){
- if(p->b != nil){
- freeblk(t, p->b->bp);
- setflag(p->b, Bfreed);
- }
- if(p->m != nil){
- freeblk(t, p->m->bp);
- setflag(p->m, Bfreed);
- }
+ if(p->b != nil)
+ freeblk(t, p->b, p->b->bp);
+ if(p->m != nil)
+ freeblk(t, p->b, p->m->bp);
dropblk(p->b);
dropblk(p->nl);
dropblk(p->nr);
@@ -1196,8 +1192,7 @@
t->dirty = 1;
unlock(&t->lk);
- freeblk(t, b->bp);
- setflag(b, Bfreed);
+ freeblk(t, b, b->bp);
dropblk(b);
dropblk(r);
return nil;