M gnot/dat.h => gnot/dat.h +4 -1
@@ 101,7 101,10 @@ struct Chan
Mount *mnt; /* mount point that derived Chan */
ulong mountid;
int fid; /* for devmnt */
- Stream *stream; /* for stream channels */
+ union{
+ Stream *stream; /* for stream channels */
+ void *aux;
+ };
Chan *mchan; /* channel to mounted server */
ulong mqid; /* qid of root of mount point */
};
M gnot/devsrv.c => gnot/devsrv.c +169 -81
@@ 4,27 4,26 @@
#include "dat.h"
#include "fns.h"
#include "errno.h"
-
#include "devtab.h"
+#include "fcall.h"
-typedef struct Srv Srv;
-struct Srv{
- Lock;
- char *name;
- Chan **chan;
-}srv;
-
-int
-srvgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp)
-{
+void *calloc(unsigned int, unsigned int);
+void free(void *);
- if(s >= conf.nsrv)
- return -1;
- if(srv.chan[s] == 0)
- return 0;
- devdir(c, s, &srv.name[s*NAMELEN], 0, 0666, dp);
- return 1;
-}
+/* This structure holds the contents of a directory entry. Entries are kept
+ * in a linked list.
+ */
+struct entry {
+ Lock;
+ struct entry *next; /* next entry */
+ struct entry **back; /* entry pointer */
+ struct entry *parent; /* parent directory */
+ Dir dir; /* dir structure */
+ union {
+ Chan *chan; /* if not a subdirectory */
+ struct entry *entries; /* directory entries */
+ };
+};
void
srvinit(void)
@@ 34,119 33,169 @@ srvinit(void)
void
srvreset(void)
{
- srv.chan = ialloc(conf.nsrv*sizeof(Chan*), 0);
- srv.name = ialloc(conf.nsrv*NAMELEN, 0);
+}
+
+struct entry *srv_alloc(int mode){
+ struct entry *e = calloc(1, sizeof(*e));
+ static Lock qidlock;
+ static nextqid;
+
+ e->dir.atime = e->dir.mtime = seconds();
+ lock(&qidlock); /* for qid allocation */
+ e->dir.qid = mode | nextqid++;
+ unlock(&qidlock);
+ return e;
}
Chan *
srvattach(char *spec)
{
- return devattach('s', spec);
+ Chan *c;
+ static Lock rootlock;
+ static struct entry *root;
+
+ lock(&rootlock);
+ if (root == 0) {
+ root = srv_alloc(CHDIR);
+ root->dir.mode = CHDIR | 0777;
+ }
+ unlock(&rootlock);
+ c = devattach('s', spec);
+ c->qid = root->dir.qid;
+ c->aux = root;
+ return c;
}
Chan *
srvclone(Chan *c, Chan *nc)
{
- return devclone(c, nc);
+ nc = devclone(c, nc);
+ nc->aux = c->aux;
+ return nc;
}
int
srvwalk(Chan *c, char *name)
{
- return devwalk(c, name, (Dirtab *)0, 0, srvgen);
+ struct entry *dir, *e;
+
+ isdir(c);
+ if (strcmp(name, ".") == 0)
+ return 1;
+ if ((dir = c->aux) == 0)
+ panic("bad aux pointer in srvwalk");
+ if (strcmp(name, "..") == 0)
+ e = dir->parent;
+ else {
+ lock(dir);
+ for (e = dir->entries; e != 0; e = e->next)
+ if (strcmp(name, e->dir.name) == 0)
+ break;
+ unlock(dir);
+ }
+ if (e == 0) {
+ u->error.code = Enonexist;
+ u->error.type = 0;
+ u->error.dev = 0;
+ return 0;
+ }
+ c->qid = e->dir.qid;
+ c->aux = e;
+ return 1;
}
void
srvstat(Chan *c, char *db)
{
- devstat(c, db, (Dirtab *)0, 0L, srvgen);
+ struct entry *e = c->aux;
+
+ convD2M(&e->dir, db);
}
Chan *
srvopen(Chan *c, int omode)
{
+ struct entry *e;
Chan *f;
- if(c->qid == CHDIR){
- if(omode != OREAD)
+ if (c->qid & CHDIR) {
+ if (omode != OREAD)
error(0, Eisdir);
c->mode = omode;
c->flag |= COPEN;
c->offset = 0;
return c;
}
- lock(&srv);
- if(waserror()){
- unlock(&srv);
- nexterror();
- }
- f = srv.chan[c->qid];
- if(f == 0)
+ if ((e = c->aux) == 0)
+ panic("bad aux pointer in srvopen");
+ if ((f = e->chan) == 0)
error(0, Eshutdown);
- if(omode&OTRUNC)
+ if (omode & OTRUNC)
error(0, Eperm);
- if(omode!=f->mode && f->mode!=ORDWR)
+ if (omode != f->mode && f->mode != ORDWR)
error(0, Eperm);
close(c);
incref(f);
- unlock(&srv);
- poperror();
return f;
}
void
srvcreate(Chan *c, char *name, int omode, ulong perm)
{
- int j, i;
+ struct entry *parent = c->aux, *e;
- if(omode != OWRITE)
- error(0, Eperm);
- lock(&srv);
- if(waserror()){
- unlock(&srv);
+ isdir(c);
+ lock(parent);
+ if (waserror()) {
+ unlock(parent);
nexterror();
}
- j = -1;
- for(i=0; i<conf.nsrv; i++){
- if(srv.chan[i] == 0){
- if(j == -1)
- j = i;
- }else if(strcmp(name, &srv.name[i*NAMELEN]) == 0){
- print("reuse of srv name\n");
+ for (e = parent->entries; e != 0; e = e->next)
+ if (strcmp(name, e->dir.name) == 0)
error(0, Einuse);
- }
- }
- if(j == -1)
- error(0, Enosrv);
- srv.chan[j] = c;
- unlock(&srv);
- strcpy(&srv.name[j*NAMELEN], name);
- c->qid = j;
+ e = srv_alloc(perm & CHDIR);
+ e->parent = parent;
+ strcpy(e->dir.name, name);
+ e->dir.mode = perm & parent->dir.mode;
+ e->dir.gid = parent->dir.gid;
+ if ((e->next = parent->entries) != 0)
+ e->next->back = &e->next;
+ *(e->back = &parent->entries) = e;
+ parent->dir.mtime = e->dir.mtime;
+ unlock(parent);
+ poperror();
+ c->qid = e->dir.gid;
+ c->aux = e;
c->flag |= COPEN;
- c->mode = OWRITE;
+ c->mode = omode;
}
void
srvremove(Chan *c)
{
- Chan *f;
+ struct entry *e = c->aux;
- if(c->qid == CHDIR)
+ if (e->parent == 0)
error(0, Eperm);
- lock(&srv);
- if(waserror()){
- unlock(&srv);
+ lock(e->parent);
+ if (waserror()) {
+ unlock(e->parent);
nexterror();
}
- f = srv.chan[c->qid];
- if(f == 0)
- error(0, Eshutdown);
- if(strcmp(&srv.name[c->qid*NAMELEN], "boot") == 0)
- error(0, Eperm);
- srv.chan[c->qid] = 0;
- unlock(&srv);
+ if (e->dir.mode & CHDIR) {
+ if (e->entries != 0)
+ error(0, Eperm);
+ }
+ else {
+ if (e->chan == 0)
+ error(0, Eshutdown);
+ close(e->chan);
+ }
+ if ((*e->back = e->next) != 0)
+ e->next->back = e->back;
+ unlock(e->parent);
poperror();
- close(f);
+ free(e);
}
void
@@ 160,33 209,72 @@ srvclose(Chan *c)
{
}
+/* A directory is being read. The entries must be synthesized. e points
+ * to a list of entries in this directory. Count is the size to be
+ * read.
+ */
+int srv_direntry(struct entry *e, char *a, long count){
+ Dir dir;
+ int n = 0;
+
+ while (n != count && e != 0) {
+ n += convD2M(&e->dir, a + n);
+ e = e->next;
+ }
+ return n;
+}
+
long
srvread(Chan *c, void *va, long n)
{
- char *a = va;
+ struct entry *dir = c->aux, *e;
+ int offset = c->offset;
- if(c->qid != CHDIR)
- panic("srvread");
- return devdirread(c, a, n, (Dirtab *)0, 0L, srvgen);
+ isdir(c);
+ if (n <= 0)
+ return 0;
+ if ((offset % DIRLEN) != 0 || (n % DIRLEN) != 0)
+ error(0, Egreg);
+ lock(dir);
+ for (e = dir->entries; e != 0; e = e->next)
+ if (offset <= 0) {
+ n = srv_direntry(e, va, n);
+ unlock(dir);
+ c->offset += n;
+ return n;
+ }
+ else
+ offset -= DIRLEN;
+ unlock(dir);
+ return 0;
}
long
srvwrite(Chan *c, void *va, long n)
{
+ struct entry *e = c->aux;
int i, fd;
char buf[32];
- i = c->qid;
- if(srv.chan[i] != c) /* already been written to */
+ if (e->dir.mode & CHDIR)
+ panic("write to directory");
+ lock(e);
+ if (waserror()) {
+ unlock(e);
+ nexterror();
+ }
+ if (e->chan != 0)
error(0, Egreg);
- if(n >= sizeof buf)
+ if (n >= sizeof buf)
error(0, Egreg);
memcpy(buf, va, n); /* so we can NUL-terminate */
buf[n] = 0;
fd = strtoul(buf, 0, 0);
fdtochan(fd, -1); /* error check only */
- srv.chan[i] = u->fd[fd];
- incref(u->fd[fd]);
+ e->chan = u->fd[fd];
+ incref(e->chan);
+ unlock(e);
+ poperror();
return n;
}
M gnot/sturp.c => gnot/sturp.c +14 -7
@@ 465,6 465,7 @@ urpiput(Queue *q, Block *bp)
case ACK+4: case ACK+5: case ACK+6: case ACK+7:
case ECHO+0: case ECHO+1: case ECHO+2: case ECHO+3:
case ECHO+4: case ECHO+5: case ECHO+6: case ECHO+7:
+ DPRINT("rACK %ux\n", ctl);
rcvack(up, ctl);
break;
@@ 695,15 696,18 @@ static void
sendctl(Urp *up, int ctl)
{
Block *bp;
+ Queue *q;
- if(QFULL(up->wq->next))
+ q = up->wq;
+ if(QFULL(q->next))
return;
bp = allocb(1);
bp->wptr = bp->lim;
bp->rptr = bp->lim-1;
*bp->rptr = ctl;
bp->flags |= S_DELIM;
- PUTNEXT(up->wq, bp);
+ PUTNEXT(q, bp);
+ DPRINT("sCTL %ulx\n", ctl);
}
/*
@@ 762,9 766,11 @@ sendblock(Urp *up, int bn)
{
Block *bp, *m, *nbp;
int n;
+ Queue *q;
+ q = up->wq;
up->timer = NOW + MSrexmit;
- if(QFULL(up->wq->next))
+ if(QFULL(q->next))
return;
/*
@@ 781,7 787,7 @@ sendblock(Urp *up, int bn)
nbp->rptr = bp->rptr;
nbp->wptr = bp->wptr;
nbp->flags |= S_DELIM;
- PUTNEXT(up->wq, m);
+ PUTNEXT(q, m);
/*
* message 2, the block length and the SEQ
@@ 794,7 800,8 @@ sendblock(Urp *up, int bn)
m->rptr[1] = n;
m->rptr[2] = n<<8;
m->flags |= S_DELIM;
- PUTNEXT(up->wq, m);
+ PUTNEXT(q, m);
+ DPRINT("sb %d\n", bn);
}
/*
@@ 945,8 952,8 @@ todo(void *arg)
return (up->state&INITING)
? NOW>up->timer /* time to INIT1 */
: ((up->unechoed!=up->next && NOW>up->timer) /* time to ENQ */
- || WINDOW(up)>0 && up->next!=up->nxb
- || (!QFULL(up->rq->next) && up->iseq!=(up->lastecho&7))); /* time to ECHO */
+ || (WINDOW(up)>0 && (up->next!=up->nxb || up->wq->first)) /* open xmit window */
+ || (up->iseq!=(up->lastecho&7) && !QFULL(up->rq->next))); /* time to ECHO */
}
static void
urpkproc(void *arg)
M port/devmnt.c => port/devmnt.c +4 -1
@@ 747,8 747,11 @@ mntxmit(Mnt *m, Mnthdr *mh)
/*
* Copy out on read
*/
- if(mh->thdr.type == Tread)
+ if(mh->thdr.type == Tread){
+ if(mh->rhdr.count>497 && mh->rhdr.data[497]==011)
+ print("*497==11 %lux\n", &mh->rhdr.data[497]);
memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count);
+ }
mbfree(mh->mbr);
mbfree(mbw);
poperror();
M port/devsrv.c => port/devsrv.c +169 -81
@@ 4,27 4,26 @@
#include "dat.h"
#include "fns.h"
#include "errno.h"
-
#include "devtab.h"
+#include "fcall.h"
-typedef struct Srv Srv;
-struct Srv{
- Lock;
- char *name;
- Chan **chan;
-}srv;
-
-int
-srvgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp)
-{
+void *calloc(unsigned int, unsigned int);
+void free(void *);
- if(s >= conf.nsrv)
- return -1;
- if(srv.chan[s] == 0)
- return 0;
- devdir(c, s, &srv.name[s*NAMELEN], 0, 0666, dp);
- return 1;
-}
+/* This structure holds the contents of a directory entry. Entries are kept
+ * in a linked list.
+ */
+struct entry {
+ Lock;
+ struct entry *next; /* next entry */
+ struct entry **back; /* entry pointer */
+ struct entry *parent; /* parent directory */
+ Dir dir; /* dir structure */
+ union {
+ Chan *chan; /* if not a subdirectory */
+ struct entry *entries; /* directory entries */
+ };
+};
void
srvinit(void)
@@ 34,119 33,169 @@ srvinit(void)
void
srvreset(void)
{
- srv.chan = ialloc(conf.nsrv*sizeof(Chan*), 0);
- srv.name = ialloc(conf.nsrv*NAMELEN, 0);
+}
+
+struct entry *srv_alloc(int mode){
+ struct entry *e = calloc(1, sizeof(*e));
+ static Lock qidlock;
+ static nextqid;
+
+ e->dir.atime = e->dir.mtime = seconds();
+ lock(&qidlock); /* for qid allocation */
+ e->dir.qid = mode | nextqid++;
+ unlock(&qidlock);
+ return e;
}
Chan *
srvattach(char *spec)
{
- return devattach('s', spec);
+ Chan *c;
+ static Lock rootlock;
+ static struct entry *root;
+
+ lock(&rootlock);
+ if (root == 0) {
+ root = srv_alloc(CHDIR);
+ root->dir.mode = CHDIR | 0777;
+ }
+ unlock(&rootlock);
+ c = devattach('s', spec);
+ c->qid = root->dir.qid;
+ c->aux = root;
+ return c;
}
Chan *
srvclone(Chan *c, Chan *nc)
{
- return devclone(c, nc);
+ nc = devclone(c, nc);
+ nc->aux = c->aux;
+ return nc;
}
int
srvwalk(Chan *c, char *name)
{
- return devwalk(c, name, (Dirtab *)0, 0, srvgen);
+ struct entry *dir, *e;
+
+ isdir(c);
+ if (strcmp(name, ".") == 0)
+ return 1;
+ if ((dir = c->aux) == 0)
+ panic("bad aux pointer in srvwalk");
+ if (strcmp(name, "..") == 0)
+ e = dir->parent;
+ else {
+ lock(dir);
+ for (e = dir->entries; e != 0; e = e->next)
+ if (strcmp(name, e->dir.name) == 0)
+ break;
+ unlock(dir);
+ }
+ if (e == 0) {
+ u->error.code = Enonexist;
+ u->error.type = 0;
+ u->error.dev = 0;
+ return 0;
+ }
+ c->qid = e->dir.qid;
+ c->aux = e;
+ return 1;
}
void
srvstat(Chan *c, char *db)
{
- devstat(c, db, (Dirtab *)0, 0L, srvgen);
+ struct entry *e = c->aux;
+
+ convD2M(&e->dir, db);
}
Chan *
srvopen(Chan *c, int omode)
{
+ struct entry *e;
Chan *f;
- if(c->qid == CHDIR){
- if(omode != OREAD)
+ if (c->qid & CHDIR) {
+ if (omode != OREAD)
error(0, Eisdir);
c->mode = omode;
c->flag |= COPEN;
c->offset = 0;
return c;
}
- lock(&srv);
- if(waserror()){
- unlock(&srv);
- nexterror();
- }
- f = srv.chan[c->qid];
- if(f == 0)
+ if ((e = c->aux) == 0)
+ panic("bad aux pointer in srvopen");
+ if ((f = e->chan) == 0)
error(0, Eshutdown);
- if(omode & OTRUNC)
+ if (omode & OTRUNC)
error(0, Eperm);
- if(omode!=f->mode && f->mode!=ORDWR)
+ if (omode != f->mode && f->mode != ORDWR)
error(0, Eperm);
close(c);
incref(f);
- unlock(&srv);
- poperror();
return f;
}
void
srvcreate(Chan *c, char *name, int omode, ulong perm)
{
- int j, i;
+ struct entry *parent = c->aux, *e;
- if(omode != OWRITE)
- error(0, Eperm);
- lock(&srv);
- if(waserror()){
- unlock(&srv);
+ isdir(c);
+ lock(parent);
+ if (waserror()) {
+ unlock(parent);
nexterror();
}
- j = -1;
- for(i=0; i<conf.nsrv; i++){
- if(srv.chan[i] == 0){
- if(j == -1)
- j = i;
- }else if(strcmp(name, &srv.name[i*NAMELEN]) == 0){
- print("reuse of srv name\n");
+ for (e = parent->entries; e != 0; e = e->next)
+ if (strcmp(name, e->dir.name) == 0)
error(0, Einuse);
- }
- }
- if(j == -1)
- error(0, Enosrv);
- srv.chan[j] = c;
- unlock(&srv);
- strcpy(&srv.name[j*NAMELEN], name);
- c->qid = j;
+ e = srv_alloc(perm & CHDIR);
+ e->parent = parent;
+ strcpy(e->dir.name, name);
+ e->dir.mode = perm & parent->dir.mode;
+ e->dir.gid = parent->dir.gid;
+ if ((e->next = parent->entries) != 0)
+ e->next->back = &e->next;
+ *(e->back = &parent->entries) = e;
+ parent->dir.mtime = e->dir.mtime;
+ unlock(parent);
+ poperror();
+ c->qid = e->dir.gid;
+ c->aux = e;
c->flag |= COPEN;
- c->mode = OWRITE;
+ c->mode = omode;
}
void
srvremove(Chan *c)
{
- Chan *f;
+ struct entry *e = c->aux;
- if(c->qid == CHDIR)
+ if (e->parent == 0)
error(0, Eperm);
- lock(&srv);
- if(waserror()){
- unlock(&srv);
+ lock(e->parent);
+ if (waserror()) {
+ unlock(e->parent);
nexterror();
}
- f = srv.chan[c->qid];
- if(f == 0)
- error(0, Eshutdown);
- if(strcmp(&srv.name[c->qid*NAMELEN], "boot") == 0)
- error(0, Eperm);
- srv.chan[c->qid] = 0;
- unlock(&srv);
+ if (e->dir.mode & CHDIR) {
+ if (e->entries != 0)
+ error(0, Eperm);
+ }
+ else {
+ if (e->chan == 0)
+ error(0, Eshutdown);
+ close(e->chan);
+ }
+ if ((*e->back = e->next) != 0)
+ e->next->back = e->back;
+ unlock(e->parent);
poperror();
- close(f);
+ free(e);
}
void
@@ 160,33 209,72 @@ srvclose(Chan *c)
{
}
+/* A directory is being read. The entries must be synthesized. e points
+ * to a list of entries in this directory. Count is the size to be
+ * read.
+ */
+int srv_direntry(struct entry *e, char *a, long count){
+ Dir dir;
+ int n = 0;
+
+ while (n != count && e != 0) {
+ n += convD2M(&e->dir, a + n);
+ e = e->next;
+ }
+ return n;
+}
+
long
srvread(Chan *c, void *va, long n)
{
- char *a = va;
+ struct entry *dir = c->aux, *e;
+ int offset = c->offset;
- if(c->qid != CHDIR)
- panic("srvread");
- return devdirread(c, a, n, (Dirtab *)0, 0L, srvgen);
+ isdir(c);
+ if (n <= 0)
+ return 0;
+ if ((offset % DIRLEN) != 0 || (n % DIRLEN) != 0)
+ error(0, Egreg);
+ lock(dir);
+ for (e = dir->entries; e != 0; e = e->next)
+ if (offset <= 0) {
+ n = srv_direntry(e, va, n);
+ unlock(dir);
+ c->offset += n;
+ return n;
+ }
+ else
+ offset -= DIRLEN;
+ unlock(dir);
+ return 0;
}
long
srvwrite(Chan *c, void *va, long n)
{
+ struct entry *e = c->aux;
int i, fd;
char buf[32];
- i = c->qid;
- if(srv.chan[i] != c) /* already been written to */
+ if (e->dir.mode & CHDIR)
+ panic("write to directory");
+ lock(e);
+ if (waserror()) {
+ unlock(e);
+ nexterror();
+ }
+ if (e->chan != 0)
error(0, Egreg);
- if(n >= sizeof buf)
+ if (n >= sizeof buf)
error(0, Egreg);
memcpy(buf, va, n); /* so we can NUL-terminate */
buf[n] = 0;
fd = strtoul(buf, 0, 0);
fdtochan(fd, -1); /* error check only */
- srv.chan[i] = u->fd[fd];
- incref(u->fd[fd]);
+ e->chan = u->fd[fd];
+ incref(e->chan);
+ unlock(e);
+ poperror();
return n;
}
M power/dat.h => power/dat.h +4 -1
@@ 107,7 107,10 @@ struct Chan
Mount *mnt; /* mount point that derived Chan */
ulong mountid;
int fid; /* for devmnt */
- Stream *stream; /* for stream channels */
+ union{
+ Stream *stream; /* for stream channels */
+ void *aux;
+ };
Chan *mchan; /* channel to mounted server */
ulong mqid; /* qid of root of mount point */
};
M power/main.c => power/main.c +1 -1
@@ 121,7 121,7 @@ ioboardinit(void)
maxlevel = 8;
noforce = 0;
}
-
+ print("IO %d\n", ioid);
/*
* reset VME bus (MODEREG is on the IO2)