ref: c060aac1dc864907d750acb529553e0151f286e5
parent: 903c4891fb14330c01182ed0b565861f2c4220d5
author: Michael Forney <[email protected]>
date: Sat Feb 12 15:13:52 EST 2022
fs: add some missed putfid and fix an incorrect clunkfid condition Omitting putfid causes leaked Fid structures and Mnt/Dent references. Most of these are only in failure paths, so don't occur frequently. However, fsremove never calls putfid even in the success path so it only removes the clunk reference, not it's local reference. In fswalk, if m->fid != m->newfid, but we didn't walk the full path, then we haven't duped into newfid. If getdent fails, then we end up clunking the original fid. This would cause an Efid the next time the client tries to use it.
--- a/fs.c
+++ b/fs.c
@@ -796,6 +796,7 @@
}
if(o->mode != -1){
rerror(m, Einuse);
+ putfid(o);
return;
}
e = nil;
@@ -856,7 +857,7 @@
if(i > 0){
dent = getdent(up, &d);
if(dent == nil){
- if(m->fid != m->newfid)
+ if(f != o)
clunkfid(f);
rerror(m, Enomem);
putfid(f);
@@ -1094,13 +1095,15 @@
}
if(m->perm & (DMMOUNT|DMAUTH)){
rerror(m, "unknown permission");
+ putfid(f);
return;
}
de = f->dent;
rlock(de);
if(fsaccess(f, de->mode, de->uid, de->gid, DMWRITE) == -1){
- rerror(m, Eperm);
runlock(de);
+ rerror(m, Eperm);
+ putfid(f);
return;
}
runlock(de);
@@ -1233,6 +1236,7 @@
rerror(m, Efid);
return;
}
+ clunkfid(f);
rlock(f->dent);
if((e = candelete(f)) != nil)
@@ -1253,17 +1257,16 @@
goto Error;
}
- clunkfid(f);
runlock(f->dent);
r.type = Rremove;
respond(m, &r);
+ putfid(f);
return;
Error:
- clunkfid(f);
runlock(f->dent);
rerror(m, e);
- return;
+ putfid(f);
}
static void
@@ -1337,6 +1340,7 @@
if((e = btupsert(f->mnt->root, &mb, 1)) != nil){
wunlock(f->dent);
rerror(m, e);
+ putfid(f);
return;
}
wunlock(f->dent);