summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-10-16 12:26:56 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-10-16 12:26:56 +0200
commit965bb2d2480363bf02ad0c10f92b7a6b4962e38f (patch)
tree6b208c761f464ca6b5bb24aab9f6e7620e7d2337
parent1cd4579cdc9bbfc9001ed15af6bf01e331e07493 (diff)
downloadplan9front-965bb2d2480363bf02ad0c10f92b7a6b4962e38f.tar.xz
nusb/disk: handle blocking usb access with srv released
usb is bound after /dev, so a hanging usb device will hang access to /dev. we avoid this by releasing the srv, which allows the fs to still handle reads and walks of the directories. ios are serialized by a qlock in the Umsc structure.
-rw-r--r--sys/src/cmd/nusb/disk/disk.c26
-rw-r--r--sys/src/cmd/nusb/disk/ums.h2
2 files changed, 26 insertions, 2 deletions
diff --git a/sys/src/cmd/nusb/disk/disk.c b/sys/src/cmd/nusb/disk/disk.c
index b9bbe6cf6..0b964f052 100644
--- a/sys/src/cmd/nusb/disk/disk.c
+++ b/sys/src/cmd/nusb/disk/disk.c
@@ -619,7 +619,11 @@ dopen(Req *req)
lun = ums->lun + (req->ofcall.qid.path >> 16) - 1;
switch(path){
case Qraw:
+ srvrelease(req->srv);
+ qlock(lun);
lun->phase = Pcmd;
+ qunlock(lun);
+ srvacquire(req->srv);
break;
}
respond(req, nil);
@@ -684,6 +688,7 @@ dread(Req *req)
long count;
void *data;
vlong offset;
+ Srv *srv;
q = req->fid->qid;
if(q.path == 0){
@@ -701,13 +706,19 @@ dread(Req *req)
case Qdir:
dirread9p(req, dirgen, lun);
respond(req, nil);
- break;
+ return;
case Qctl:
s = ctlstring(lun);
readstr(req, s);
free(s);
respond(req, nil);
- break;
+ return;
+ }
+
+ srv = req->srv;
+ srvrelease(srv);
+ qlock(lun);
+ switch(path){
case Qraw:
if(lun->lbsize <= 0 && umscapacity(lun) < 0){
respond(req, "phase error");
@@ -772,6 +783,9 @@ dread(Req *req)
respond(req, nil);
break;
}
+
+ qunlock(lun);
+ srvacquire(srv);
}
static void
@@ -786,6 +800,7 @@ dwrite(Req *req)
long count;
void *data;
vlong offset;
+ Srv *srv;
lun = ums->lun + (req->fid->qid.path >> 16) - 1;
path = req->fid->qid.path & 0xFFFF;
@@ -793,6 +808,10 @@ dwrite(Req *req)
data = req->ifcall.data;
offset = req->ifcall.offset;
+ srv = req->srv;
+ srvrelease(srv);
+ qlock(lun);
+
switch(path){
case Qctl:
s = emallocz(count+1, 1);
@@ -896,6 +915,9 @@ dwrite(Req *req)
respond(req, nil);
break;
}
+
+ qunlock(lun);
+ srvacquire(srv);
}
int
diff --git a/sys/src/cmd/nusb/disk/ums.h b/sys/src/cmd/nusb/disk/ums.h
index f8dbfa4fc..95f1929a3 100644
--- a/sys/src/cmd/nusb/disk/ums.h
+++ b/sys/src/cmd/nusb/disk/ums.h
@@ -76,6 +76,8 @@ struct Umsc
long off; /* offset within a block */
long nb; /* byte count */
+ QLock;
+
/* partitions */
Part part[Maxparts];