From 77899d563f9a6d22c14dec9d9d7fad4f893c02e1 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 2 Oct 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-10-02 --- gnot/dat.h | 5 +- gnot/devsrv.c | 250 ++++++++++++++++++++++++++++++++++---------------- gnot/sturp.c | 21 +++-- port/devmnt.c | 5 +- port/devsrv.c | 250 ++++++++++++++++++++++++++++++++++---------------- power/dat.h | 5 +- power/main.c | 2 +- 7 files changed, 365 insertions(+), 173 deletions(-) diff --git a/gnot/dat.h b/gnot/dat.h index cb556d62fe0877a857459347efbcf47ec2c301ea..1fe695070f0589639306c5280a780ac59ed5b214 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -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 */ }; diff --git a/gnot/devsrv.c b/gnot/devsrv.c index 3a96b82499f77a20dc6b176bd45865f481e86716..7ad6fe3ea093f4b4262dbf1c7da2eeb608ef5ffc 100644 --- a/gnot/devsrv.c +++ b/gnot/devsrv.c @@ -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; ientries; 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; } diff --git a/gnot/sturp.c b/gnot/sturp.c index 1e63142c1f38fd7108f750161ac027ac2e45fc14..ea00165ad804554504ed685840e2d370f762ae0d 100644 --- a/gnot/sturp.c +++ b/gnot/sturp.c @@ -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) diff --git a/port/devmnt.c b/port/devmnt.c index 239b2b253383fbeb890e71a0eda588606e89c1e2..ca3338bc18be022e3f27f20d7ad4087c664e4e66 100644 --- a/port/devmnt.c +++ b/port/devmnt.c @@ -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(); diff --git a/port/devsrv.c b/port/devsrv.c index c938e198a1d1e6b6a2b2d6d6a8c85730d6d19108..7ad6fe3ea093f4b4262dbf1c7da2eeb608ef5ffc 100644 --- a/port/devsrv.c +++ b/port/devsrv.c @@ -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; ientries; 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; } diff --git a/power/dat.h b/power/dat.h index 68900cfee81a6a06a8539c4b82f52bbd42faa156..8e8ddd0dbfb252a8468f4024a47c6c3f5acfa1cb 100644 --- a/power/dat.h +++ b/power/dat.h @@ -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 */ }; diff --git a/power/main.c b/power/main.c index 587e9ef370160b4175f16c0b314e7e777093f3f2..458e238f7883735914fd14499ca67c5c9e443890 100644 --- a/power/main.c +++ b/power/main.c @@ -121,7 +121,7 @@ ioboardinit(void) maxlevel = 8; noforce = 0; } - + print("IO %d\n", ioid); /* * reset VME bus (MODEREG is on the IO2)