From 32eb3adf284e2993c993384c9dc457d6715f1d98 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 17 Jun 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-06-17 --- mpc/random.c | 4 +- mpc/trap.c | 1 + pc/pci.c | 5 +- pc/sdata.c | 2 +- pc/sdscsi.c | 19 +- port/devloopback.c | 582 +++++++++++++++++++++++++++++++++++++++++++++ port/devsd.c | 106 ++++----- port/devsdp.c | 1 - port/sd.h | 8 +- 9 files changed, 657 insertions(+), 71 deletions(-) create mode 100644 port/devloopback.c diff --git a/mpc/random.c b/mpc/random.c index cf9eb1d054608a5a63c47eb48ed459b739b8a6d3..4954367f8ad4a996b0d9ee49e775103f92beb9b8 100644 --- a/mpc/random.c +++ b/mpc/random.c @@ -81,7 +81,7 @@ randomclock(void) wakeup(&rb.consumer); } -static void +void randominit(void) { addclock0link(randomclock); @@ -93,7 +93,7 @@ randominit(void) /* * consume random bytes from a circular buffer */ -static ulong +ulong randomread(void *xp, ulong n) { uchar *e, *p; diff --git a/mpc/trap.c b/mpc/trap.c index 464b73280327bac0527dd017da5a92a56c5bba55..4ba11ef77b5e43e00cc04ee3f48641cba77995ec 100644 --- a/mpc/trap.c +++ b/mpc/trap.c @@ -656,6 +656,7 @@ syscall(Ureg* ureg) } if(up->nerrlab){ print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab); + print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr); for(i = 0; i < NERR; i++) print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc); panic("error stack"); diff --git a/pc/pci.c b/pc/pci.c index 5571df81ee36c392189dfd87f0ff2b8b4b6c31b3..f4073271cf22500a862db65e2dc3fcced02211cb 100644 --- a/pc/pci.c +++ b/pc/pci.c @@ -61,6 +61,7 @@ enum static Lock pcicfglock; static Lock pcicfginitlock; static int pcicfgmode = -1; +static int pcimaxbno = 255; static int pcimaxdno; static Pcidev* pciroot; static Pcidev* pcilist; @@ -534,11 +535,13 @@ pcicfginit(void) fmtinstall('T', tbdfconv); + if(p = getconf("*pcimaxbno")) + pcimaxbno = strtoul(p, 0, 0); if(p = getconf("*pcimaxdno")) pcimaxdno = strtoul(p, 0, 0); list = &pciroot; - for(bno = 0; bno < 256; bno++) { + for(bno = 0; bno <= pcimaxbno; bno++) { bno = pciscan(bno, list); while(*list) list = &(*list)->link; diff --git a/pc/sdata.c b/pc/sdata.c index 04df00a4d3faf936897529fb7e4c8c8d7857e26b..4a1533557613cc35842c9e0b7f4ebf0937f8313f 100644 --- a/pc/sdata.c +++ b/pc/sdata.c @@ -1758,7 +1758,7 @@ atarctl(SDunit* unit, char* p, int l) n += snprint(p+n, l-n, " rwm %ud rwmctl %ud", drive->rwm, drive->rwmctl); n += snprint(p+n, l-n, "\n"); - if(!unit->changed && unit->sectors){ + if(unit->sectors){ n += snprint(p+n, l-n, "geometry %ld %ld", unit->sectors, unit->secsize); if(drive->pkt == 0) diff --git a/pc/sdscsi.c b/pc/sdscsi.c index 1f95bb10660257e347a7f19c4a58383295290843..1a08c5428aef938d0ab297b703d5396d923d5863 100644 --- a/pc/sdscsi.c +++ b/pc/sdscsi.c @@ -217,6 +217,14 @@ scsionline(SDunit* unit) */ unit->sectors++; unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7]; + + /* + * Some ATAPI CD readers lie about the block size. + * Since we don't read audio via this interface + * it's okay to always fudge this. + */ + if((unit->inquiry[0] & 0x1F) == 0x05 && unit->secsize == 2352) + unit->secsize = 2048; ok = 1; break; case 1: @@ -230,7 +238,10 @@ scsionline(SDunit* unit) free(p); free(r); - return ok; + if(ok) + return ok+retries; + else + return 0; } int @@ -331,15 +342,13 @@ again: case 0x06: /* check condition */ /* * Check for a removeable media change. - * If so, mark it and zap the geometry info + * If so, mark it by zapping the geometry info * to force an online request. */ if(r->sense[12] != 0x28 || r->sense[13] != 0) break; - if(unit->inquiry[1] & 0x80){ - unit->changed = 1; + if(unit->inquiry[1] & 0x80) unit->sectors = 0; - } break; case 0x02: /* not ready */ /* diff --git a/port/devloopback.c b/port/devloopback.c new file mode 100644 index 0000000000000000000000000000000000000000..48faefa636912ebb80204d80db841df0e22de41c --- /dev/null +++ b/port/devloopback.c @@ -0,0 +1,582 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#include "netif.h" + +typedef struct Link Link; +typedef struct Loop Loop; + +struct Link +{ + Lock; + + int ref; + + int nodrop; /* disable dropping on iq overflow */ + int soverflows; /* packets dropped because iq overflowed */ + int drops; /* packets deliberately dropped */ + + long delay0; /* fastticks of delay in the link */ + long delayn; /* fastticks of delay per byte */ + + Block *tq; /* transmission queue */ + Block *tqtail; + vlong tout; /* time the last packet in tq is really out */ + vlong tin; /* time the head packet in tq enters the remote side */ + + Queue *oq; /* output queue from other side & packets in the link */ + Queue *iq; +}; + +struct Loop +{ + QLock; + int ref; + int minmtu; /* smallest block transmittable */ + Loop *next; + ulong path; + long limit; /* queue buffering limit */ + Link link[2]; +}; + +static struct +{ + Lock; + ulong path; +} loopbackalloc; + +enum +{ + Qdir, + Qctl, + Qstatus, + Qstats, + Qdata0, + Qdata1, + + TMSIZE = 8, + + NLOOPBACKS = 1, + LOOPBACKSIZE = 32*1024, /*ZZZ change to settable; size of queues */ +}; + +Dirtab loopbackdir[] = +{ + "ctl", {Qctl}, 0, 0222, + "status", {Qstatus}, 0, 0222, + "stats", {Qstats}, 0, 0444, + "data", {Qdata0}, 0, 0666, + "data1", {Qdata1}, 0, 0666, +}; + +static Loop loopbacks[NLOOPBACKS]; + +static void looper(Loop *lb); +static long loopoput(Loop *lb, Link *link, Block *bp); +static void ptime(uchar *p, vlong t); +static vlong gtime(uchar *p); +static void closelink(Link *link, int dofree); +static vlong pushlink(Link *link, vlong now); +static void freelb(Loop *lb); + +static void +loopbackinit(void) +{ + int i; + + for(i = 0; i < NLOOPBACKS; i++) + loopbacks[i].path = i; +} + +static Chan* +loopbackattach(char *spec) +{ + Loop *lb; + Queue *q; + Chan *c; + int chan; + + c = devattach('X', spec); + lb = &loopbacks[0]; + + qlock(lb); + if(waserror()){ + qunlock(lb); + nexterror(); + } + + lb->ref++; + if(lb->ref == 1){ + lb->limit = LOOPBACKSIZE; + for(chan = 0; chan < 2; chan++){ + q = qopen(lb->limit, 0, 0, 0); + lb->link[chan].iq = q; + if(q == nil){ + freelb(lb); + exhausted("memory"); + } + q = qopen(lb->limit, 0, 0, 0); + lb->link[chan].oq = q; + if(q == nil){ + freelb(lb); + exhausted("memory"); + } + lb->link[chan].nodrop = 1; + } + } + poperror(); + qunlock(lb); + + c->qid = (Qid){CHDIR|NETQID(2*lb->path, Qdir), 0}; + c->aux = lb; + c->dev = 0; + return c; +} + +static Chan* +loopbackclone(Chan *c, Chan *nc) +{ + Loop *lb; + int chan; + + lb = c->aux; + nc = devclone(c, nc); + qlock(lb); + lb->ref++; + if(c->flag & COPEN){ + switch(chan = NETTYPE(c->qid.path)){ + case Qdata0: + case Qdata1: + chan -= Qdata0; + lb->link[chan].ref++; + break; + } + } + qunlock(lb); + return nc; +} + +static int +loopbackgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) +{ + Loop *lb; + int id, len, chan; + + if(i == DEVDOTDOT){ + devdir(c, c->qid, "#X", 0, eve, CHDIR|0555, dp); + return 1; + } + + id = NETID(c->qid.path); + if(i > 1) + id++; + if(tab==nil || i>=ntab) + return -1; + tab += i; + lb = c->aux; + switch(chan = tab->qid.path){ + case Qdata0: + case Qdata1: + chan -= Qdata0; + len = qlen(lb->link[chan].iq); + break; + default: + len = tab->length; + break; + } + devdir(c, (Qid){NETQID(id, tab->qid.path),0}, tab->name, len, eve, tab->perm, dp); + return 1; +} + + +static int +loopbackwalk(Chan *c, char *name) +{ + return devwalk(c, name, loopbackdir, nelem(loopbackdir), loopbackgen); +} + +static void +loopbackstat(Chan *c, char *db) +{ + Loop *lb; + Dir dir; + int chan; + + lb = c->aux; + switch(chan = NETTYPE(c->qid.path)){ + case Qdir: + devdir(c, c->qid, ".", nelem(loopbackdir)*DIRLEN, eve, CHDIR|0555, &dir); + break; + case Qdata0: + case Qdata1: + chan -= Qdata0; + devdir(c, c->qid, "data", qlen(lb->link[chan].iq), eve, 0660, &dir); + break; + default: + panic("loopbackstat"); + } + convD2M(&dir, db); +} + +/* + * if the stream doesn't exist, create it + */ +static Chan* +loopbackopen(Chan *c, int omode) +{ + Loop *lb; + int chan; + + if(c->qid.path & CHDIR){ + if(omode != OREAD) + error(Ebadarg); + c->mode = omode; + c->flag |= COPEN; + c->offset = 0; + return c; + } + + lb = c->aux; + qlock(lb); + switch(chan = NETTYPE(c->qid.path)){ + case Qdata0: + case Qdata1: + chan -= Qdata0; + lb->link[chan].ref++; + break; + } + qunlock(lb); + + c->mode = openmode(omode); + c->flag |= COPEN; + c->offset = 0; + return c; +} + +static void +loopbackclose(Chan *c) +{ + Loop *lb; + int ref, chan; + + lb = c->aux; + + qlock(lb); + if(c->flag & COPEN){ + /* + * closing either side hangs up the stream + */ + switch(chan = NETTYPE(c->qid.path)){ + case Qdata0: + case Qdata1: + chan -= Qdata0; + if(--lb->link[chan].ref == 0){ + qhangup(lb->link[chan ^ 1].oq, nil); + looper(lb); + } + break; + } + } + + + /* + * if both sides are closed, they are reusable + */ + if(lb->link[0].ref == 0 && lb->link[1].ref == 0){ + for(chan = 0; chan < 2; chan++){ + closelink(&lb->link[chan], 0); + qreopen(lb->link[chan].iq); + qreopen(lb->link[chan].oq); + } + } + ref = --lb->ref; + if(ref == 0) + freelb(lb); + qunlock(lb); +} + +static void +freelb(Loop *lb) +{ + int chan; + + for(chan = 0; chan < 2; chan++) + closelink(&lb->link[chan], 1); +} + +/* + * called with the Loop qlocked, + * so only pushlink can mess with the queues + */ +static void +closelink(Link *link, int dofree) +{ + Queue *iq, *oq; + Block *bp; + + ilock(link); + iq = link->iq; + oq = link->oq; + bp = link->tq; + link->tq = nil; + link->tqtail = nil; + link->tout = 0; + link->tin = 0; + iunlock(link); + if(iq != nil){ + qclose(iq); + if(dofree){ + ilock(link); + free(iq); + link->iq = nil; + iunlock(link); + } + } + if(oq != nil){ + qclose(oq); + if(dofree){ + ilock(link); + free(oq); + link->oq = nil; + iunlock(link); + } + } + freeblist(bp); +} + +static long +loopbackread(Chan *c, void *va, long n, vlong) +{ + Loop *lb; + int chan; + + lb = c->aux; +//ZZZ ctl message to set q limit -- qsetlimit(q, limit) +//ZZZ ctl message to set blocking/dropping qnoblock(q, dropit) +//ZZZ ctl message for delays + switch(chan = NETTYPE(c->qid.path)){ + case Qdir: + return devdirread(c, va, n, loopbackdir, nelem(loopbackdir), loopbackgen); + case Qdata0: + case Qdata1: + chan -= Qdata0; + return qread(lb->link[chan].iq, va, n); + default: + panic("loopbackread"); + } + return -1; /* not reached */ +} + +static Block* +loopbackbread(Chan *c, long n, ulong offset) +{ + Loop *lb; + int chan; + + lb = c->aux; + switch(chan = NETTYPE(c->qid.path)){ + case Qdata0: + case Qdata1: + chan -= Qdata0; + return qbread(lb->link[chan].iq, n); + } + + return devbread(c, n, offset); +} + +static long +loopbackbwrite(Chan *c, Block *bp, ulong off) +{ + Loop *lb; + int chan; + + lb = c->aux; + switch(chan = NETTYPE(c->qid.path)){ + case Qdata0: + case Qdata1: + chan -= Qdata0; + return loopoput(lb, &lb->link[chan ^ 1], bp); + default: + return devbwrite(c, bp, off); + } +} + +static long +loopbackwrite(Chan *c, void *va, long n, vlong off) +{ + Block *bp; + + if(!islo()) + print("loopbackwrite hi %lux\n", getcallerpc(&c)); + + switch(NETTYPE(c->qid.path)){ + case Qdata0: + case Qdata1: + bp = allocb(n); + if(waserror()){ + freeb(bp); + nexterror(); + } + memmove(bp->wp, va, n); + poperror(); + bp->wp += n; + return loopbackbwrite(c, bp, off); + case Qctl: + default: + panic("loopbackwrite"); + } + + return n; +} + +static long +loopoput(Loop *lb, Link *link, Block *bp) +{ + long n; + + n = BLEN(bp); + + /* make it a single block with space for the loopback header */ + bp = padblock(bp, TMSIZE); + if(bp->next) + bp = concatblock(bp); + if(BLEN(bp) < lb->minmtu) + bp = adjustblock(bp, lb->minmtu); + + qbwrite(link->oq, bp); + looper(lb); + return n; +} + +/* + * move blocks between queues if they are ready. + * schedule an interrupt for the next interesting time + */ +static void +looper(Loop *lb) +{ + vlong t, tt; + + tt = fastticks(nil); +again:; + t = pushlink(&lb->link[0], tt); + tt = pushlink(&lb->link[1], tt); + if(t > tt && tt) + t = tt; + if(t){ + tt = fastticks(nil); + if(tt <= t) + goto again; + //schedule an intr at tt-t fastticks + } +} + +static vlong +pushlink(Link *link, vlong now) +{ + Block *bp; + vlong t; + + /* + * put another block in the link queue + */ + ilock(link); + if(link->iq == nil || link->oq == nil){ + iunlock(link); + return 0; + } + t = link->tout; + if(!t || t < now){ + bp = qget(link->oq); + if(bp != nil){ + if(!t) + t = now; + link->tout = t + BLEN(bp) * link->delayn; + ptime(bp->rp, t + link->delay0); +//ZZZ drop or introduce errors here + if(link->tq == nil) + link->tq = bp; + else + link->tqtail->next = bp; + link->tqtail = bp; + }else + link->tout = 0; + } + + /* + * put more blocks into the receive queue + */ + t = 0; + while(bp = link->tq){ + t = gtime(bp->rp); + if(t > now) + break; + bp->rp += TMSIZE; + link->tq = bp->next; + bp->next = nil; + if(link->nodrop) + qpassnolim(link->iq, bp); + else if(qpass(link->iq, bp) < 0) + link->soverflows++; + t = 0; + } + if(bp == nil && qisclosed(link->oq) && !qcanread(link->oq) && !qisclosed(link->iq)) + qhangup(link->iq, nil); + link->tin = t; + if(!t || t < link->tout) + t = link->tout; + iunlock(link); + return t; +} + +static void +ptime(uchar *p, vlong t) +{ + ulong tt; + + tt = t >> 32; + p[0] = tt >> 24; + p[1] = tt >> 16; + p[2] = tt >> 8; + p[3] = tt; + tt = t; + p[4] = tt >> 24; + p[5] = tt >> 16; + p[6] = tt >> 8; + p[7] = tt; +} + +static vlong +gtime(uchar *p) +{ + ulong t1, t2; + + t1 = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + t2 = (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]; + return ((vlong)t1 << 32) | t2; +} + +Dev loopbackdevtab = { + 'X', + "loopback", + + devreset, + loopbackinit, + loopbackattach, + loopbackclone, + loopbackwalk, + loopbackstat, + loopbackopen, + devcreate, + loopbackclose, + loopbackread, + loopbackbread, + loopbackwrite, + loopbackbwrite, + devremove, + devwstat, +}; diff --git a/port/devsd.c b/port/devsd.c index baa87e1a119ba3d19f728e14bf2fca4e8eecddac..33c8cf4e58543fad042892c8fe6567d62b222b5f 100644 --- a/port/devsd.c +++ b/port/devsd.c @@ -78,7 +78,9 @@ sdaddpart(SDunit* unit, char* name, ulong start, ulong end) /* * Check there is a free slot and size and extent are valid. */ - if(partno == -1 || start > end || end > unit->sectors) + if(partno == -1) + error(Ebadctl); + if(start > end || end > unit->sectors) error(Eio); pp = &unit->part[partno]; pp->start = start; @@ -87,7 +89,6 @@ sdaddpart(SDunit* unit, char* name, ulong start, ulong end) strncpy(pp->user, eve, NAMELEN); pp->perm = 0640; pp->valid = 1; - unit->npart++; } static void @@ -99,8 +100,6 @@ sddelpart(SDunit* unit, char* name) /* * Look for the partition to delete. * Can't delete if someone still has it open. - * If it's the last valid partition zap the - * whole table. */ pp = unit->part; for(i = 0; i < SDnpart; i++){ @@ -112,29 +111,24 @@ sddelpart(SDunit* unit, char* name) error(Ebadctl); if(strncmp(up->user, pp->user, NAMELEN) && !iseve()) error(Eperm); - if(pp->nopen) - error(Einuse); pp->valid = 0; - - unit->npart--; - if(unit->npart == 0){ - free(unit->part); - unit->part = nil; - } + pp->vers++; } static int sdinitpart(SDunit* unit) { - int nf; + int i, nf; ulong start, end; char *f[4], *p, *q, buf[10]; + unit->vers++; unit->sectors = unit->secsize = 0; - unit->npart = 0; if(unit->part){ - free(unit->part); - unit->part = nil; + for(i = 0; i < SDnpart; i++){ + unit->part[i].valid = 0; + unit->part[i].vers++; + } } if(unit->inquiry[0] & 0xC0) @@ -322,22 +316,20 @@ sd2gen(Chan* c, int i, Dir* dp) SDpart *pp; SDunit *unit; + unit = sdunit[UNIT(c->qid)]; switch(i){ case Qctl: - q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qctl), c->qid.vers}; + q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qctl), unit->vers}; devdir(c, q, "ctl", 0, eve, 0640, dp); return 1; case Qraw: - q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qraw), c->qid.vers}; + q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qraw), unit->vers}; devdir(c, q, "raw", 0, eve, CHEXCL|0600, dp); return 1; case Qpart: - unit = sdunit[UNIT(c->qid)]; - if(unit->changed) - break; pp = &unit->part[PART(c->qid)]; l = (pp->end - pp->start) * (vlong)unit->secsize; - q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qpart), c->qid.vers}; + q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qpart), unit->vers+pp->vers}; if(pp->user[0] == '\0') strncpy(pp->user, eve, NAMELEN); devdir(c, q, pp->name, l, pp->user, pp->perm, dp); @@ -392,8 +384,16 @@ sdgen(Chan* c, Dirtab*, int, int s, Dir* dp) } unit = sdunit[UNIT(c->qid)]; qlock(&unit->ctl); - if(!unit->changed && unit->sectors == 0) + + /* + * Check for media change. + * If one has already been detected, sectors will be zero. + * If there is one waiting to be detected, online will return > 1. + * Online is a bit of a large hammer but does the job. + */ + if(unit->sectors == 0 || (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1)) sdinitpart(unit); + i = s+Qunitbase; if(i < Qpart){ r = sd2gen(c, i, dp); @@ -401,17 +401,17 @@ sdgen(Chan* c, Dirtab*, int, int s, Dir* dp) return r; } i -= Qpart; - if(unit->npart == 0 || i >= SDnpart){ + if(unit->part == nil || i >= SDnpart){ qunlock(&unit->ctl); break; } pp = &unit->part[i]; - if(unit->changed || !pp->valid){ + if(!pp->valid){ qunlock(&unit->ctl); return 0; } l = (pp->end - pp->start) * (vlong)unit->secsize; - q = (Qid){QID(UNIT(c->qid), i, Qpart), c->qid.vers}; + q = (Qid){QID(UNIT(c->qid), i, Qpart), unit->vers+pp->vers}; if(pp->user[0] == '\0') strncpy(pp->user, eve, NAMELEN); devdir(c, q, pp->name, l, pp->user, pp->perm, dp); @@ -493,8 +493,13 @@ sdopen(Chan* c, int omode) switch(TYPE(c->qid)){ default: break; + case Qctl: + unit = sdunit[UNIT(c->qid)]; + c->qid.vers = unit->vers; + break; case Qraw: unit = sdunit[UNIT(c->qid)]; + c->qid.vers = unit->vers; if(!canlock(&unit->rawinuse)){ c->flag &= ~COPEN; error(Einuse); @@ -509,11 +514,8 @@ sdopen(Chan* c, int omode) c->flag &= ~COPEN; nexterror(); } - if(unit->changed) - error(Eio); pp = &unit->part[PART(c->qid)]; - pp->nopen++; - unit->nopen++; + c->qid.vers = unit->vers+pp->vers; qunlock(&unit->ctl); poperror(); break; @@ -524,7 +526,6 @@ sdopen(Chan* c, int omode) static void sdclose(Chan* c) { - SDpart *pp; SDunit *unit; if(c->qid.path & CHDIR) @@ -539,28 +540,13 @@ sdclose(Chan* c) unit = sdunit[UNIT(c->qid)]; unlock(&unit->rawinuse); break; - case Qpart: - unit = sdunit[UNIT(c->qid)]; - qlock(&unit->ctl); - if(waserror()){ - qunlock(&unit->ctl); - c->flag &= ~COPEN; - nexterror(); - } - pp = &unit->part[PART(c->qid)]; - pp->nopen--; - unit->nopen--; - if(unit->nopen == 0) - unit->changed = 0; - qunlock(&unit->ctl); - poperror(); - break; } } static long sdbio(Chan* c, int write, char* a, long len, vlong off) { + int nchange; long l; uchar *b; SDpart *pp; @@ -569,12 +555,21 @@ sdbio(Chan* c, int write, char* a, long len, vlong off) unit = sdunit[UNIT(c->qid)]; + nchange = 0; qlock(&unit->ctl); - if(waserror()){ + while(waserror()){ + /* notification of media change; go around again */ + if(strcmp(up->error, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){ + sdinitpart(unit); + continue; + } + + /* other errors; give up */ qunlock(&unit->ctl); nexterror(); } - if(unit->changed) + pp = &unit->part[PART(c->qid)]; + if(unit->vers+pp->vers != c->qid.vers) error(Eio); /* @@ -588,7 +583,6 @@ sdbio(Chan* c, int write, char* a, long len, vlong off) * (sectors, secsize) can't change once the drive has * been brought online. */ - pp = &unit->part[PART(c->qid)]; bno = (off/unit->secsize) + pp->start; nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno; max = SDmaxio/unit->secsize; @@ -728,7 +722,9 @@ sdread(Chan *c, void *a, long n, vlong off) */ if(unit->dev->ifc->rctl) l += unit->dev->ifc->rctl(unit, p+l, READSTR-l); - if(!unit->changed && unit->sectors){ + if(unit->sectors == 0) + sdinitpart(unit); + if(unit->sectors){ if(unit->dev->ifc->rctl == nil) l += snprint(p+l, READSTR-l, "geometry %ld %ld\n", @@ -789,13 +785,13 @@ sdwrite(Chan *c, void *a, long n, vlong off) free(cb); nexterror(); } - if(unit->changed) + if(unit->vers != c->qid.vers) error(Eio); if(cb->nf < 1) error(Ebadctl); if(strcmp(cb->f[0], "part") == 0){ - if(cb->nf != 4 || unit->npart >= SDnpart) + if(cb->nf != 4) error(Ebadctl); if(unit->sectors == 0 && !sdinitpart(unit)) error(Eio); @@ -874,10 +870,8 @@ sdwstat(Chan* c, char* dp) nexterror(); } - if(unit->changed) - error(Enonexist); pp = &unit->part[PART(c->qid)]; - if(!pp->valid) + if(unit->vers+pp->vers != c->qid.vers) error(Enonexist); if(strncmp(up->user, pp->user, NAMELEN) && !iseve()) error(Eperm); diff --git a/port/devsdp.c b/port/devsdp.c index 76af2b26fb17d1c0ac83d9bf6545ed4700eb9b62..b70e0e96dd0eaa1b185f9f2e762185a570b014ae 100644 --- a/port/devsdp.c +++ b/port/devsdp.c @@ -528,7 +528,6 @@ sdpclose(Chan* ch) } } qunlock(c); - poperror(); break; } } diff --git a/port/sd.h b/port/sd.h index f756adcdd0fa5747d56976988709f7fcdeb3f1b0..9093a20cbfcf3d7ec945ebedfa14bd3ad6f310f1 100644 --- a/port/sd.h +++ b/port/sd.h @@ -14,7 +14,7 @@ typedef struct SDpart { char user[NAMELEN]; ulong perm; int valid; - int nopen; /* of this partition */ + ulong vers; } SDpart; typedef struct SDunit { @@ -27,10 +27,8 @@ typedef struct SDunit { QLock ctl; ulong sectors; ulong secsize; - SDpart* part; - int npart; /* of valid partitions */ - int nopen; /* of partitions on this unit */ - int changed; + SDpart* part; /* either nil or points at array of size SDnpart */ + ulong vers; Lock rawinuse; /* really just a test-and-set */ int state;