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());