shithub: front

Download patch

ref: a610f2eac21804f178494f1f90787f7fe0f9d187
parent: 235681677d512abed4ce217c2e358f3fcefd6465
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Oct 23 17:30:49 EDT 2024

nusb/disk: kill 9p procs before sysfatal(), devctl() before opendevdata()

This is an error probably when converting from libthread
to classid plan9 procs. umsrequest() used to just sysfatal()
once the error counter reached some value. But this leaves
9p procs (created by srvrelease()) around keeping the
device hanging around.

Instead, reply first, then attempt some recovery.
If that fails, kill our notegroup.

Also, for upcoming devusb changes, make sure we do
devctl() while the endpoint is not in use.

--- a/sys/src/cmd/nusb/disk/disk.c
+++ b/sys/src/cmd/nusb/disk/disk.c
@@ -241,17 +241,19 @@
 	return 0;
 }
 
-static int
+static void
 umsrecover(void)
 {
-	if(umsreset() < 0)
-		return -1;
+	if(umsreset() < 0){
+		/* kill the 9p procs */
+		postnote(PNGROUP, getpid(), "shutdown");
+		sysfatal("umsrecover: %r");
+	}
 	if(unstall(dev, ums->epin, Ein) < 0)
 		dprint(2, "%s: unstall epin: %r\n", argv0);
 	/* do we need this when epin == epout? */
 	if(unstall(dev, ums->epout, Eout) < 0)
 		dprint(2, "%s: unstall epout: %r\n", argv0);
-	return 0;
 }
 
 static int
@@ -500,14 +502,10 @@
 		dprint(2, "%s: phase error\n", argv0);
 		goto Fail;
 	}
-	ums->nerrs = 0;
 	return data->count - csw.dataresidue;
 
 Fail:
 	*status = STharderr;
-	if(ums->nerrs++ > 15)
-		sysfatal("%s: too many errors", dev->dir);
-	umsrecover();
 	return -1;
 }
 
@@ -765,6 +763,7 @@
 			if(count < 0){
 				lun->lbsize = 0;  /* medium may have changed */
 				responderror(req);
+				umsrecover();
 			}else{
 				req->ofcall.count = count;
 				respond(req, nil);
@@ -878,6 +877,7 @@
 			if(count < 0){
 				lun->lbsize = 0;  /* medium may have changed */
 				responderror(req);
+				umsrecover();
 			}else{
 				req->ofcall.count = count;
 				respond(req, nil);
@@ -997,6 +997,15 @@
 		closedev(ums->epin);
 		return -1;
 	}
+
+	devctl(ums->epin, "timeout 2000");
+	devctl(ums->epout, "timeout 2000");
+	if(usbdebug > 1 || diskdebug > 2){
+		devctl(ums->epin, "debug 1");
+		devctl(ums->epout, "debug 1");
+		devctl(dev, "debug 1");
+	}
+
 	if(ums->epin == ums->epout)
 		opendevdata(ums->epin, ORDWR);
 	else{
@@ -1009,15 +1018,6 @@
 		return -1;
 	}
 	dprint(2, "%s: ep in %s out %s\n", argv0, ums->epin->dir, ums->epout->dir);
-
-	devctl(ums->epin, "timeout 2000");
-	devctl(ums->epout, "timeout 2000");
-
-	if(usbdebug > 1 || diskdebug > 2){
-		devctl(ums->epin, "debug 1");
-		devctl(ums->epout, "debug 1");
-		devctl(dev, "debug 1");
-	}
 	return 0;
 }
 
--- a/sys/src/cmd/nusb/disk/ums.h
+++ b/sys/src/cmd/nusb/disk/ums.h
@@ -96,7 +96,6 @@
 	Umsc	*lun;
 	uchar	maxlun;
 	int	seq;
-	int	nerrs;
 	int	wrongresidues;
 };
 
--