shithub: gefs

Download patch

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};