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 void
epochclean(void) epochclean(int sync)
{ {
ulong c, e, ge; ulong c, e, ge;
Limbo *p, *n; Limbo *p, *n;
@ -907,7 +907,7 @@ epochclean(void)
for(i = 0; i < fs->nworker; i++){ for(i = 0; i < fs->nworker; i++){
e = agetl(&fs->lepoch[i]); e = agetl(&fs->lepoch[i]);
if((e & Eactive) && e != (ge | Eactive)){ if((e & Eactive) && e != (ge | Eactive)){
if(c < fs->cmax/4) if(!sync && c < fs->cmax/4)
return; return;
epochwait(); epochwait();
} }

View file

@ -26,18 +26,12 @@ setdbg(int fd, char **ap, int na)
} }
static void static void
sendsync(int fd, int halt) asend(int fd, int op)
{ {
Amsg *a; Amsg *a;
a = mallocz(sizeof(Amsg), 1); a = emalloc(sizeof(Amsg), 1);
if(a == nil){ a->op = op;
fprint(fd, "alloc sync msg: %r\n");
free(a);
return;
}
a->op = AOsync;
a->halt = halt;
a->fd = fd; a->fd = fd;
chsend(fs->admchan, a); chsend(fs->admchan, a);
} }
@ -45,14 +39,14 @@ sendsync(int fd, int halt)
static void static void
syncfs(int fd, char **, int) syncfs(int fd, char **, int)
{ {
sendsync(fd, 0); asend(fd, AOsync);
fprint(fd, "synced\n"); fprint(fd, "synced\n");
} }
static void static void
haltfs(int fd, char **, int) haltfs(int fd, char **, int)
{ {
sendsync(fd, 1); asend(fd, AOhalt);
fprint(fd, "gefs: ending...\n"); 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]); strecpy(a->old, a->old+sizeof(a->old), ap[0]);
if(na >= 2) if(na >= 2)
strecpy(a->new, a->new+sizeof(a->new), ap[1]); strecpy(a->new, a->new+sizeof(a->new), ap[1]);
sendsync(fd, 0); asend(fd, AOsync);
chsend(fs->admchan, a); chsend(fs->admchan, a);
} }

View file

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

View file

@ -59,7 +59,7 @@ void enqueue(Blk*);
void epochstart(int); void epochstart(int);
void epochend(int); void epochend(int);
void epochwait(void); void epochwait(void);
void epochclean(void); void epochclean(int);
void limbo(int op, Limbo*); void limbo(int op, Limbo*);
void freeblk(Tree*, Blk*); void freeblk(Tree*, Blk*);
void freebp(Tree*, Bptr); void freebp(Tree*, Bptr);

View file

@ -2563,7 +2563,7 @@ runmutate(int id, void *)
assert(estacksz() == 0); assert(estacksz() == 0);
epochend(id); epochend(id);
qunlock(&fs->mutlk); qunlock(&fs->mutlk);
epochclean(); epochclean(0);
if(a != nil) if(a != nil)
chsend(fs->admchan, a); chsend(fs->admchan, a);
@ -2612,7 +2612,7 @@ freetree(Bptr rb, vlong pred)
freetree(bp, pred); /* leak b on error() */ freetree(bp, pred); /* leak b on error() */
qlock(&fs->mutlk); qlock(&fs->mutlk);
qunlock(&fs->mutlk); qunlock(&fs->mutlk);
epochclean(); epochclean(0);
} }
} }
if(rb.gen > pred) if(rb.gen > pred)
@ -2648,7 +2648,7 @@ sweeptree(Tree *t)
freebp(nil, bp); freebp(nil, bp);
qlock(&fs->mutlk); qlock(&fs->mutlk);
qunlock(&fs->mutlk); qunlock(&fs->mutlk);
epochclean(); epochclean(0);
} }
btexit(&s); btexit(&s);
freetree(t->bp, t->pred); freetree(t->bp, t->pred);
@ -2672,20 +2672,27 @@ runsweep(int id, void*)
while(1){ while(1){
am = chrecv(fs->admchan); am = chrecv(fs->admchan);
switch(am->op){ 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: case AOsync:
tracem("syncreq"); tracem("syncreq");
if(!fs->snap.dirty && !am->halt) if(!fs->snap.dirty || agetl(&fs->rdonly))
goto Next; goto Next;
if(agetl(&fs->rdonly))
goto Justhalt;
if(waserror()){ if(waserror()){
fprint(2, "sync error: %s\n", errmsg()); fprint(2, "sync error: %s\n", errmsg());
ainc(&fs->rdonly); ainc(&fs->rdonly);
break; break;
} }
if(am->halt)
ainc(&fs->rdonly);
for(i = 0; i < fs->narena; i++){ for(i = 0; i < fs->narena; i++){
a = &fs->arenas[i]; a = &fs->arenas[i];
oldhd[i].addr = -1; oldhd[i].addr = -1;
@ -2709,7 +2716,7 @@ runsweep(int id, void*)
poperror(); poperror();
} }
qunlock(a); qunlock(a);
epochclean(); epochclean(0);
} }
sync(); /* oldhd blocks leaked on error() */ sync(); /* oldhd blocks leaked on error() */
@ -2730,17 +2737,10 @@ runsweep(int id, void*)
epochend(id); epochend(id);
qunlock(&fs->mutlk); qunlock(&fs->mutlk);
poperror(); 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(); poperror();
break; break;
@ -2852,7 +2852,7 @@ Justhalt:
epochend(id); epochend(id);
qunlock(&fs->mutlk); qunlock(&fs->mutlk);
poperror(); poperror();
epochclean(); epochclean(0);
nm = 0; nm = 0;
} }
} }
@ -2911,7 +2911,6 @@ runtasks(int, void *)
} }
a = emalloc(sizeof(Amsg), 1); a = emalloc(sizeof(Amsg), 1);
a->op = AOsync; a->op = AOsync;
a->halt = 0;
a->fd = -1; a->fd = -1;
chsend(fs->admchan, a); chsend(fs->admchan, a);