mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
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:
parent
ddfbf28cd4
commit
a8361bc1b4
5 changed files with 29 additions and 37 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue