summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-12-26 17:53:12 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2012-12-26 17:53:12 +0100
commit4a4c8218eed10132c7e37a603575ee7d2a7e6a9f (patch)
treeb05adf77cfa165e736f9efcdd0f8afd868c3aae7
parent7ceff03db37d98e1dc634198fcee4206d8318499 (diff)
downloadplan9front-4a4c8218eed10132c7e37a603575ee7d2a7e6a9f.tar.xz
devsd: fix possible sdbio() race with inquiry data changing (due to ahci hotplug)
the unit inquiry data might change in case the drive got pulled with ahci. so keep track if we locked the ctl in a local stack variable instead of relying on that the inquiry data stays the same.
-rw-r--r--sys/src/9/port/devsd.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/sys/src/9/port/devsd.c b/sys/src/9/port/devsd.c
index b4cbd71f5..0d2a32319 100644
--- a/sys/src/9/port/devsd.c
+++ b/sys/src/9/port/devsd.c
@@ -770,7 +770,7 @@ sdclose(Chan* c)
static long
sdbio(Chan* c, int write, char* a, long len, uvlong off)
{
- int nchange, hard, allocd;
+ int nchange, hard, allocd, locked;
long l;
uchar *b;
SDpart *pp;
@@ -832,7 +832,8 @@ sdbio(Chan* c, int write, char* a, long len, uvlong off)
poperror();
return 0;
}
- if(!(unit->inquiry[1] & 0x80)){
+ locked = (unit->inquiry[1] & 0x80) != 0;
+ if(!locked){
qunlock(&unit->ctl);
poperror();
}
@@ -854,7 +855,7 @@ sdbio(Chan* c, int write, char* a, long len, uvlong off)
if(waserror()){
if(allocd)
sdfree(b);
- if(!(unit->inquiry[1] & 0x80))
+ if(!locked)
decref(&sdev->r); /* gadverdamme! */
nexterror();
}
@@ -896,7 +897,7 @@ sdbio(Chan* c, int write, char* a, long len, uvlong off)
sdfree(b);
poperror();
- if(unit->inquiry[1] & 0x80){
+ if(locked){
qunlock(&unit->ctl);
poperror();
}