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