ref: d31382ca17d92fe7c0b3c45f418f605d1759ed55
parent: 0ab0a036edd97a461b1b0b1ff5c5c8274f2a6f7b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Aug 30 15:16:13 EDT 2024
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
--- a/sys/src/cmd/gefs/fs.c
+++ b/sys/src/cmd/gefs/fs.c
@@ -769,6 +769,11 @@
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)
{
@@ -775,6 +780,8 @@
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 @@
}
pf = &f->next;
}
+ unlock(&c->fidtablk[h]);
+
assert(f != nil);
if(f->scan != nil){
free(f->scan);
@@ -811,7 +820,6 @@
(*ao)->end = f->dent->length;
(*ao)->dent = f->dent;
}
- unlock(&c->fidtablk[h]);
}
static int
@@ -1796,8 +1804,8 @@
}
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 @@
{
Conn **pp;
Amsg *a;
- Fid *f, *nf;
+ Fid *f;
int i;
if(adec(&c->ref) != 0)
@@ -2313,19 +2321,25 @@
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);
}
--
⑨