ref: 9344873513e6bdde31746cd332aa9a9d954157d9
parent: c060aac1dc864907d750acb529553e0151f286e5
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Feb 12 20:31:20 EST 2022
fs: fix some races When enqueing a block, we could reorder the writes when sorting by sync generation rather than quiesce generation, which would lead to corrupt blocks. When clunking a dent, we could end up decrementing and not finding the entry in the table.
--- a/blk.c
+++ b/blk.c
@@ -650,6 +650,7 @@
b->bp.addr = bp;
b->bp.hash = -1;
b->bp.gen = fs->nextgen;
+ b->qgen = fs->qgen;
b->data = b->buf + Hdrsz;
b->fnext = nil;
@@ -875,6 +876,7 @@
if(!allquiesced)
return;
+ inc64(&fs->qgen, 1);
lock(&fs->freelk);
p = nil;
if(fs->freep != nil){
@@ -895,8 +897,8 @@
int
blkcmp(Blk *a, Blk *b)
{
- if(a->bp.gen != b->bp.gen)
- return (a->bp.gen < b->bp.gen) ? -1 : 1;
+ if(a->qgen != b->qgen)
+ return (a->qgen < b->qgen) ? -1 : 1;
if(a->bp.addr != b->bp.addr)
return (a->bp.addr < b->bp.addr) ? -1 : 1;
return 0;
--- a/dat.h
+++ b/dat.h
@@ -450,7 +450,7 @@
Chan *wrchan;
Chan *rdchan;
int nquiesce;
-
+ vlong qgen;
Lock activelk;
int active[32];
int lastactive[32];
@@ -621,7 +621,7 @@
Blk *fnext;
long flag;
- long syncgen;
+ long qgen;
/* serialized to disk in header */
short type; /* @0, for all */
--- a/fs.c
+++ b/fs.c
@@ -369,21 +369,21 @@
Dent *e, **pe;
u32int h;
- if(adec(&de->ref) == 0){
- h = ihash(de->qid.path) % Ndtab;
- lock(&fs->dtablk);
- pe = &fs->dtab[h];
- for(e = fs->dtab[h]; e != nil; e = e->next){
- if(e == de){
- *pe = e->next;
- unlock(&fs->dtablk);
- free(de);
- return;
- }
- pe = &e->next;
- }
- abort();
+ lock(&fs->dtablk);
+ if(adec(&de->ref) != 0)
+ goto Out;
+ h = ihash(de->qid.path) % Ndtab;
+ pe = &fs->dtab[h];
+ for(e = fs->dtab[h]; e != nil; e = e->next){
+ if(e == de)
+ break;
+ pe = &e->next;
}
+ assert(e != nil);
+ *pe = e->next;
+ free(de);
+Out:
+ unlock(&fs->dtablk);
}
void