ref: 2c2a71cd515dbd28a87b4ae85080775675a3e135
parent: 219c3121638214be8f1d4750510729a058fe2c8e
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Apr 28 01:59:10 EDT 2014
devmnt: abandon fid on botched Tclunk or Tremove if theres an error transmitting a Tclunk or Tremove request, we cannot assume the fid to be clunked. in case this was a transient error, reusing the fid on further requests will fail. as a work arround, we zero the channels fid and allocate a new fid before the chan is reused. this is not correct as we essentially leak the fid on the fileserver, but we will still be able to use the mount.
--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -225,20 +225,19 @@
lock(&chanalloc);
c = chanalloc.free;
- if(c != 0){
+ if(c != nil){
chanalloc.free = c->next;
- c->next = 0;
- }
- unlock(&chanalloc);
-
- if(c == nil){
+ c->next = nil;
+ } else {
+ unlock(&chanalloc);
c = smalloc(sizeof(Chan));
lock(&chanalloc);
- c->fid = ++chanalloc.fid;
c->link = chanalloc.list;
chanalloc.list = c;
- unlock(&chanalloc);
}
+ if(c->fid == 0)
+ c->fid = ++chanalloc.fid;
+ unlock(&chanalloc);
/* if you get an error before associating with a dev,
close calls rootclose, a nop */
--- a/sys/src/9/port/devmnt.c
+++ b/sys/src/9/port/devmnt.c
@@ -777,6 +777,13 @@
if(m->rip == up)
mntgate(m);
if(strcmp(up->errstr, Eintr) != 0){
+ switch(r->request.type){
+ case Tremove:
+ case Tclunk:
+ /* botch, abandon fid */
+ if(strcmp(up->errstr, Ehungup) != 0)
+ r->c->fid = 0;
+ }
mntflushfree(m, r);
nexterror();
}