ref: 093c8160b677469b68ba957a2c1f6c9aa093e9d2
parent: 439759e82ed9df31cc192defdb86189727109468
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Oct 26 22:14:30 EDT 2023
fs: properly protect trees with EBR, don't let them change under us
--- a/dat.h
+++ b/dat.h
@@ -603,7 +603,7 @@
long ref;
vlong gen;
char *name;
- Tree *root;
+ Tree *root; /* EBR protected */
};
struct Conn {
--- a/fs.c
+++ b/fs.c
@@ -48,7 +48,7 @@
t = nil;
for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
if(strcmp(old, mnt->name) == 0){
- t = mnt->root;
+ t = agetp(&mnt->root);
ainc(&t->memref);
}
}
@@ -241,28 +241,17 @@
if(mnt == nil)
return Eattach;
- lock(mnt);
- r = mnt->root;
- ainc(&r->memref);
- unlock(mnt);
-
+ r = agetp(&mnt->root);
e = btlookup(r, k, kv, buf, nbuf);
- closesnap(r);
return e;
}
-int
-frozen(Tree *t)
-{
- return t->nlbl != 1 || t->nsucc != 0;
-}
-
static char*
upsert(Mount *mnt, Msg *m, int nm)
{
char *e;
- if(frozen(mnt->root))
+ if(mnt->root->nlbl != 1 || mnt->root->nsucc != 0)
if((e = updatesnap(&mnt->root, mnt->root, mnt->name)) != nil)
return e;
return btupsert(mnt->root, m, nm);
@@ -355,10 +344,6 @@
PACK64(m->k+1, f->qpath);
PACK64(m->k+9, fb);
-
- if(frozen(f->mnt->root))
- if(updatesnap(&f->mnt->root, f->mnt->root, f->mnt->name) != nil)
- return -1;
b = newdblk(f->mnt->root, Tdat, f->qpath);
if(b == nil)
return -1;
@@ -914,6 +899,7 @@
char *e, *p, *n, dbuf[Kvmax], kvbuf[Kvmax];
Mount *mnt;
Dent *de;
+ Tree *t;
User *u;
Fcall r;
Xdir d;
@@ -979,7 +965,8 @@
}
dk.k = dbuf;
dk.nk = p - dbuf;
- if((e = btlookup(mnt->root, &dk, &kv, kvbuf, sizeof(kvbuf))) != nil){
+ t = agetp(&mnt->root);
+ if((e = btlookup(t, &dk, &kv, kvbuf, sizeof(kvbuf))) != nil){
rerror(m, e);
goto Out;
}
@@ -1215,6 +1202,7 @@
Msg mb[3];
Xdir n;
Dir d;
+ Tree *t;
Fid *f;
Key k;
User *u;
@@ -1240,6 +1228,7 @@
goto Out;
}
+ t = agetp(&f->mnt->root);
n = de->Xdir;
n.qid.vers++;
p = opbuf+1;
@@ -1263,7 +1252,7 @@
rerror(m, Ename);
goto Out;
}
- if(walk1(f->mnt->root, f->dent->up, d.name, &old, &oldlen) == 0){
+ if(walk1(t, f->dent->up, d.name, &old, &oldlen) == 0){
rerror(m, Eexist);
goto Out;
}
@@ -1590,20 +1579,22 @@
candelete(Fid *f)
{
char *e, pfx[Dpfxsz];
+ Tree *t;
Scan s;
if(f->dent->qid.type == QTFILE)
return nil;
+ t = agetp(&f->mnt->root);
packdkey(pfx, sizeof(pfx), f->qpath, nil);
btnewscan(&s, pfx, sizeof(pfx));
- if((e = btenter(f->mnt->root, &s)) != nil)
+ if((e = btenter(t, &s)) != nil)
goto Out;
- if((e = btnext(f->mnt->root, &s, &s.kv)) != nil)
+ if((e = btnext(t, &s, &s.kv)) != nil)
goto Out;
if(!s.done)
e = Enempty;
Out:
- btexit(f->mnt->root, &s);
+ btexit(t, &s);
return e;
}
@@ -1850,7 +1841,7 @@
Scan *s;
s = f->scan;
- t = f->mnt->root;
+ t = agetp(&f->mnt->root);
if(s != nil && s->offset != 0 && s->offset != m->offset)
return Edscan;
if(s == nil || m->offset == 0){
@@ -1979,6 +1970,7 @@
char *p, *e;
int i, j;
Fcall r;
+ Tree *t;
Fid *f;
if((f = getfid(m->conn, m->fid)) == nil){
@@ -2012,6 +2004,7 @@
p = m->data;
o = m->offset;
c = m->count;
+ t = agetp(&f->mnt->root);
for(i = 0; i < nelem(kv)-1 && c != 0; i++){
assert(i == 0 || o%Blksz == 0);
kv[i].op = Oinsert;
@@ -2022,7 +2015,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, nil, bp[i]);
+ freeblk(t, nil, bp[i]);
wunlock(f->dent);
fprint(2, "%r");
putfid(f);
--- a/load.c
+++ b/load.c
@@ -54,7 +54,7 @@
void
loadfs(char *dev)
{
- Mount *mnt;
+ Mount *dump;
Arena *a;
Bptr bp;
char *e;
@@ -61,16 +61,15 @@
Tree *t;
int i, k;
- if((mnt = mallocz(sizeof(*mnt), 1)) == nil)
+ if((dump = mallocz(sizeof(*dump), 1)) == nil)
sysfatal("malloc: %r");
- if((mnt->name = strdup("dump")) == nil)
+ if((dump->name = strdup("dump")) == nil)
sysfatal("malloc: %r");
- mnt->ref = 1;
- mnt->root = nil;
- mnt->gen = -1;
- mnt->root = &fs->snap;
+ dump->ref = 1;
+ dump->gen = -1;
+ dump->root = &fs->snap;
- fs->snapmnt = mnt;
+ fs->snapmnt = dump;
fs->gotinfo = 0;
fs->narena = 1;
if((fs->fd = open(dev, ORDWR)) == -1)
--- a/snap.c
+++ b/snap.c
@@ -436,7 +436,7 @@
delsnap(o, t->gen, nil);
}
closesnap(o);
- *r = t;
+ asetp(r, t);
return nil;
}
@@ -497,7 +497,6 @@
abort();
f->op = DFtree;
f->t = t;
-print("limbo %#p\n", t);
ge = agetl(&fs->epoch);
f->next = fs->limbo[ge];
fs->limbo[ge] = f;