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:
cinap_lenrek 2022-03-30 19:23:26 +00:00
parent 12802b94c6
commit f05b8af71e

View file

@ -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;