devsd: cache SDunit pointer in Chan.aux, improve error handling
Avoid calling sdgetdev() for every I/O. Instead, put the SDunit pointer for #S/sdXX/* files in Chan.aux and keep a reference to SDev between sdopen()/sdclose(). This avoids having to do the sdindex() lookup and qlock(),incref(),decref() on every read/write operation. Removal of SDev's is quite rare and only can happen with pcmcia ide controllers, and i assume that for that we can assume thet fileservers having been exited properly and closed their files before we attempt to remove a device. The rest is improving waserror() codepaths, making sure we release the locks for any of the interface callbacks (verify/online). Also get rid of tas() and instead only change the unit's rawopen flag while holding raw qlock.
This commit is contained in:
parent
12802b94c6
commit
f05b8af71e
1 changed files with 159 additions and 197 deletions
|
@ -293,19 +293,18 @@ sdgetunit(SDev* sdev, int subno)
|
||||||
qunlock(&sdev->unitlock);
|
qunlock(&sdev->unitlock);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((unit = malloc(sizeof(SDunit))) == nil){
|
|
||||||
qunlock(&sdev->unitlock);
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
sdev->unitflg[subno] = 1;
|
sdev->unitflg[subno] = 1;
|
||||||
|
|
||||||
|
unit = smalloc(sizeof(SDunit));
|
||||||
snprint(buf, sizeof buf, "%s%x", sdev->name, subno);
|
snprint(buf, sizeof buf, "%s%x", sdev->name, subno);
|
||||||
kstrdup(&unit->name, buf);
|
kstrdup(&unit->name, buf);
|
||||||
kstrdup(&unit->user, eve);
|
kstrdup(&unit->user, eve);
|
||||||
unit->perm = 0555;
|
unit->perm = 0555;
|
||||||
unit->subno = subno;
|
unit->subno = subno;
|
||||||
unit->dev = sdev;
|
unit->dev = sdev;
|
||||||
|
|
||||||
|
if(waserror())
|
||||||
|
goto Error;
|
||||||
if(sdev->enabled == 0)
|
if(sdev->enabled == 0)
|
||||||
sdev->enabled = sdev->ifc->enable == nil || sdev->ifc->enable(sdev);
|
sdev->enabled = sdev->ifc->enable == nil || sdev->ifc->enable(sdev);
|
||||||
|
|
||||||
|
@ -315,12 +314,15 @@ sdgetunit(SDev* sdev, int subno)
|
||||||
* sdunit[] array.
|
* sdunit[] array.
|
||||||
*/
|
*/
|
||||||
if(sdev->enabled == 0 || unit->dev->ifc->verify(unit) == 0){
|
if(sdev->enabled == 0 || unit->dev->ifc->verify(unit) == 0){
|
||||||
|
poperror();
|
||||||
|
Error:
|
||||||
qunlock(&sdev->unitlock);
|
qunlock(&sdev->unitlock);
|
||||||
free(unit->name);
|
free(unit->name);
|
||||||
free(unit->user);
|
free(unit->user);
|
||||||
free(unit);
|
free(unit);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
poperror();
|
||||||
sdev->unit[subno] = unit;
|
sdev->unit[subno] = unit;
|
||||||
}
|
}
|
||||||
qunlock(&sdev->unitlock);
|
qunlock(&sdev->unitlock);
|
||||||
|
@ -395,22 +397,15 @@ sdadddevs(SDev *sdev)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sd2gen(Chan* c, int i, Dir* dp)
|
sd2gen(Chan* c, SDunit *unit, int i, Dir* dp)
|
||||||
{
|
{
|
||||||
Qid q;
|
Qid q;
|
||||||
uvlong l;
|
uvlong l;
|
||||||
SDfile *e;
|
SDfile *e;
|
||||||
SDpart *pp;
|
SDpart *pp;
|
||||||
SDperm *perm;
|
SDperm *perm;
|
||||||
SDunit *unit;
|
int t;
|
||||||
SDev *sdev;
|
|
||||||
int rv, t;
|
|
||||||
|
|
||||||
sdev = sdgetdev(DEV(c->qid));
|
|
||||||
assert(sdev);
|
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
|
||||||
|
|
||||||
rv = -1;
|
|
||||||
switch(i){
|
switch(i){
|
||||||
case Qctl:
|
case Qctl:
|
||||||
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),
|
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),
|
||||||
|
@ -421,8 +416,7 @@ sd2gen(Chan* c, int i, Dir* dp)
|
||||||
perm->perm = 0640;
|
perm->perm = 0640;
|
||||||
}
|
}
|
||||||
devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);
|
devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);
|
||||||
rv = 1;
|
return 1;
|
||||||
break;
|
|
||||||
|
|
||||||
case Qraw:
|
case Qraw:
|
||||||
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),
|
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),
|
||||||
|
@ -433,8 +427,7 @@ sd2gen(Chan* c, int i, Dir* dp)
|
||||||
perm->perm = DMEXCL|0600;
|
perm->perm = DMEXCL|0600;
|
||||||
}
|
}
|
||||||
devdir(c, q, "raw", 0, perm->user, perm->perm, dp);
|
devdir(c, q, "raw", 0, perm->user, perm->perm, dp);
|
||||||
rv = 1;
|
return 1;
|
||||||
break;
|
|
||||||
|
|
||||||
case Qpart:
|
case Qpart:
|
||||||
pp = &unit->part[PART(c->qid)];
|
pp = &unit->part[PART(c->qid)];
|
||||||
|
@ -444,8 +437,8 @@ sd2gen(Chan* c, int i, Dir* dp)
|
||||||
if(emptystr(pp->user))
|
if(emptystr(pp->user))
|
||||||
kstrdup(&pp->user, eve);
|
kstrdup(&pp->user, eve);
|
||||||
devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
|
devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
|
||||||
rv = 1;
|
return 1;
|
||||||
break;
|
|
||||||
case Qextra:
|
case Qextra:
|
||||||
t = PART(c->qid);
|
t = PART(c->qid);
|
||||||
if(t >= unit->nefile)
|
if(t >= unit->nefile)
|
||||||
|
@ -456,12 +449,10 @@ sd2gen(Chan* c, int i, Dir* dp)
|
||||||
if(emptystr(e->user))
|
if(emptystr(e->user))
|
||||||
kstrdup(&e->user, eve);
|
kstrdup(&e->user, eve);
|
||||||
devdir(c, q, e->name, 0, e->user, e->perm, dp);
|
devdir(c, q, e->name, 0, e->user, e->perm, dp);
|
||||||
rv = 1;
|
return 1;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decref(&sdev->r);
|
return -1;
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -574,13 +565,14 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((sdev = sdgetdev(DEV(c->qid))) == nil){
|
if((sdev = sdgetdev(DEV(c->qid))) == nil)
|
||||||
devdir(c, c->qid, "unavailable", 0, eve, 0, dp);
|
return -1;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
unit = sdev->unit[UNIT(c->qid)];
|
||||||
qlock(&unit->ctl);
|
qlock(&unit->ctl);
|
||||||
|
if(waserror()){
|
||||||
|
r = -1;
|
||||||
|
goto ReleaseUnit;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for media change.
|
* Check for media change.
|
||||||
|
@ -595,23 +587,22 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp)
|
||||||
|
|
||||||
i = s+Qunitbase;
|
i = s+Qunitbase;
|
||||||
if(i < Qpart){
|
if(i < Qpart){
|
||||||
r = sd2gen(c, i, dp);
|
r = sd2gen(c, unit, i, dp);
|
||||||
qunlock(&unit->ctl);
|
poperror();
|
||||||
decref(&sdev->r);
|
goto ReleaseUnit;
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
i -= Qpart;
|
i -= Qpart;
|
||||||
if(unit->part == nil || i >= unit->npart){
|
if(unit->part == nil || i >= unit->npart){
|
||||||
r = efilegen(c, unit, i, dp);
|
r = efilegen(c, unit, i, dp);
|
||||||
qunlock(&unit->ctl);
|
poperror();
|
||||||
decref(&sdev->r);
|
goto ReleaseUnit;
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
poperror();
|
||||||
|
|
||||||
pp = &unit->part[i];
|
pp = &unit->part[i];
|
||||||
if(!pp->valid || unit->sectors == 0){
|
if(!pp->valid || unit->sectors == 0){
|
||||||
qunlock(&unit->ctl);
|
r = 0;
|
||||||
decref(&sdev->r);
|
goto ReleaseUnit;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
l = (pp->end - pp->start) * (uvlong)unit->secsize;
|
l = (pp->end - pp->start) * (uvlong)unit->secsize;
|
||||||
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),
|
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),
|
||||||
|
@ -619,20 +610,23 @@ sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp)
|
||||||
if(emptystr(pp->user))
|
if(emptystr(pp->user))
|
||||||
kstrdup(&pp->user, eve);
|
kstrdup(&pp->user, eve);
|
||||||
devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
|
devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
|
||||||
qunlock(&unit->ctl);
|
r = 1;
|
||||||
decref(&sdev->r);
|
goto ReleaseUnit;
|
||||||
return 1;
|
|
||||||
case Qraw:
|
case Qraw:
|
||||||
case Qctl:
|
case Qctl:
|
||||||
case Qpart:
|
case Qpart:
|
||||||
case Qextra:
|
case Qextra:
|
||||||
if((sdev = sdgetdev(DEV(c->qid))) == nil){
|
if((sdev = sdgetdev(DEV(c->qid))) == nil)
|
||||||
devdir(c, q, "unavailable", 0, eve, 0, dp);
|
return -1;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
unit = sdev->unit[UNIT(c->qid)];
|
||||||
qlock(&unit->ctl);
|
qlock(&unit->ctl);
|
||||||
r = sd2gen(c, TYPE(c->qid), dp);
|
if(!waserror()){
|
||||||
|
r = sd2gen(c, unit, TYPE(c->qid), dp);
|
||||||
|
poperror();
|
||||||
|
} else {
|
||||||
|
r = -1;
|
||||||
|
}
|
||||||
|
ReleaseUnit:
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
decref(&sdev->r);
|
decref(&sdev->r);
|
||||||
return r;
|
return r;
|
||||||
|
@ -668,15 +662,17 @@ sdattach(char* spec)
|
||||||
|
|
||||||
if((sdev=sdgetdev(idno)) == nil)
|
if((sdev=sdgetdev(idno)) == nil)
|
||||||
error(Enonexist);
|
error(Enonexist);
|
||||||
if(sdgetunit(sdev, subno) == nil){
|
if(waserror()){
|
||||||
decref(&sdev->r);
|
decref(&sdev->r);
|
||||||
error(Enonexist);
|
nexterror();
|
||||||
}
|
}
|
||||||
|
if(sdgetunit(sdev, subno) == nil)
|
||||||
|
error(Enonexist);
|
||||||
c = devattach(sddevtab.dc, spec);
|
c = devattach(sddevtab.dc, spec);
|
||||||
mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR);
|
mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR);
|
||||||
c->dev = (sdev->idno << UnitLOG) + subno;
|
c->dev = (sdev->idno << UnitLOG) + subno;
|
||||||
decref(&sdev->r);
|
decref(&sdev->r);
|
||||||
|
poperror();
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,46 +694,48 @@ sdopen(Chan* c, int omode)
|
||||||
SDpart *pp;
|
SDpart *pp;
|
||||||
SDunit *unit;
|
SDunit *unit;
|
||||||
SDev *sdev;
|
SDev *sdev;
|
||||||
uchar tp;
|
|
||||||
|
|
||||||
c = devopen(c, omode, 0, 0, sdgen);
|
c = devopen(c, omode, 0, 0, sdgen);
|
||||||
if((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart)
|
if(TYPE(c->qid) < Qunitbase)
|
||||||
return c;
|
return c;
|
||||||
|
if(waserror()){
|
||||||
|
c->flag &= ~COPEN;
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
sdev = sdgetdev(DEV(c->qid));
|
sdev = sdgetdev(DEV(c->qid));
|
||||||
if(sdev == nil)
|
if(sdev == nil)
|
||||||
error(Enonexist);
|
error(Enonexist);
|
||||||
|
if(waserror()){
|
||||||
|
decref(&sdev->r);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
unit = sdev->unit[UNIT(c->qid)];
|
||||||
|
|
||||||
switch(TYPE(c->qid)){
|
switch(TYPE(c->qid)){
|
||||||
case Qctl:
|
case Qctl:
|
||||||
|
case Qextra:
|
||||||
c->qid.vers = unit->vers;
|
c->qid.vers = unit->vers;
|
||||||
break;
|
break;
|
||||||
case Qraw:
|
case Qraw:
|
||||||
c->qid.vers = unit->vers;
|
qlock(&unit->raw);
|
||||||
if(tas(&unit->rawinuse) != 0){
|
if(unit->rawinuse){
|
||||||
c->flag &= ~COPEN;
|
qunlock(&unit->raw);
|
||||||
decref(&sdev->r);
|
|
||||||
error(Einuse);
|
error(Einuse);
|
||||||
}
|
}
|
||||||
unit->state = Rawcmd;
|
unit->state = Rawcmd;
|
||||||
|
c->qid.vers = unit->vers;
|
||||||
|
qunlock(&unit->raw);
|
||||||
break;
|
break;
|
||||||
case Qpart:
|
case Qpart:
|
||||||
qlock(&unit->ctl);
|
qlock(&unit->ctl);
|
||||||
if(waserror()){
|
|
||||||
qunlock(&unit->ctl);
|
|
||||||
c->flag &= ~COPEN;
|
|
||||||
decref(&sdev->r);
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
pp = &unit->part[PART(c->qid)];
|
pp = &unit->part[PART(c->qid)];
|
||||||
c->qid.vers = unit->vers+pp->vers;
|
c->qid.vers = unit->vers+pp->vers;
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
poperror();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
decref(&sdev->r);
|
poperror();
|
||||||
|
poperror();
|
||||||
|
/* keep the reference to unit->dev (sdev) */
|
||||||
|
c->aux = unit;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,25 +743,20 @@ static void
|
||||||
sdclose(Chan* c)
|
sdclose(Chan* c)
|
||||||
{
|
{
|
||||||
SDunit *unit;
|
SDunit *unit;
|
||||||
SDev *sdev;
|
|
||||||
|
|
||||||
if(c->qid.type & QTDIR)
|
|
||||||
return;
|
|
||||||
if(!(c->flag & COPEN))
|
if(!(c->flag & COPEN))
|
||||||
return;
|
return;
|
||||||
|
if(TYPE(c->qid) < Qunitbase)
|
||||||
|
return;
|
||||||
|
unit = c->aux;
|
||||||
switch(TYPE(c->qid)){
|
switch(TYPE(c->qid)){
|
||||||
default:
|
|
||||||
break;
|
|
||||||
case Qraw:
|
case Qraw:
|
||||||
sdev = sdgetdev(DEV(c->qid));
|
qlock(&unit->raw);
|
||||||
if(sdev){
|
unit->rawinuse = 0;
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
qunlock(&unit->raw);
|
||||||
unit->rawinuse = 0;
|
|
||||||
decref(&sdev->r);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
decref(&unit->dev->r);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define iskaddr(a) ((uintptr)(a) > KZERO)
|
#define iskaddr(a) ((uintptr)(a) > KZERO)
|
||||||
|
@ -776,21 +769,12 @@ sdbio(Chan* c, int write, char* a, long len, uvlong off)
|
||||||
uchar *b;
|
uchar *b;
|
||||||
SDpart *pp;
|
SDpart *pp;
|
||||||
SDunit *unit;
|
SDunit *unit;
|
||||||
SDev *sdev;
|
|
||||||
ulong max, nb, offset;
|
ulong max, nb, offset;
|
||||||
uvlong bno;
|
uvlong bno;
|
||||||
|
|
||||||
sdev = sdgetdev(DEV(c->qid));
|
unit = c->aux;
|
||||||
if(sdev == nil){
|
|
||||||
decref(&sdev->r);
|
|
||||||
error(Enonexist);
|
|
||||||
}
|
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
|
||||||
if(unit == nil)
|
|
||||||
error(Enonexist);
|
|
||||||
|
|
||||||
nchange = 0;
|
|
||||||
qlock(&unit->ctl);
|
qlock(&unit->ctl);
|
||||||
|
nchange = 0;
|
||||||
while(waserror()){
|
while(waserror()){
|
||||||
/* notification of media change; go around again */
|
/* notification of media change; go around again */
|
||||||
if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
|
if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
|
||||||
|
@ -800,7 +784,6 @@ sdbio(Chan* c, int write, char* a, long len, uvlong off)
|
||||||
|
|
||||||
/* other errors; give up */
|
/* other errors; give up */
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
decref(&sdev->r);
|
|
||||||
nexterror();
|
nexterror();
|
||||||
}
|
}
|
||||||
pp = &unit->part[PART(c->qid)];
|
pp = &unit->part[PART(c->qid)];
|
||||||
|
@ -829,7 +812,6 @@ sdbio(Chan* c, int write, char* a, long len, uvlong off)
|
||||||
if(write)
|
if(write)
|
||||||
error(Eio);
|
error(Eio);
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
decref(&sdev->r);
|
|
||||||
poperror();
|
poperror();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -848,21 +830,14 @@ sdbio(Chan* c, int write, char* a, long len, uvlong off)
|
||||||
b = (uchar*)a;
|
b = (uchar*)a;
|
||||||
allocd = 0;
|
allocd = 0;
|
||||||
}else{
|
}else{
|
||||||
while((b = sdmalloc(nb*unit->secsize)) == nil){
|
while((b = sdmalloc(nb*unit->secsize)) == nil)
|
||||||
if(!waserror()){
|
resrcwait("no memory for sdbio");
|
||||||
resrcwait("no memory for sdbio");
|
if(waserror()){
|
||||||
poperror();
|
sdfree(b);
|
||||||
}
|
nexterror();
|
||||||
}
|
}
|
||||||
allocd = 1;
|
allocd = 1;
|
||||||
}
|
}
|
||||||
if(waserror()){
|
|
||||||
if(allocd)
|
|
||||||
sdfree(b);
|
|
||||||
if(!locked)
|
|
||||||
decref(&sdev->r); /* gadverdamme! */
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(write){
|
if(write){
|
||||||
if(hard){
|
if(hard){
|
||||||
|
@ -897,16 +872,16 @@ sdbio(Chan* c, int write, char* a, long len, uvlong off)
|
||||||
if(allocd)
|
if(allocd)
|
||||||
memmove(a, b+offset, len);
|
memmove(a, b+offset, len);
|
||||||
}
|
}
|
||||||
if(allocd)
|
|
||||||
sdfree(b);
|
|
||||||
poperror();
|
|
||||||
|
|
||||||
|
if(allocd){
|
||||||
|
sdfree(b);
|
||||||
|
poperror();
|
||||||
|
}
|
||||||
if(locked){
|
if(locked){
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
poperror();
|
poperror();
|
||||||
}
|
}
|
||||||
|
|
||||||
decref(&sdev->r);
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -933,19 +908,17 @@ sdrio(SDreq* r, void* a, long n)
|
||||||
}
|
}
|
||||||
|
|
||||||
data = nil;
|
data = nil;
|
||||||
while(n > 0 && (data = sdmalloc(n)) == nil){
|
if(n > 0){
|
||||||
if(!waserror()){
|
while((data = sdmalloc(n)) == nil)
|
||||||
resrcwait("no memory for sdrio");
|
resrcwait("no memory for sdrio");
|
||||||
poperror();
|
if(waserror()){
|
||||||
|
r->data = nil;
|
||||||
|
sdfree(data);
|
||||||
|
nexterror();
|
||||||
}
|
}
|
||||||
|
if(r->write)
|
||||||
|
memmove(data, a, n);
|
||||||
}
|
}
|
||||||
if(waserror()){
|
|
||||||
sdfree(data);
|
|
||||||
r->data = nil;
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
if(r->write && n > 0)
|
|
||||||
memmove(data, a, n);
|
|
||||||
r->data = data;
|
r->data = data;
|
||||||
r->dlen = n;
|
r->dlen = n;
|
||||||
|
|
||||||
|
@ -966,13 +939,16 @@ sdrio(SDreq* r, void* a, long n)
|
||||||
if(rv != SDok)
|
if(rv != SDok)
|
||||||
error(Eio);
|
error(Eio);
|
||||||
|
|
||||||
if(!r->write && r->rlen > 0)
|
|
||||||
memmove(a, data, r->rlen);
|
|
||||||
poperror();
|
|
||||||
sdfree(data);
|
|
||||||
r->data = nil;
|
r->data = nil;
|
||||||
|
if(n > 0){
|
||||||
return r->rlen;
|
if(n < r->rlen)
|
||||||
|
n = r->rlen;
|
||||||
|
if(!r->write && n > 0)
|
||||||
|
memmove(a, data, n);
|
||||||
|
sdfree(data);
|
||||||
|
poperror();
|
||||||
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1187,36 +1163,21 @@ sdfakescsirw(SDreq *r, uvlong *llba, int *nsec, int *rwp)
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
extrarw(int write, Chan *c, void *a, long n, vlong off)
|
extrarw(Chan *c, int write, void *a, long n, vlong off)
|
||||||
{
|
{
|
||||||
int i;
|
SDunit *unit = c->aux;
|
||||||
SDrw *f;
|
SDrw *f;
|
||||||
SDev *sdev;
|
int i;
|
||||||
SDunit *unit;
|
|
||||||
|
|
||||||
sdev = sdgetdev(DEV(c->qid));
|
|
||||||
if(sdev == nil)
|
|
||||||
error(Enonexist);
|
|
||||||
if(waserror()){
|
|
||||||
decref(&sdev->r);
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
|
||||||
if(unit->vers != c->qid.vers)
|
if(unit->vers != c->qid.vers)
|
||||||
error(Echange);
|
error(Echange);
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
|
||||||
i = PART(c->qid);
|
i = PART(c->qid);
|
||||||
if(i >= unit->nefile)
|
if(i >= unit->nefile)
|
||||||
error(Enonexist);
|
error(Enonexist);
|
||||||
f = unit->efile[i].r;
|
f = write ? unit->efile[i].w : unit->efile[i].r;
|
||||||
if(write)
|
if(f == nil)
|
||||||
f = unit->efile[i].w;
|
|
||||||
if(i >= unit->nefile || f == nil)
|
|
||||||
error(Eperm);
|
error(Eperm);
|
||||||
n = f(unit, c, a, n, off);
|
return f(unit, c, a, n, off);
|
||||||
poperror();
|
|
||||||
decref(&sdev->r);
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
|
@ -1244,17 +1205,29 @@ sdread(Chan *c, void *a, long n, vlong off)
|
||||||
m = 64*1024; /* room for register dumps */
|
m = 64*1024; /* room for register dumps */
|
||||||
p = buf = smalloc(m);
|
p = buf = smalloc(m);
|
||||||
e = p + m;
|
e = p + m;
|
||||||
|
if(waserror()){
|
||||||
|
free(buf);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
qlock(&devslock);
|
qlock(&devslock);
|
||||||
|
if(waserror()){
|
||||||
|
qunlock(&devslock);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
for(i = 0; i < nelem(devs); i++){
|
for(i = 0; i < nelem(devs); i++){
|
||||||
sdev = devs[i];
|
sdev = devs[i];
|
||||||
if(sdev && sdev->ifc->rtopctl)
|
if(sdev == nil)
|
||||||
|
continue;
|
||||||
|
if(sdev->ifc->rtopctl)
|
||||||
p = sdev->ifc->rtopctl(sdev, p, e);
|
p = sdev->ifc->rtopctl(sdev, p, e);
|
||||||
else if(sdev)
|
else
|
||||||
p = deftopctl(sdev, p, e);
|
p = deftopctl(sdev, p, e);
|
||||||
}
|
}
|
||||||
qunlock(&devslock);
|
qunlock(&devslock);
|
||||||
|
poperror();
|
||||||
n = readstr(off, a, n, buf);
|
n = readstr(off, a, n, buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
poperror();
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
case Qtopdir:
|
case Qtopdir:
|
||||||
|
@ -1262,55 +1235,53 @@ sdread(Chan *c, void *a, long n, vlong off)
|
||||||
return devdirread(c, a, n, 0, 0, sdgen);
|
return devdirread(c, a, n, 0, 0, sdgen);
|
||||||
|
|
||||||
case Qctl:
|
case Qctl:
|
||||||
sdev = sdgetdev(DEV(c->qid));
|
|
||||||
if(sdev == nil)
|
|
||||||
error(Enonexist);
|
|
||||||
|
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
|
||||||
m = 16*1024; /* room for register dumps */
|
m = 16*1024; /* room for register dumps */
|
||||||
p = smalloc(m);
|
p = buf = smalloc(m);
|
||||||
l = snprint(p, m, "inquiry %.48s\n",
|
e = p + m;
|
||||||
(char*)unit->inquiry+8);
|
if(waserror()){
|
||||||
|
free(buf);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
|
unit = c->aux;
|
||||||
qlock(&unit->ctl);
|
qlock(&unit->ctl);
|
||||||
|
if(waserror()){
|
||||||
|
qunlock(&unit->ctl);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
|
p = seprint(p, e, "inquiry %.48s\n", (char*)unit->inquiry+8);
|
||||||
/*
|
/*
|
||||||
* If there's a device specific routine it must
|
* If there's a device specific routine it must
|
||||||
* provide all information pertaining to night geometry
|
* provide all information pertaining to night geometry
|
||||||
* and the garscadden trains.
|
* and the garscadden trains.
|
||||||
*/
|
*/
|
||||||
if(unit->dev->ifc->rctl)
|
if(unit->dev->ifc->rctl)
|
||||||
l += unit->dev->ifc->rctl(unit, p+l, m-l);
|
p += unit->dev->ifc->rctl(unit, p, e - p);
|
||||||
if(unit->sectors == 0)
|
if(unit->sectors == 0)
|
||||||
sdinitpart(unit);
|
sdinitpart(unit);
|
||||||
if(unit->sectors){
|
if(unit->sectors){
|
||||||
if(unit->dev->ifc->rctl == nil)
|
if(unit->dev->ifc->rctl == nil)
|
||||||
l += snprint(p+l, m-l,
|
p = seprint(p, e, "geometry %llud %lud\n",
|
||||||
"geometry %llud %lud\n",
|
|
||||||
unit->sectors, unit->secsize);
|
unit->sectors, unit->secsize);
|
||||||
pp = unit->part;
|
pp = unit->part;
|
||||||
for(i = 0; i < unit->npart; i++){
|
for(i = 0; i < unit->npart; i++){
|
||||||
if(pp->valid)
|
if(pp->valid)
|
||||||
l += snprint(p+l, m-l,
|
p = seprint(p, e, "part %s %llud %llud\n",
|
||||||
"part %s %llud %llud\n",
|
|
||||||
pp->name, pp->start, pp->end);
|
pp->name, pp->start, pp->end);
|
||||||
pp++;
|
pp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
decref(&sdev->r);
|
poperror();
|
||||||
l = readstr(offset, a, n, p);
|
l = readstr(offset, a, n, buf);
|
||||||
free(p);
|
free(buf);
|
||||||
|
poperror();
|
||||||
return l;
|
return l;
|
||||||
|
|
||||||
case Qraw:
|
case Qraw:
|
||||||
sdev = sdgetdev(DEV(c->qid));
|
unit = c->aux;
|
||||||
if(sdev == nil)
|
|
||||||
error(Enonexist);
|
|
||||||
|
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
|
||||||
qlock(&unit->raw);
|
qlock(&unit->raw);
|
||||||
if(waserror()){
|
if(waserror()){
|
||||||
qunlock(&unit->raw);
|
qunlock(&unit->raw);
|
||||||
decref(&sdev->r);
|
|
||||||
nexterror();
|
nexterror();
|
||||||
}
|
}
|
||||||
if(unit->state == Rawdata){
|
if(unit->state == Rawdata){
|
||||||
|
@ -1337,15 +1308,14 @@ sdread(Chan *c, void *a, long n, vlong off)
|
||||||
free(r);
|
free(r);
|
||||||
} else
|
} else
|
||||||
i = 0;
|
i = 0;
|
||||||
poperror();
|
|
||||||
qunlock(&unit->raw);
|
qunlock(&unit->raw);
|
||||||
decref(&sdev->r);
|
poperror();
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
case Qpart:
|
case Qpart:
|
||||||
return sdbio(c, 0, a, n, off);
|
return sdbio(c, 0, a, n, off);
|
||||||
case Qextra:
|
case Qextra:
|
||||||
return extrarw(0, c, a, n, off);
|
return extrarw(c, 0, a, n, off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1413,7 +1383,7 @@ sdwrite(Chan* c, void* a, long n, vlong off)
|
||||||
|
|
||||||
subtopctl:
|
subtopctl:
|
||||||
if(waserror()){
|
if(waserror()){
|
||||||
if(sdev)
|
if(sdev != nil)
|
||||||
decref(&sdev->r);
|
decref(&sdev->r);
|
||||||
nexterror();
|
nexterror();
|
||||||
}
|
}
|
||||||
|
@ -1421,24 +1391,19 @@ sdwrite(Chan* c, void* a, long n, vlong off)
|
||||||
ifc->wtopctl(sdev, cb);
|
ifc->wtopctl(sdev, cb);
|
||||||
else
|
else
|
||||||
error(Ebadctl);
|
error(Ebadctl);
|
||||||
poperror();
|
if(sdev != nil)
|
||||||
poperror();
|
|
||||||
if(sdev)
|
|
||||||
decref(&sdev->r);
|
decref(&sdev->r);
|
||||||
|
poperror();
|
||||||
|
poperror();
|
||||||
free(cb);
|
free(cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qctl:
|
case Qctl:
|
||||||
cb = parsecmd(a, n);
|
cb = parsecmd(a, n);
|
||||||
sdev = sdgetdev(DEV(c->qid));
|
unit = c->aux;
|
||||||
if(sdev == nil)
|
|
||||||
error(Enonexist);
|
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
|
||||||
|
|
||||||
qlock(&unit->ctl);
|
qlock(&unit->ctl);
|
||||||
if(waserror()){
|
if(waserror()){
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
decref(&sdev->r);
|
|
||||||
free(cb);
|
free(cb);
|
||||||
nexterror();
|
nexterror();
|
||||||
}
|
}
|
||||||
|
@ -1466,7 +1431,6 @@ sdwrite(Chan* c, void* a, long n, vlong off)
|
||||||
else
|
else
|
||||||
error(Ebadctl);
|
error(Ebadctl);
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
decref(&sdev->r);
|
|
||||||
poperror();
|
poperror();
|
||||||
free(cb);
|
free(cb);
|
||||||
break;
|
break;
|
||||||
|
@ -1475,14 +1439,10 @@ sdwrite(Chan* c, void* a, long n, vlong off)
|
||||||
proto = SDcdb;
|
proto = SDcdb;
|
||||||
ataproto = 0;
|
ataproto = 0;
|
||||||
atacdb = 0;
|
atacdb = 0;
|
||||||
sdev = sdgetdev(DEV(c->qid));
|
unit = c->aux;
|
||||||
if(sdev == nil)
|
|
||||||
error(Enonexist);
|
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
|
||||||
qlock(&unit->raw);
|
qlock(&unit->raw);
|
||||||
if(waserror()){
|
if(waserror()){
|
||||||
qunlock(&unit->raw);
|
qunlock(&unit->raw);
|
||||||
decref(&sdev->r);
|
|
||||||
nexterror();
|
nexterror();
|
||||||
}
|
}
|
||||||
switch(unit->state){
|
switch(unit->state){
|
||||||
|
@ -1528,14 +1488,13 @@ sdwrite(Chan* c, void* a, long n, vlong off)
|
||||||
req->write = 1;
|
req->write = 1;
|
||||||
n = sdrio(req, a, n);
|
n = sdrio(req, a, n);
|
||||||
}
|
}
|
||||||
poperror();
|
|
||||||
qunlock(&unit->raw);
|
qunlock(&unit->raw);
|
||||||
decref(&sdev->r);
|
poperror();
|
||||||
break;
|
break;
|
||||||
case Qpart:
|
case Qpart:
|
||||||
return sdbio(c, 1, a, n, off);
|
return sdbio(c, 1, a, n, off);
|
||||||
case Qextra:
|
case Qextra:
|
||||||
return extrarw(1, c, a, n, off);
|
return extrarw(c, 1, a, n, off);
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
|
@ -1562,13 +1521,10 @@ sdwstat(Chan* c, uchar* dp, int n)
|
||||||
unit = sdev->unit[UNIT(c->qid)];
|
unit = sdev->unit[UNIT(c->qid)];
|
||||||
}
|
}
|
||||||
qlock(&unit->ctl);
|
qlock(&unit->ctl);
|
||||||
|
|
||||||
d = nil;
|
|
||||||
if(waserror()){
|
if(waserror()){
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
if(sdev != nil)
|
if(sdev != nil)
|
||||||
decref(&sdev->r);
|
decref(&sdev->r);
|
||||||
free(d);
|
|
||||||
nexterror();
|
nexterror();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1594,6 +1550,10 @@ sdwstat(Chan* c, uchar* dp, int n)
|
||||||
error(Eperm);
|
error(Eperm);
|
||||||
|
|
||||||
d = smalloc(sizeof(Dir)+n);
|
d = smalloc(sizeof(Dir)+n);
|
||||||
|
if(waserror()){
|
||||||
|
free(d);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
n = convM2D(dp, n, &d[0], (char*)&d[1]);
|
n = convM2D(dp, n, &d[0], (char*)&d[1]);
|
||||||
if(n == 0)
|
if(n == 0)
|
||||||
error(Eshortstat);
|
error(Eshortstat);
|
||||||
|
@ -1607,11 +1567,12 @@ sdwstat(Chan* c, uchar* dp, int n)
|
||||||
error(Eperm);
|
error(Eperm);
|
||||||
if(d[0].mode != ~0UL)
|
if(d[0].mode != ~0UL)
|
||||||
perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
|
perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
|
||||||
poperror();
|
|
||||||
qunlock(&unit->ctl);
|
qunlock(&unit->ctl);
|
||||||
if(sdev != nil)
|
if(sdev != nil)
|
||||||
decref(&sdev->r);
|
decref(&sdev->r);
|
||||||
free(d);
|
free(d);
|
||||||
|
poperror();
|
||||||
|
poperror();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1682,6 +1643,7 @@ unconfigure(char* spec)
|
||||||
|
|
||||||
if(sdev->ifc->clear)
|
if(sdev->ifc->clear)
|
||||||
sdev->ifc->clear(sdev);
|
sdev->ifc->clear(sdev);
|
||||||
|
|
||||||
free(sdev);
|
free(sdev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1717,7 +1679,7 @@ sdaddfile(SDunit *unit, char *s, int perm, char *u, SDrw *r, SDrw *w)
|
||||||
if(e->name == nil)
|
if(e->name == nil)
|
||||||
kstrdup(&e->name, s);
|
kstrdup(&e->name, s);
|
||||||
if(e->user == nil)
|
if(e->user == nil)
|
||||||
kstrdup(&e->user, u);
|
kstrdup(&e->user, u);
|
||||||
e->perm = perm;
|
e->perm = perm;
|
||||||
e->r = r;
|
e->r = r;
|
||||||
e->w = w;
|
e->w = w;
|
||||||
|
|
Loading…
Reference in a new issue