mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
gefs: fix fidtab locking order in clunkfid()
Do not abuse fidtab lock for serializing clunking. The clunk should serialize on Fid.Lock instead, so add a canlock check here. The lock order is strictly: Fid.Lock > Conn.fidtab[x].Lock
This commit is contained in:
parent
0ab0a036ed
commit
d31382ca17
1 changed files with 21 additions and 7 deletions
|
@ -769,12 +769,19 @@ dupfid(Conn *c, u32int new, Fid *f)
|
|||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* clunkfid() removes a fid from the
|
||||
* connection fid tab and drops reference.
|
||||
* Fid must be locked.
|
||||
*/
|
||||
static void
|
||||
clunkfid(Conn *c, Fid *fid, Amsg **ao)
|
||||
{
|
||||
Fid *f, **pf;
|
||||
u32int h;
|
||||
|
||||
assert(!canlock(fid));
|
||||
|
||||
h = ihash(fid->fid) % Nfidtab;
|
||||
lock(&c->fidtablk[h]);
|
||||
pf = &c->fidtab[h];
|
||||
|
@ -786,6 +793,8 @@ clunkfid(Conn *c, Fid *fid, Amsg **ao)
|
|||
}
|
||||
pf = &f->next;
|
||||
}
|
||||
unlock(&c->fidtablk[h]);
|
||||
|
||||
assert(f != nil);
|
||||
if(f->scan != nil){
|
||||
free(f->scan);
|
||||
|
@ -811,7 +820,6 @@ clunkfid(Conn *c, Fid *fid, Amsg **ao)
|
|||
(*ao)->end = f->dent->length;
|
||||
(*ao)->dent = f->dent;
|
||||
}
|
||||
unlock(&c->fidtablk[h]);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1796,8 +1804,8 @@ fsremove(Fmsg *m, int id, Amsg **ao)
|
|||
}
|
||||
t = f->mnt->root;
|
||||
nm = 0;
|
||||
*ao = nil;
|
||||
lock(f);
|
||||
*ao = nil;
|
||||
clunkfid(m->conn, f, ao);
|
||||
/* rclose files are getting removed here anyways */
|
||||
if(*ao != nil)
|
||||
|
@ -2291,7 +2299,7 @@ putconn(Conn *c)
|
|||
{
|
||||
Conn **pp;
|
||||
Amsg *a;
|
||||
Fid *f, *nf;
|
||||
Fid *f;
|
||||
int i;
|
||||
|
||||
if(adec(&c->ref) != 0)
|
||||
|
@ -2313,19 +2321,25 @@ putconn(Conn *c)
|
|||
close(c->cfd);
|
||||
|
||||
for(i = 0; i < Nfidtab; i++){
|
||||
lock(&c->fidtablk[i]);
|
||||
for(f = c->fidtab[i]; f != nil; f = nf){
|
||||
nf = f->next;
|
||||
for(;;){
|
||||
lock(&c->fidtablk[i]);
|
||||
f = c->fidtab[i];
|
||||
if(f == nil){
|
||||
unlock(&c->fidtablk[i]);
|
||||
break;
|
||||
}
|
||||
ainc(&f->ref);
|
||||
unlock(&c->fidtablk[i]);
|
||||
|
||||
lock(f);
|
||||
a = nil;
|
||||
clunkfid(c, f, &a);
|
||||
unlock(f);
|
||||
putfid(f);
|
||||
|
||||
if(a != nil)
|
||||
chsend(fs->admchan, a);
|
||||
}
|
||||
unlock(&c->fidtablk[i]);
|
||||
}
|
||||
free(c);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue