shithub: riscv

Download patch

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();
 		}