ref: 015bcdb965ed6055a2075ce1acdd94b4bb81990e
parent: 9c12f278297212e8644ba85975f2b1ab3bd2c8b9
author: Ori Bernstein <ori@eigenstate.org>
date: Wed Dec 27 20:19:40 EST 2023
fs, blk: hold mutlk when cleaning epoch, pull tree out of mnt to prevent version skew
--- a/fs.c
+++ b/fs.c
@@ -118,13 +118,12 @@
finalize(fs->sb1);
fs->snap.dirty = 0;
qunlock(&fs->mutlk);
- wrbarrier();
/*
* pass 1: sync block headers; if we crash here,
* the block footers are consistent, and we can
* use them.
- */ wrbarrier();
+ */
for(i = 0; i < fs->narena; i++)
enqueue(fs->arenas[i].h0);
wrbarrier();
@@ -136,6 +135,7 @@
* get synced after so that we can use them next
* time around.
*/
+ qlock(&fs->mutlk);
syncblk(fs->sb0);
syncblk(fs->sb1);
@@ -146,12 +146,10 @@
*/
for(i = 0; i < fs->narena; i++)
enqueue(fs->arenas[i].h1);
- wrbarrier();
/*
* Pass 4: clean up the old snap tree's deadlist
*/
- qlock(&fs->mutlk);
freedl(&fs->snapdl, 1);
fs->snapdl.hd.addr = -1;
fs->snapdl.hd.hash = -1;
@@ -160,8 +158,8 @@
fs->snapdl.tl.hash = -1;
fs->snapdl.tl.gen = -1;
fs->snapdl.ins = nil;
- qunlock(&fs->mutlk);
wrbarrier();
+ qunlock(&fs->mutlk);
qunlock(&fs->synclk);
poperror();
}
@@ -368,17 +366,6 @@
}
-static int
-lookup(Mount *mnt, Key *k, Kvp *kv, char *buf, int nbuf)
-{
- Tree *r;
-
- if(mnt == nil)
- error(Eattach);
- r = agetp(&mnt->root);
- return btlookup(r, k, kv, buf, nbuf);
-}
-
static void
upsert(Mount *mnt, Msg *m, int nm)
{
@@ -410,7 +397,7 @@
}
static int
-readb(Fid *f, char *d, vlong o, vlong n, vlong sz)
+readb(Tree *t, Fid *f, char *d, vlong o, vlong n, vlong sz)
{
char buf[17], kvbuf[17+32];
vlong fb, fo;
@@ -433,7 +420,7 @@
PACK64(k.k+1, f->qpath);
PACK64(k.k+9, fb);
- if(!lookup(f->mnt, &k, &kv, kvbuf, sizeof(kvbuf))){
+ if(!btlookup(t, &k, &kv, kvbuf, sizeof(kvbuf))){
memset(d, 0, n);
return n;
}
@@ -451,6 +438,7 @@
char buf[Kvmax];
vlong fb, fo;
Blk *b, *t;
+ Tree *r;
Bptr bp;
Kvp kv;
@@ -463,7 +451,8 @@
b = newblk(f->mnt->root, Tdat, f->qpath);
t = nil;
- if(lookup(f->mnt, m, &kv, buf, sizeof(buf))){
+ r = f->mnt->root;
+ if(btlookup(r, m, &kv, buf, sizeof(buf))){
bp = unpackbp(kv.v, kv.nv);
if(fb < sz && (fo != 0 || n != Blksz)){
t = getblk(bp, GBraw);
@@ -470,7 +459,7 @@
memcpy(b->buf, t->buf, Blksz);
dropblk(t);
}
- freeblk(f->mnt->root, nil, bp);
+ freeblk(r, nil, bp);
}
if(fo+n > Blksz)
n = Blksz-fo;
@@ -1134,7 +1123,7 @@
}
static int
-findparent(Fid *f, vlong *qpath, char **name, char *buf, int nbuf)
+findparent(Tree *t, Fid *f, vlong *qpath, char **name, char *buf, int nbuf)
{
char *p, kbuf[Keymax];
Kvp kv;
@@ -1143,7 +1132,7 @@
p = packsuper(kbuf, sizeof(kbuf), f->pqpath);
k.k = kbuf;
k.nk = p - kbuf;
- if(!lookup(f->mnt, &k, &kv, buf, nbuf))
+ if(!btlookup(t, &k, &kv, buf, nbuf))
return 0;
*name = unpackdkey(kv.v, kv.nv, qpath);
return 1;
@@ -1158,6 +1147,7 @@
Fid *o, *f;
Dent *dent;
Mount *mnt;
+ Tree *t;
Fcall r;
Xdir d;
Kvp kv;
@@ -1175,6 +1165,7 @@
}
if(o->mode != -1)
error(Einuse);
+ t = o->mnt->root;
mnt = o->mnt;
up = o->qpath;
prev = o->qpath;
@@ -1208,7 +1199,7 @@
dmode = d.mode;
goto Found;
}
- if(!findparent(o, &prev, &name, kbuf, sizeof(kbuf)))
+ if(!findparent(t, o, &prev, &name, kbuf, sizeof(kbuf)))
error(Esrch);
}
p = packdkey(kbuf, sizeof(kbuf), prev, name);
@@ -1218,7 +1209,7 @@
dmode = d.mode;
k.k = kbuf;
k.nk = p - kbuf;
- if(!lookup(mnt, &k, &kv, kvbuf, sizeof(kvbuf)))
+ if(!btlookup(t, &k, &kv, kvbuf, sizeof(kvbuf)))
break;
kv2dir(&kv, &d);
Found:
@@ -1730,6 +1721,7 @@
{
char *p, buf[Kvmax];
int mbits;
+ Tree *t;
Fcall r;
Xdir d;
Fid *f;
@@ -1746,10 +1738,11 @@
putfid(f);
return;
}
+ t = agetp(&f->mnt->root);
if((f->qpath & Qdump) != 0){
filldumpdir(&d);
}else{
- if(!lookup(f->mnt, f->dent, &kv, buf, sizeof(buf)))
+ if(!btlookup(t, f->dent, &kv, buf, sizeof(buf)))
error(Esrch);
kv2dir(&kv, &d);
}
@@ -1936,6 +1929,7 @@
vlong n, c, o;
char *p;
Dent *e;
+ Tree *t;
e = f->dent;
rlock(e);
@@ -1946,10 +1940,11 @@
p = r->data;
c = m->count;
o = m->offset;
+ t = agetp(&f->mnt->root);
if(m->offset + m->count > e->length)
c = e->length - m->offset;
while(c != 0){
- n = readb(f, p, o, c, e->length);
+ n = readb(t, f, p, o, c, e->length);
r->count += n;
if(n == 0)
break;
@@ -2233,8 +2228,8 @@
}
assert(estacksz() == 0);
epochend(id);
- qunlock(&fs->mutlk);
epochclean();
+ qunlock(&fs->mutlk);
if(a != nil)
chsend(fs->admchan, a);
@@ -2275,7 +2270,9 @@
getval(b, i, &kv);
bp = unpackbp(kv.v, kv.nv);
freetree(bp, pred);
+ qlock(&fs->mutlk);
epochclean();
+ qunlock(&fs->mutlk);
}
}
if(rb.gen > pred)
@@ -2289,6 +2286,10 @@
* has already waited for an epoch to tick over, there's
* nobody that can be accessing the tree other than us,
* and we just need to keep the limbo list short.
+ *
+ * Because this is the last reference to the tree, we don't
+ * need to hold the mutlk, other than when we free or kill
+ * blocks via epochclean.
*/
void
sweeptree(Tree *t)
@@ -2296,7 +2297,6 @@
char pfx[1];
Scan s;
Bptr bp;
-
pfx[0] = Kdat;
btnewscan(&s, pfx, 1);
btenter(t, &s);
@@ -2306,7 +2306,9 @@
bp = unpackbp(s.kv.v, s.kv.nv);
if(bp.gen > t->pred)
freeblk(nil, nil, bp);
+ qlock(&fs->mutlk);
epochclean();
+ qunlock(&fs->mutlk);
}
btexit(&s);
freetree(t->bp, t->pred);
@@ -2438,8 +2440,8 @@
m.nv = 0;
upsert(am->mnt, &m, 1);
epochend(id);
- qunlock(&fs->mutlk);
epochclean();
+ qunlock(&fs->mutlk);
poperror();
}
if(am->dent != nil){
--- a/load.c
+++ b/load.c
@@ -85,7 +85,6 @@
sysfatal("open %s: %r", dev);
if((d = dirfstat(fs->fd)) == nil)
sysfatal("stat %s: %r", dev);
-
eb = d->length;
eb = eb - (eb%Blksz) - Blksz;
bhd = (Bptr){0, -1, -1};