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.
This commit is contained in:
Ori Bernstein 2025-01-05 18:07:53 +00:00
parent ddfbf28cd4
commit a8361bc1b4
5 changed files with 29 additions and 37 deletions

View file

@ -892,7 +892,7 @@ Again:
}
void
epochclean(void)
epochclean(int sync)
{
ulong c, e, ge;
Limbo *p, *n;
@ -907,7 +907,7 @@ epochclean(void)
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();
}

View file

@ -26,18 +26,12 @@ setdbg(int fd, char **ap, int na)
}
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,14 +39,14 @@ sendsync(int fd, int halt)
static void
syncfs(int fd, char **, int)
{
sendsync(fd, 0);
asend(fd, AOsync);
fprint(fd, "synced\n");
}
static void
haltfs(int fd, char **, int)
{
sendsync(fd, 1);
asend(fd, AOhalt);
fprint(fd, "gefs: ending...\n");
}
@ -129,7 +123,7 @@ snapfs(int fd, char **ap, int na)
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);
}

View file

@ -323,6 +323,7 @@ enum {
AOnone,
AOsnap,
AOsync,
AOhalt,
AOclear,
AOrclose,
};
@ -398,6 +399,7 @@ struct Amsg {
int op;
int fd;
union {
/* AOsync, AOhalt: no data */
struct { /* AOsnap */
char old[128];
char new[128];
@ -405,9 +407,6 @@ struct Amsg {
char delete;
};
struct { /* AOsync */
int halt;
};
struct { /* AOclear, AOrclose */
Mount *mnt;
Dent *dent;

View file

@ -59,7 +59,7 @@ void enqueue(Blk*);
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);

View file

@ -2563,7 +2563,7 @@ runmutate(int id, void *)
assert(estacksz() == 0);
epochend(id);
qunlock(&fs->mutlk);
epochclean();
epochclean(0);
if(a != nil)
chsend(fs->admchan, a);
@ -2612,7 +2612,7 @@ freetree(Bptr rb, vlong pred)
freetree(bp, pred); /* leak b on error() */
qlock(&fs->mutlk);
qunlock(&fs->mutlk);
epochclean();
epochclean(0);
}
}
if(rb.gen > pred)
@ -2648,7 +2648,7 @@ sweeptree(Tree *t)
freebp(nil, bp);
qlock(&fs->mutlk);
qunlock(&fs->mutlk);
epochclean();
epochclean(0);
}
btexit(&s);
freetree(t->bp, t->pred);
@ -2672,20 +2672,27 @@ runsweep(int id, void*)
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);
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 @@ runsweep(int id, void*)
poperror();
}
qunlock(a);
epochclean();
epochclean(0);
}
sync(); /* oldhd blocks leaked on error() */
@ -2730,17 +2737,10 @@ runsweep(int id, void*)
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 @@ Justhalt:
epochend(id);
qunlock(&fs->mutlk);
poperror();
epochclean();
epochclean(0);
nm = 0;
}
}
@ -2911,7 +2911,6 @@ runtasks(int, void *)
}
a = emalloc(sizeof(Amsg), 1);
a->op = AOsync;
a->halt = 0;
a->fd = -1;
chsend(fs->admchan, a);