shithub: gefs

Download patch

ref: 18b2896645d65b8daad467374f51a778272f9dd8
parent: 8bf1d98e0dcf18c48cd667eae9fa116dc9218908
author: Ori Bernstein <[email protected]>
date: Wed Feb 28 11:39:05 EST 2024

fs: adjust ordering of sync to survive crashes in all cases

--- a/blk.c
+++ b/blk.c
@@ -751,8 +751,14 @@
 			xh = bp.hash;
 			ck = b->bp.hash;
 		}
-		if(ck != xh)
-			broke("%s: %ullx %llux != %llux", Ecorrupt, bp.addr, xh, ck);
+		if(ck != xh){
+			if(flg & GBsoftchk){
+				fprint(2, "%s: %ullx %llux != %llux", Ecorrupt, bp.addr, xh, ck);
+				error(Ecorrupt);
+			}else{
+				broke("%s: %ullx %llux != %llux", Ecorrupt, bp.addr, xh, ck);
+			}
+		}
 	}
 	b->bp.gen = bp.gen;
 	b->lasthold = getcallerpc(&bp);
--- a/dat.h
+++ b/dat.h
@@ -267,6 +267,7 @@
 	GBraw	= 1<<0,
 	GBwrite	= 1<<1,
 	GBnochk	= 1<<2,
+	GBsoftchk = 1<<3,
 };
 
 enum {
--- a/fs.c
+++ b/fs.c
@@ -87,9 +87,19 @@
          */
 	qlock(&fs->mutlk);
 	tracem("packb");
-	dlsync();
 	for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next)
 		updatesnap(&mnt->root, mnt->root, mnt->name);
+	/*
+	 * Now that we've updated the snaps, we can sync the
+	 * dlist; the snap tree will not change from here.
+	 */
+	dlsync();
+	dl = fs->snapdl;
+	fs->snapdl.hd = Zb;
+	fs->snapdl.tl = Zb;
+	fs->snapdl.ins = nil;
+	traceb("syncdl.dl", dl.hd);
+	traceb("syncdl.rb", fs->snap.bp);
 	for(i = 0; i < fs->narena; i++){
 		a = &fs->arenas[i];
 		qlock(a);
@@ -112,16 +122,13 @@
 		fs->arenabp[i] = a->h0->bp;
 		qunlock(a);
 	}
-
+	assert(fs->snapdl.hd.addr == -1);
+	traceb("packsb.rb", fs->snap.bp);
 	packsb(fs->sb0->buf, Blksz, fs);
 	packsb(fs->sb1->buf, Blksz, fs);
 	finalize(fs->sb0);
 	finalize(fs->sb1);
 	fs->snap.dirty = 0;
-	dl = fs->snapdl;
-	fs->snapdl.hd = Zb;
-	fs->snapdl.tl = Zb;
-	fs->snapdl.ins = nil;
 	qunlock(&fs->mutlk);
 
 	/*
@@ -159,18 +166,11 @@
 	 * Pass 4: clean up the old snap tree's deadlist
 	 */
 	tracem("snapdl");
-	freedl(&dl, 1);
-	fs->snapdl.hd.addr = -1;
-	fs->snapdl.hd.hash = -1;
-	fs->snapdl.hd.gen = -1;
-	fs->snapdl.tl.addr = -1;
-	fs->snapdl.tl.hash = -1;
-	fs->snapdl.tl.gen = -1;
-	fs->snapdl.ins = nil;
 	wrbarrier();
 	qunlock(&fs->mutlk);
 	qunlock(&fs->synclk);
 	tracem("synced");
+	freedl(&dl, 1);
 	poperror();
 }
 
--- a/load.c
+++ b/load.c
@@ -27,13 +27,13 @@
 	h0 = nil;
 	h1 = nil;
 	if(!waserror()){
-		h0 = getblk(bp, 0);
+		h0 = getblk(bp, GBsoftchk);
 		poperror();
 	}else
 		print("loading arena primary header: %s\n", errmsg());
 	bp.addr += Blksz;
 	if(!waserror()){
-		h1 = getblk(bp, 0);
+		h1 = getblk(bp, GBsoftchk);
 		poperror();
 	}else
 		print("loading arena backup header: %s\n", errmsg());