shithub: gefs

Download patch

ref: 609d8e27749a12c41f527bbc43afe2b66f01449c
parent: 51d16fc61273db6d88691e9777066b70cbb397a1
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Dec 23 15:52:31 EST 2023

blk: take consistent snapshot under mutlk before syncing

--- a/blk.c
+++ b/blk.c
@@ -1070,14 +1070,13 @@
 	}
 }
 
-vlong
+void
 wrbarrier(void)
 {
 	Qent qe;
-	vlong gen;
 	int i;
 	
-	gen = aincv(&fs->qgen, 1);
+	aincv(&fs->qgen, 1);
 	fs->syncing = fs->nsyncers;
 	for(i = 0; i < fs->nsyncers; i++){
 		qe.op = Qfence;
@@ -1089,13 +1088,11 @@
 	}
 	while(fs->syncing != 0)
 		rsleep(&fs->syncrz);
-	return gen;
 }
 
 void
 sync(void)
 {
-	uvlong gen;
 	Arena *a;
 	int i;
 
@@ -1112,31 +1109,49 @@
 		qunlock(&fs->synclk);
 		nexterror();
 	}
+
+	/*
+	 * pass 0: Pack the blocks we want to sync
+	 *  while holding the write lock, and then
+	 *  wait until all the blocks they point at
+	 *  have hit disk; once they're on disk, we
+	 *  can take a consistent snapshot.
+         */
+	qlock(&fs->mutlk);
 	flushdlcache(1);
-	gen = wrbarrier();
-	/* pass 0: sync arena contents */
 	for(i = 0; i < fs->narena; i++){
 		a = &fs->arenas[i];
 		qlock(a);
-		logbarrier(a, gen);
 		setflag(a->logtl, Bdirty);
 		enqueue(a->logtl);
+		logbarrier(a, fs->qgen);
+
+		packarena(a->h0->data, Blksz, a);
+		packarena(a->h1->data, Blksz, a);
+		finalize(a->h0);
+		finalize(a->h1);
+		setflag(a->h0, Bdirty);
+		setflag(a->h1, Bdirty);
+		fs->arenabp[i] = a->h0->bp;
 		qunlock(a);
 	}
+
+	packsb(fs->sb0->buf, Blksz, fs);
+	packsb(fs->sb1->buf, Blksz, fs);
+	finalize(fs->sb0);
+	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.
-         */
-	for(i = 0; i < fs->narena; i++){
-		a = &fs->arenas[i];
-		qlock(a);
-		packarena(a->h0->data, Blksz, a);
-		setflag(a->h0, Bdirty);
-		enqueue(a->h0);
-		qunlock(a);
-	}
+	 */	wrbarrier();
+	for(i = 0; i < fs->narena; i++)
+		enqueue(fs->arenas[i].h0);
 	wrbarrier();
+
 	/*
 	 * pass 2: sync superblock; we have a consistent
 	 * set of block headers, so if we crash, we can
@@ -1144,28 +1159,17 @@
 	 * get synced after so that we can use them next
 	 * time around.
          */
-	for(i = 0; i < fs->narena; i++)
-		fs->arenabp[i] = fs->arenas[i].h0->bp;
-	packsb(fs->sb0->buf, Blksz, fs);
-	packsb(fs->sb1->buf, Blksz, fs);
-	finalize(fs->sb0);
-	finalize(fs->sb1);
 	syncblk(fs->sb0);
 	syncblk(fs->sb1);
-	fs->snap.dirty = 0;
+
 	/*
 	 * pass 3: sync block footers; if we crash here,
 	 *  the block headers are consistent, and we can
 	 *  use them.
          */
-	for(i = 0; i < fs->narena; i++){
-		a = &fs->arenas[i];
-		qlock(a);
-		packarena(a->h1->data, Blksz, a);
-		setflag(a->h1, Bdirty);
-		enqueue(a->h1);
-		qunlock(a);
-	}
+	for(i = 0; i < fs->narena; i++)
+		enqueue(fs->arenas[i].h1);
+
 	/*
 	 * Pass 4: clean up the old snap tree's deadlist
 	 */
--- a/fs.c
+++ b/fs.c
@@ -2277,10 +2277,11 @@
 			}
 			epochstart(id);
 			snapfs(am, &t);
-			sync();
 			epochend(id);
 			poperror();
 			qunlock(&fs->mutlk);
+
+			sync();
 
 			if(t != nil){
 				epochwait();
--- a/load.c
+++ b/load.c
@@ -30,13 +30,13 @@
 		h0 = getblk(bp, 0);
 		poperror();
 	}else
-		print("error %s\n", errmsg());
+		print("loading arena primary header: %s\n", errmsg());
 	bp.addr += Blksz;
 	if(!waserror()){
 		h1 = getblk(bp, 0);
 		poperror();
 	}else
-		print("error %s\n", errmsg());
+		print("loading arena backup header: %s\n", errmsg());
 
 	/* if neither head nor tail is consistent, we're hosed */
 	b = (h0 != nil) ? h0 : h1;