shithub: gefs

Download patch

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