shithub: gefs

Download patch

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;