@@ 10,7 10,6 @@ typedef struct Drive Drive;
typedef struct Ident Ident;
typedef struct Controller Controller;
typedef struct Partition Partition;
-typedef struct Ptable Ptable;
enum
{
@@ 45,7 44,7 @@ enum
Qmask= (3<<(3+3)),
Maxxfer= 4*1024, /* maximum transfer size/cmd */
- Npart= 8+1, /* 8 sub partitions and one for the disk */
+ Npart= 8+2, /* 8 sub partitions, disk, and partiiton */
};
#define PART(x) ((x)&0x3)
#define DRIVE(x) (((x)>>3)&0x7)
@@ 93,19 92,7 @@ struct Partition
{
ulong start;
ulong end;
- uchar name[NAMELEN];
-};
-
-struct Ptable
-{
- uchar magic[4]; /* ascii "disk" */
- uchar n[4]; /* number of partitions */
- struct
- {
- uchar start[4]; /* starting block */
- uchar end[4]; /* ending block */
- uchar name[NAMELEN];
- } p[1];
+ char name[NAMELEN+1];
};
/*
@@ 159,11 146,9 @@ struct Controller
Controller *hardc;
Drive *hard;
-Dirtab *harddir;
-#define NHDIR 2 /* directory entries/drive */
static void hardintr(Ureg*);
-static long hardxfer(Drive*, int, void*, long, long);
+static long hardxfer(Drive*, Partition*, int, void*, long, long);
static long hardident(Drive*);
static void hardsetbuf(Drive*, int);
static void hardpart(Drive*);
@@ 173,33 158,30 @@ hardgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
{
Qid qid;
int drive;
- char *name;
+ char name[NAMELEN];
Drive *dp;
Partition *pp;
ulong l;
qid.vers = 0;
- drive = s/(Npart+1);
- s = s % (Npart+1);
+ drive = s/Npart;
+ s = s % Npart;
if(drive >= conf.nhard)
return -1;
dp = &hard[drive];
- if(s == 0){
- sprint(name, "hd%dparition", drive);
- qid.path = MKQID(Qpart, drive, 0);
- l = dp->npart * sizeof(Partition);
- } else if(s-1 < p.npart){
- pp = &dp->p[s-1];
+ if(s < dp->npart){
+ pp = &dp->p[s];
sprint(name, "hd%d%s", drive, pp->name);
- qid.path = MKQID(Qdata, drive, s-1);
- l = (pp->end - pp->start) * dp->cp->bytes;
+ qid.path = MKQID(Qdata, drive, s);
+ l = (pp->end - pp->start) * dp->bytes;
} else
return 0;
devdir(c, qid, name, l, 0600, dirp);
return 1;
}
+
/*
* we assume drives 0 and 1 are on the first controller, 2 and 3 on the
* second, etc.
@@ 210,11 192,9 @@ hardreset(void)
Drive *dp;
Controller *cp;
int drive;
- Dirtab *dir;
hard = ialloc(conf.nhard * sizeof(Drive), 0);
hardc = ialloc(((conf.nhard+1)/2 + 1) * sizeof(Controller), 0);
- dir = harddir = ialloc(NHDIR * conf.nhard * sizeof(Dirtab), 0);
for(drive = 0; drive < conf.nhard; drive++){
dp = &hard[drive];
@@ 228,16 208,6 @@ hardreset(void)
cp->pbase = Pbase + (cp-hardc)*8; /* BUG!! guessing */
setvec(Hardvec + (cp-hardc)*8, hardintr); /* BUG!! guessing */
}
- sprint(harddir[drive*2].name, "hd%ddata", drive);
- dir->length = 0;
- dir->qid.path = Qdata + drive;
- dir->perm = 0600;
- dir++;
- sprint(dir->name, "hd%dstruct", drive);
- dir->length = 8;
- dir->qid.path = Qstruct + drive;
- dir->perm = 0600;
- dir++;
}
}
@@ 260,14 230,13 @@ hardattach(char *spec)
dp->bytes = 512;
hardsetbuf(dp, 1);
hardident(dp);
- hardpart(dp);
dp->cyl = dp->id.lcyls;
dp->heads = dp->id.lheads;
dp->sectors = dp->id.ls2t;
dp->bytes = 512;
dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
- harddir[NHDIR*dp->drive].length = dp->cap;
dp->online = 1;
+ hardpart(dp);
poperror();
} else
dp->online = 0;
@@ 285,19 254,19 @@ hardclone(Chan *c, Chan *nc)
int
hardwalk(Chan *c, char *name)
{
- return devwalk(c, name, harddir, conf.nhard*NHDIR, devgen);
+ return devwalk(c, name, 0, 0, hardgen);
}
void
hardstat(Chan *c, char *dp)
{
- devstat(c, dp, harddir, conf.nhard*NHDIR, devgen);
+ devstat(c, dp, 0, 0, hardgen);
}
Chan*
hardopen(Chan *c, int omode)
{
- return devopen(c, omode, harddir, conf.nhard*NHDIR, devgen);
+ return devopen(c, omode, 0, 0, hardgen);
}
void
@@ 323,43 292,29 @@ hardwstat(Chan *c, char *dp)
error(Eperm);
}
-static void
-ul2user(uchar *a, ulong x)
-{
- a[0] = x >> 24;
- a[1] = x >> 16;
- a[2] = x >> 8;
- a[3] = x;
-}
-
long
hardread(Chan *c, void *a, long n)
{
Drive *dp;
long rv, i;
uchar *aa = a;
+ Partition *pp;
if(c->qid.path == CHDIR)
- return devdirread(c, a, n, harddir, conf.nhard*NHDIR, devgen);
+ return devdirread(c, a, n, 0, 0, hardgen);
rv = 0;
dp = &hard[c->qid.path & ~Qmask];
switch ((int)(c->qid.path & Qmask)) {
case Qdata:
for(rv = 0; rv < n; rv += i){
- i = hardxfer(dp, Cread, aa+rv, c->offset+rv, n-rv);
+ pp = &dp->p[PART(c->qid.path)];
+ i = hardxfer(dp, pp, Cread, aa+rv, c->offset+rv, n-rv);
if(i <= 0)
break;
}
break;
- case Qstruct:
- if (n < 2*sizeof(ulong))
- error(Ebadarg);
- if (c->offset >= 2*sizeof(ulong))
- return 0;
- rv = 2*sizeof(ulong);
- ul2user((uchar*)a, dp->cap);
- ul2user((uchar*)a+sizeof(ulong), dp->bytes);
+ case Qpart:
break;
default:
panic("hardread: bad qid");
@@ 373,19 328,20 @@ hardwrite(Chan *c, void *a, long n)
Drive *dp;
long rv, i;
uchar *aa = a;
+ Partition *pp;
rv = 0;
dp = &hard[c->qid.path & ~Qmask];
switch ((int)(c->qid.path & Qmask)) {
case Qdata:
for(rv = 0; rv < n; rv += i){
- i = hardxfer(dp, Cwrite, aa+rv, c->offset+rv, n-rv);
+ pp = &dp->p[PART(c->qid.path)];
+ i = hardxfer(dp, pp, Cwrite, aa+rv, c->offset+rv, n-rv);
if(i <= 0)
break;
}
break;
- case Qstruct:
- error(Eperm);
+ case Qpart:
break;
default:
panic("hardwrite: bad qid");
@@ 425,7 381,7 @@ print("cmdreadywait failed\n");
* parts.
*/
static long
-hardxfer(Drive *dp, int cmd, void *va, long off, long len)
+hardxfer(Drive *dp, Partition *pp, int cmd, void *va, long off, long len)
{
Controller *cp;
int err;
@@ 439,6 395,9 @@ hardxfer(Drive *dp, int cmd, void *va, long off, long len)
if(off % dp->bytes)
errors("bad offset"); /* BUG - this shouldn't be a problem */
+print("hardxfer %ld %ld\n", off, len);
+print("hardxfer part %s %ld %ld\n", pp->name, pp->start, pp->end);
+
cp = dp->cp;
qlock(cp);
if(waserror()){
@@ 450,6 409,9 @@ hardxfer(Drive *dp, int cmd, void *va, long off, long len)
* calculate the physical address of off
*/
lsec = off/dp->bytes;
+ lsec += pp->start;
+ if(lsec >= pp->end)
+ errors("xfer past end of partition\n");
cp->tcyl = lsec/(dp->sectors*dp->heads);
cp->tsec = (lsec % dp->sectors) + 1;
cp->thead = (lsec/dp->sectors) % dp->heads;
@@ 458,6 420,9 @@ hardxfer(Drive *dp, int cmd, void *va, long off, long len)
* can't xfer across cylinder boundaries.
*/
lsec = (off+len)/dp->bytes;
+ lsec += pp->start;
+ if(lsec > pp->end)
+ errors("xfer past end of partition\n");
cyl = lsec/(dp->sectors*dp->heads);
if(cyl == cp->tcyl)
cp->len = len;
@@ 515,6 480,7 @@ hardsetbuf(Drive *dp, int on)
cmdreadywait(cp);
+ cp->cmd = Csetbuf;
outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55);
outb(cp->pbase+Pdh, (dp->drive<<4));
outb(cp->pbase+Pcmd, Csetbuf);
@@ 536,6 502,7 @@ hardident(Drive *dp)
cp = dp->cp;
qlock(cp);
if(waserror()){
+print("waserror in hardident\n");
qunlock(cp);
nexterror();
}
@@ 566,24 533,64 @@ print("bad disk magic\n");
}
/*
- * read partition table
+ * read partition table. The partition table is just ascii strings.
*/
+#define MAGIC "plan9 partitions"
static void
hardpart(Drive *dp)
{
Partition *pp;
- Ptable *pt;
- uchar buf[1024];
+ char *line[Npart+1];
+ char *field[3];
+ char buf[1024];
+ ulong n;
+ int i;
pp = &dp->p[0];
strcpy(pp->name, "disk");
pp->start = 0;
- pp->end = pp->cap / dp->bytes;
+ pp->end = dp->cap / dp->bytes;
+ pp++;
+ strcpy(pp->name, "partition");
+ pp->start = dp->p[0].end - 1;
+ pp->end = dp->p[0].end;
+ dp->npart = 2;
- qlock(dp->cp);
- hardxfer(dp, Cread, buf, pp->end - 1, dp->bytes);
-
- qunlock(dp->cp);
+ if(waserror()){
+ print("error in hardpart\n");
+ nexterror();
+ }
+
+ hardxfer(dp, pp, Cread, buf, (pp->end - 1)*dp->bytes, dp->bytes);
+ buf[dp->bytes] = 0;
+
+ n = getfields(buf, line, Npart+1, '\n');
+ if(strncmp(line[0], MAGIC, sizeof(MAGIC)-1) != 0){
+ print("bad partition table 1\n");
+ goto out;
+ }
+ for(i = 1; i < n; i++){
+ pp++;
+ if(getfields(line[i], field, 3, 0) != 3){
+ print("bad partition field\n");
+ goto out;
+ }
+ if(strlen(field[0]) > NAMELEN){
+ print("bad partition name\n");
+ goto out;
+ }
+ strcpy(pp->name, field[0]);
+ pp->start = strtoul(field[1], 0, 0);
+ pp->end = strtoul(field[2], 0, 0);
+ if(pp->start > pp->end || pp->start >= dp->p[0].end){
+ print("bad partition limit\n");
+ goto out;
+ }
+print("partition %s from %d to %d\n", pp->name, pp->start, pp->end);
+ dp->npart++;
+ }
+out:
+ poperror();
}
/*
@@ 642,8 649,12 @@ hardintr(Ureg *ur)
wakeup(&cp->r);
}
break;
+ case Csetbuf:
+ cp->cmd = 0;
+ wakeup(&cp->r);
+ break;
default:
- print("wierd disk interrupt\n");
+ print("weird disk interrupt\n");
break;
}
}
@@ 9,7 9,7 @@
#include "fcall.h"
-#define NTAG 16384 /* 1 <= tag <= NTAG */
+#define NTAG 65536 /* 1 <= tag < NTAG */
typedef struct Mnt Mnt;
typedef struct Mnthdr Mnthdr;
@@ 52,8 52,9 @@ struct Mnthdr
{
Mnthdr *next; /* in free list or writers list */
Mnthdr *prev; /* in writers list only */
- short active;
- short flushing; /* a Tflush has been sent */
+ char active;
+ char flushing; /* a Tflush has been sent */
+ short seq;
Fcall thdr;
Fcall rhdr;
Rendez r;
@@ 66,7 67,8 @@ struct
{
Lock;
Mnthdr *arena;
- Mnthdr *free;
+ Mnthdr *head;
+ Mnthdr *tail;
}mnthdralloc;
struct
@@ 85,7 87,6 @@ struct
Mnt *mnt;
void mntxmit(Mnt*, Mnthdr*);
-Ref mnttag;
Mntbuf*
mballoc(void)
@@ 119,17 120,27 @@ mbfree(Mntbuf *mb)
}
Mnthdr*
-mhalloc(void)
+mhalloc(Mnt *m)
{
Mnthdr *mh;
+ int seq;
loop:
lock(&mnthdralloc);
- if(mh = mnthdralloc.free){ /* assign = */
- mnthdralloc.free = mh->next;
- mh->mbr = 0;
- mh->thdr.tag = 1 + (incref(&mnttag) & (NTAG-1));
+ if(mh = mnthdralloc.head){ /* assign = */
+ mnthdralloc.head = mh->next;
+ if(mnthdralloc.head)
+ mnthdralloc.head->prev = 0;
+ else
+ mnthdralloc.tail = 0;
unlock(&mnthdralloc);
+ mh->mbr = 0;
+ seq = ++mh->seq;
+ if(seq == (1<<7)){
+ mh->seq = 1;
+ seq = 1;
+ }
+ mh->thdr.tag = (((mh-mnthdralloc.arena)<<7)|seq) & (NTAG-1);
return mh;
}
unlock(&mnthdralloc);
@@ 150,8 161,13 @@ mhfree(Mnthdr *mh)
lock(&mnthdralloc);
mh->active = 0;
mh->thdr.tag = 0;
- mh->next = mnthdralloc.free;
- mnthdralloc.free = mh;
+ mh->next = 0;
+ mh->prev = mnthdralloc.tail;
+ if(mnthdralloc.tail)
+ mnthdralloc.tail->next = mh;
+ else
+ mnthdralloc.head = mh;
+ mnthdralloc.tail = mh;
unlock(&mnthdralloc);
}
@@ 217,27 233,39 @@ mntreset(void)
Mnthdr *mh;
MntQ *mq;
+ if(conf.nmnthdr > 512){
+ print("conf.nmnthdr is %d set to 512\n", conf.nmnthdr);
+ conf.nmnthdr = 512;
+ }
mnt = ialloc(conf.nmntdev*sizeof(Mnt), 0);
mb = ialloc(conf.nmntbuf*sizeof(Mntbuf), 0);
- for(i=0; i<conf.nmntbuf-1; i++)
- mb[i].next = &mb[i+1];
- mb[i].next = 0;
mntbufalloc.free = mb;
+ for(i=0; i<conf.nmntbuf; i++,mb++)
+ mb->next = mb+1;
+ --mb;
+ mb->next = 0;
mh = ialloc(conf.nmnthdr*sizeof(Mnthdr), 0);
- for(i=0; i<conf.nmnthdr-1; i++)
- mh[i].next = &mh[i+1];
- mh[i].next = 0;
mnthdralloc.arena = mh;
- mnthdralloc.free = mh;
+ mnthdralloc.head = mh;
+ for(i=0; i<conf.nmnthdr; i++,mh++){
+ mh->seq = 0;
+ mh->next = mh+1;
+ mh->prev = mh-1;
+ }
+ --mh;
+ mnthdralloc.tail = mh;
+ mh->next = 0;
+ mnthdralloc.head->prev = 0;
mq = ialloc(conf.nmntdev*sizeof(MntQ), 0);
- for(i=0; i<conf.nmntdev-1; i++)
- mq[i].next = &mq[i+1];
- mq[i].next = 0;
mntqalloc.arena = mq;
mntqalloc.free = mq;
+ for(i=0; i<conf.nmntdev; i++,mq++)
+ mq->next = mq+1;
+ --mq;
+ mq->next = 0;
}
void
@@ 302,7 330,7 @@ mntattach(char *crud)
out:
qunlock(&mntqalloc);
- mh = mhalloc();
+ mh = mhalloc(m);
if(waserror()){
mhfree(mh);
close(c);
@@ 339,7 367,7 @@ mntclone(Chan *c, Chan *nc)
}
}
m = mntdev(c, 0);
- mh = mhalloc();
+ mh = mhalloc(m);
if(waserror()){
mhfree(mh);
nexterror();
@@ 377,7 405,7 @@ mntwalk(Chan *c, char *name)
found = 1;
m = mntdev(c, 0);
- mh = mhalloc();
+ mh = mhalloc(m);
mh->thdr.type = Twalk;
mh->thdr.fid = c->fid;
strcpy(mh->thdr.name, name);
@@ 400,7 428,7 @@ mntstat(Chan *c, char *dp)
Mnthdr *mh;
m = mntdev(c, 0);
- mh = mhalloc();
+ mh = mhalloc(m);
if(waserror()){
mhfree(mh);
nexterror();
@@ 424,7 452,7 @@ mntopen(Chan *c, int omode)
Mnthdr *mh;
m = mntdev(c, 0);
- mh = mhalloc();
+ mh = mhalloc(m);
if(waserror()){
mhfree(mh);
nexterror();
@@ 449,7 477,7 @@ mntcreate(Chan *c, char *name, int omode, ulong perm)
Mnthdr *mh;
m = mntdev(c, 0);
- mh = mhalloc();
+ mh = mhalloc(m);
if(waserror()){
mhfree(mh);
nexterror();
@@ 477,7 505,7 @@ mntclunk(Chan *c, int t)
int waserr;
m = mntdev(c, 0);
- mh = mhalloc();
+ mh = mhalloc(m);
mh->thdr.type = t;
mh->thdr.fid = c->fid;
waserr = 0;
@@ 519,7 547,7 @@ mntreadwrite(Chan *c, void *vbuf, long n, int type, ulong offset)
buf = vbuf;
count = 0;
m = mntdev(c, 0);
- mh = mhalloc();
+ mh = mhalloc(m);
if(waserror()){
mhfree(mh);
nexterror();
@@ 585,7 613,7 @@ mntwstat(Chan *c, char *dp)
Mnthdr *mh;
m = mntdev(c, 0);
- mh = mhalloc();
+ mh = mhalloc(m);
if(waserror()){
mhfree(mh);
nexterror();
@@ 626,7 654,7 @@ mntflush(Mnt *m, Mnthdr *omh) /* queue is unlocked */
return;
}
- mh = mhalloc();
+ mh = mhalloc(m);
if(waserror()){
omh->flushing = 0;
mhfree(mh);
@@ 814,7 842,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
if(tag == mh->thdr.tag){ /* it's mine */
if(mh->rhdr.type != Rerror)
if(mh->rhdr.type != mh->thdr.type+1){
- print("mail rob: '%s T(%d)%c %d %d'\n", u->p->text,
+ print("mail rob: '%s xxT(%d)%c %d %d'\n", u->p->text,
tag, devchar[m->q->msg->type],
mh->rhdr.type, mh->thdr.type+1);
goto FreeRead;
@@ 835,7 863,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
/*
* Hand response to correct recipient
*/
- if(tag<=0 || tag>NTAG){
+ if(tag==0 || tag>=NTAG){
print("unknown tag %d\n", tag);
FreeRead:
mbfree(mh->mbr);
@@ 854,7 882,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
goto FreeRead;
if(mh->rhdr.type != Rerror)
if(mh->rhdr.type != w->thdr.type+1){
- print("mail rob: '%s w(%d)%c %d %d'\n",
+ print("mail rob: '%s xxw(%d)%c %d %d'\n",
u->p->text, tag, devchar[m->q->msg->type],
mh->rhdr.type, w->thdr.type+1);
goto FreeRead;