code: plan9front

Download patch

ref: 469573c3fe8a09a2b5a1607188f4e52f6f8bee10
parent: 843b2168c6a41b5fd91a7e9993d14dc0c186d4ca
author: Ori Bernstein <ori@eigenstate.org>
date: Sun May 26 18:01:41 EDT 2024

gefs: avoid holding the wrlock when syncing the file system

we only need to enforce ordering or syncedness to disk when
writing out the blocks during sync, we don't need to prevent
mutation on the tree once the arenas and superblock are
serialized.

--- a/sys/src/cmd/gefs/blk.c
+++ b/sys/src/cmd/gefs/blk.c
@@ -153,8 +153,10 @@
 
 	lo = 0;
 	hi = fs->narena;
-	if(b == 0)
+	if(b == fs->sb0->bp.addr)
 		return &fs->arenas[0];
+	if(b == fs->sb1->bp.addr)
+		return &fs->arenas[hi-1];
 	while(1){
 		mid = (hi + lo)/2;
 		a = &fs->arenas[mid];
@@ -1000,7 +1002,7 @@
 	int i;
 
 	if(qe.op == Qfree || qe.op == Qwrite)
-		assert(qe.bp.addr != 0 && (qe.bp.addr & (Blksz-1)) == 0);
+		assert((qe.bp.addr & (Blksz-1)) == 0);
 	else if(qe.op == Qfence)
 		assert(fs->syncing > 0);
 	else
--- a/sys/src/cmd/gefs/fs.c
+++ b/sys/src/cmd/gefs/fs.c
@@ -38,11 +38,18 @@
 static void
 wrbarrier(void)
 {
+	tracev("barrier", fs->qgen);
+	aincv(&fs->qgen, 1);
+}
+
+static void
+wrwait(void)
+{
 	Qent qe;
 	int i;
-	
+
+	tracev("wrwait", fs->qgen);
 	aincv(&fs->qgen, 1);
-	tracev("barrier", fs->qgen);
 	fs->syncing = fs->nsyncers;
 	for(i = 0; i < fs->nsyncers; i++){
 		qe.op = Qfence;
@@ -130,6 +137,8 @@
 	packsb(fs->sb1->buf, Blksz, fs);
 	finalize(fs->sb0);
 	finalize(fs->sb1);
+	setflag(fs->sb0, Bdirty);
+	setflag(fs->sb1, Bdirty);
 	fs->snap.dirty = 0;
 	qunlock(&fs->mutlk);
 
@@ -150,10 +159,10 @@
 	 * get synced after so that we can use them next
 	 * time around.
          */
-	qlock(&fs->mutlk);
 	tracem("supers");
-	syncblk(fs->sb0);
-	syncblk(fs->sb1);
+	enqueue(fs->sb0);
+	enqueue(fs->sb1);
+	wrbarrier();
 
 	/*
 	 * pass 3: sync block footers; if we crash here,
@@ -165,11 +174,13 @@
 		enqueue(fs->arenas[i].h1);
 
 	/*
-	 * Pass 4: clean up the old snap tree's deadlist
+	 * Pass 4: clean up the old snap tree's deadlist.
+	 * we need to wait for all the new data to hit disk
+	 * before we can free anything, otherwise it gets
+	 * clobbered.
 	 */
 	tracem("snapdl");
-	wrbarrier();
-	qunlock(&fs->mutlk);
+	wrwait();
 	freedl(&dl, 1);
 	qunlock(&fs->synclk);
 	tracem("synced");