shithub: riscv

Download patch

ref: a8361bc1b4b71a2ee495b23cfca1f03b5a844f28
parent: ddfbf28cd4be4beef34a45970751db4f58926c38
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Jan 5 13:07:53 EST 2025

gefs: flush limbo lists on halt

the limbo lists are full of blocks that are queued
for deferred free -- if we exit, we lose track of
them, and they never get freed.

--- a/sys/src/cmd/gefs/blk.c
+++ b/sys/src/cmd/gefs/blk.c
@@ -892,7 +892,7 @@
 }
 
 void
-epochclean(void)
+epochclean(int sync)
 {
 	ulong c, e, ge;
 	Limbo *p, *n;
@@ -907,7 +907,7 @@
 	for(i = 0; i < fs->nworker; i++){
 		e = agetl(&fs->lepoch[i]);
 		if((e & Eactive) && e != (ge | Eactive)){
-			if(c < fs->cmax/4)
+			if(!sync && c < fs->cmax/4)
 				return;
 			epochwait();
 		}
--- a/sys/src/cmd/gefs/cons.c
+++ b/sys/src/cmd/gefs/cons.c
@@ -26,18 +26,12 @@
 }
 
 static void
-sendsync(int fd, int halt)
+asend(int fd, int op)
 {
 	Amsg *a;
 
-	a = mallocz(sizeof(Amsg), 1);
-	if(a == nil){
-		fprint(fd, "alloc sync msg: %r\n");
-		free(a);
-		return;
-	}
-	a->op = AOsync;
-	a->halt = halt;
+	a = emalloc(sizeof(Amsg), 1);
+	a->op = op;
 	a->fd = fd;
 	chsend(fs->admchan, a);		
 }
@@ -45,7 +39,7 @@
 static void
 syncfs(int fd, char **, int)
 {
-	sendsync(fd, 0);
+	asend(fd, AOsync);
 	fprint(fd, "synced\n");
 }
 
@@ -52,7 +46,7 @@
 static void
 haltfs(int fd, char **, int)
 {
-	sendsync(fd, 1);
+	asend(fd, AOhalt);
 	fprint(fd, "gefs: ending...\n");
 }
 
@@ -129,7 +123,7 @@
 		strecpy(a->old, a->old+sizeof(a->old), ap[0]);
 	if(na >= 2)
 		strecpy(a->new, a->new+sizeof(a->new), ap[1]);
-	sendsync(fd, 0);
+	asend(fd, AOsync);
 	chsend(fs->admchan, a);
 }
 
--- a/sys/src/cmd/gefs/dat.h
+++ b/sys/src/cmd/gefs/dat.h
@@ -323,6 +323,7 @@
 	AOnone,
 	AOsnap,
 	AOsync,
+	AOhalt,
 	AOclear,
 	AOrclose,
 };
@@ -398,6 +399,7 @@
 	int	op;
 	int	fd;
 	union {
+		/* AOsync, AOhalt: no data */
 		struct {	/* AOsnap */
 			char	old[128];
 			char	new[128];
@@ -404,9 +406,6 @@
 			int	flag;
 			char	delete;
 
-		};
-		struct {	/* AOsync */
-			int	halt;
 		};
 		struct {	/* AOclear, AOrclose */
 			Mount	*mnt;
--- a/sys/src/cmd/gefs/fns.h
+++ b/sys/src/cmd/gefs/fns.h
@@ -59,7 +59,7 @@
 void	epochstart(int);
 void	epochend(int);
 void	epochwait(void);
-void	epochclean(void);
+void	epochclean(int);
 void	limbo(int op, Limbo*);
 void	freeblk(Tree*, Blk*);
 void	freebp(Tree*, Bptr);
--- a/sys/src/cmd/gefs/fs.c
+++ b/sys/src/cmd/gefs/fs.c
@@ -2563,7 +2563,7 @@
 		assert(estacksz() == 0);
 		epochend(id);
 		qunlock(&fs->mutlk);
-		epochclean();
+		epochclean(0);
 
 		if(a != nil)
 			chsend(fs->admchan, a);
@@ -2612,7 +2612,7 @@
 			freetree(bp, pred);	/* leak b on error() */
 			qlock(&fs->mutlk);
 			qunlock(&fs->mutlk);
-			epochclean();
+			epochclean(0);
 		}
 	}
 	if(rb.gen > pred)
@@ -2648,7 +2648,7 @@
 			freebp(nil, bp);
 		qlock(&fs->mutlk);
 		qunlock(&fs->mutlk);
-		epochclean();
+		epochclean(0);
 	}
 	btexit(&s);
 	freetree(t->bp, t->pred);
@@ -2672,12 +2672,21 @@
 	while(1){
 		am = chrecv(fs->admchan);
 		switch(am->op){
+		case AOhalt:
+			if(!agetl(&fs->rdonly)){
+				ainc(&fs->rdonly);
+				/* cycle through all epochs to clear them.  */
+				for(i = 0; i < 3; i++)
+					epochclean(1);
+				sync();
+			}
+			postnote(PNGROUP, getpid(), "halted");
+			exits(nil);
+			break;
 		case AOsync:
 			tracem("syncreq");
-			if(!fs->snap.dirty && !am->halt)
+			if(!fs->snap.dirty || agetl(&fs->rdonly))
 				goto Next;
-			if(agetl(&fs->rdonly))
-				goto Justhalt;
 			if(waserror()){
 				fprint(2, "sync error: %s\n", errmsg());
 				ainc(&fs->rdonly);
@@ -2684,8 +2693,6 @@
 				break;
 			}
 
-			if(am->halt)
-				ainc(&fs->rdonly);
 			for(i = 0; i < fs->narena; i++){
 				a = &fs->arenas[i];
 				oldhd[i].addr = -1;
@@ -2709,7 +2716,7 @@
 					poperror();
 				}
 				qunlock(a);
-				epochclean();
+				epochclean(0);
 			}
 
 			sync();	/* oldhd blocks leaked on error() */
@@ -2730,17 +2737,10 @@
 					epochend(id);
 					qunlock(&fs->mutlk);
 					poperror();
-					epochclean();
+					epochclean(0);
 				}
 			}
 
-Justhalt:
-			if(am->halt){
-				assert(fs->snapdl.hd.addr == -1);
-				assert(fs->snapdl.tl.addr == -1);
-				postnote(PNGROUP, getpid(), "halted");
-				exits(nil);
-			}
 			poperror();
 			break;
 
@@ -2852,7 +2852,7 @@
 					epochend(id);
 					qunlock(&fs->mutlk);
 					poperror();
-					epochclean();
+					epochclean(0);
 					nm = 0;
 				}
 			}
@@ -2911,7 +2911,6 @@
 		}
 		a = emalloc(sizeof(Amsg), 1);
 		a->op = AOsync;
-		a->halt = 0;
 		a->fd = -1;
 		chsend(fs->admchan, a);
 
--