| plan 9 kernel history: overview | file list | diff list |
1990/0604/port/devmnt.c (diff list | history)
| 1990/0513/sys/src/9/port/devmnt.c:9,28 – 1990/0604/sys/src/9/port/devmnt.c:9,37 (short | long | prev | next) | ||
| 1990/0227 | #include "fcall.h" | |
| 1990/0604 | typedef struct Mnthdr Mnthdr; typedef struct MntQ MntQ; | |
| 1990/0227 | struct Mnt { Ref; /* for number of chans, incl. mntpt but not msg */ | |
| 1990/0324 |
| |
| 1990/0303 | ulong mntid; /* serial # */ | |
| 1990/0227 |
| |
| 1990/0604 | MntQ *q; | |
| 1990/0227 | }; | |
| 1990/0604 | struct MntQ { Ref; QLock; /* for access */ MntQ *next; /* for allocation */ Chan *msg; /* for reading and writing messages */ Proc *reader; /* process reading response */ Mnthdr *writer; /* queue of headers of written messages */ }; | |
| 1990/0227 | #define BUFSIZE (MAXFDATA+500) /* BUG */ typedef struct Mntbuf Mntbuf; struct Mntbuf | |
| 1990/0513/sys/src/9/port/devmnt.c:37,48 – 1990/0604/sys/src/9/port/devmnt.c:46,59 | ||
| 1990/0227 | Mntbuf *free; }mntbufalloc; | |
| 1990/0604 | struct Mnthdr | |
| 1990/0227 | { | |
| 1990/0604 | Mnthdr *next; /* in free list or writers list */ | |
| 1990/0227 | Fcall thdr; Fcall rhdr; | |
| 1990/0604 | Rendez r; Proc *p; Mntbuf *mbr; | |
| 1990/0227 | }; struct | |
| 1990/0513/sys/src/9/port/devmnt.c:54,59 – 1990/0604/sys/src/9/port/devmnt.c:65,77 | ||
| 1990/0303 | struct { Lock; | |
| 1990/0604 | MntQ *arena; MntQ *free; }mntqalloc; struct { Lock; | |
| 1990/0303 | long id; }mntid; | |
| 1990/0513/sys/src/9/port/devmnt.c:106,112 – 1990/0604/sys/src/9/port/devmnt.c:124,130 | ||
| 1990/0227 | unlock(&mnthdralloc); print("no mnthdrs\n"); if(u == 0) | |
| 1990/0604 | panic("mhalloc"); | |
| 1990/0227 | u->p->state = Wakeme; alarm(1000, wakeme, u->p); sched(); | |
| 1990/0513/sys/src/9/port/devmnt.c:122,127 – 1990/0604/sys/src/9/port/devmnt.c:140,184 | ||
| 1990/0227 | unlock(&mnthdralloc); } | |
| 1990/0604 | MntQ* mqalloc(void) { MntQ *q; lock(&mntqalloc); if(q = mntqalloc.free){ /* assign = */ mntqalloc.free = q->next; unlock(&mntqalloc); lock(q); q->ref = 1; q->writer = 0; q->reader = 0; unlock(q); return q; } unlock(&mntqalloc); panic("no mntqs\n"); /* there MUST be enough */ } void mqfree(MntQ *mq) { Chan *msg = 0; lock(mq); if(--mq->ref == 0){ msg = mq->msg; mq->msg = 0; lock(&mntqalloc); mq->next = mntqalloc.free; mntqalloc.free = mq; unlock(&mntqalloc); } unlock(mq); if(msg) /* after locks are down */ close(msg); } | |
| 1990/0227 | Mnt* mntdev(int dev, int noerr) { | |
| 1990/0513/sys/src/9/port/devmnt.c:130,136 – 1990/0604/sys/src/9/port/devmnt.c:187,193 | ||
| 1990/0227 | ||
| 1990/0303 | for(m=mnt,i=0; i<conf.nmntdev; i++,m++) /* use a hash table some day */ if(m->mntid == dev){ | |
| 1990/0604 | if(m->q == 0) | |
| 1990/0303 | break; return m; } | |
| 1990/0513/sys/src/9/port/devmnt.c:145,150 – 1990/0604/sys/src/9/port/devmnt.c:202,208 | ||
| 1990/0227 | int i; Mntbuf *mb; Mnthdr *mh; | |
| 1990/0604 | MntQ *mq; | |
| 1990/0227 | mnt = ialloc(conf.nmntdev*sizeof(Mnt), 0); | |
| 1990/0513/sys/src/9/port/devmnt.c:159,164 – 1990/0604/sys/src/9/port/devmnt.c:217,229 | ||
| 1990/0227 | mh[i].next = &mh[i+1]; mh[i].next = 0; mnthdralloc.free = mh; | |
| 1990/0604 | 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; | |
| 1990/0227 | } void | |
| 1990/0513/sys/src/9/port/devmnt.c:170,177 – 1990/0604/sys/src/9/port/devmnt.c:235,243 | ||
| 1990/0227 | mntattach(char *spec) { int i; | |
| 1990/0604 | Mnt *m, *mm; | |
| 1990/0227 | Mnthdr *mh; | |
| 1990/0604 | MntQ *q; | |
| 1990/0227 | Chan *c, *cm; struct bogus{ Chan *chan; | |
| 1990/0513/sys/src/9/port/devmnt.c:189,194 – 1990/0604/sys/src/9/port/devmnt.c:255,261 | ||
| 1990/0227 | unlock(m); } error(0, Enomntdev); | |
| 1990/0604 | ||
| 1990/0227 | Found: m->ref = 1; unlock(m); | |
| 1990/0513/sys/src/9/port/devmnt.c:199,209 – 1990/0604/sys/src/9/port/devmnt.c:266,296 | ||
| 1990/0303 | c->dev = m->mntid; | |
| 1990/0227 | m->mntpt = c; cm = bogus.chan; | |
| 1990/0604 | /* * Look for queue to same msg channel */ q = mntqalloc.arena; for(i=0; i<conf.nmntdev; i++,q++) if(q->msg==cm){ lock(q); if(q->ref && q->msg==cm){ m->q = q; q->ref++; unlock(q); goto out; } unlock(q); } m->q = mqalloc(); m->q->msg = cm; | |
| 1990/0227 | incref(cm); | |
| 1990/0604 | out: | |
| 1990/0227 | mh = mhalloc(); if(waserror()){ mhfree(mh); | |
| 1990/0604 | mqfree(q); | |
| 1990/0227 | close(c); nexterror(); } | |
| 1990/0513/sys/src/9/port/devmnt.c:213,219 – 1990/0604/sys/src/9/port/devmnt.c:300,306 | ||
| 1990/0227 | strcpy(mh->thdr.aname, spec); mntxmit(m, mh); c->qid = mh->rhdr.qid; | |
| 1990/0303 |
| |
| 1990/0604 | c->mchan = m->q->msg; | |
| 1990/0303 | c->mqid = c->qid; | |
| 1990/0227 | mhfree(mh); poperror(); | |
| 1990/0513/sys/src/9/port/devmnt.c:364,395 – 1990/0604/sys/src/9/port/devmnt.c:451,496 | ||
| 1990/0227 | } void | |
| 1990/0604 | mntclunk(Chan *c, int t) | |
| 1990/0227 | { Mnt *m; Mnthdr *mh; | |
| 1990/0604 | MntQ *q; int waserr; int ne = u->nerrlab; | |
| 1990/0227 | m = mntdev(c->dev, 0); mh = mhalloc(); | |
| 1990/0604 | mh->thdr.type = t; | |
| 1990/0227 | mh->thdr.fid = c->fid; | |
| 1990/0604 | waserr = 0; if(waserror()) /* gotta clean up as if there wasn't */ waserr = 1; else mntxmit(m, mh); | |
| 1990/0227 | mhfree(mh); if(c == m->mntpt) m->mntpt = 0; | |
| 1990/0324 |
| |
| 1990/0227 |
| |
| 1990/0324 |
| |
| 1990/0227 |
| |
| 1990/0604 | lock(m); if(--m->ref == 0){ /* BUG: need to hang up all pending i/o */ q = m->q; m->q = 0; m->mntid = 0; unlock(m); /* mqfree can take time */ mqfree(q); }else unlock(m); if(waserr) nexterror(); | |
| 1990/0227 | poperror(); } | |
| 1990/0604 | void mntclose(Chan *c) { mntclunk(c, Tclunk); } | |
| 1990/0227 | long mntreadwrite(Chan *c, void *vbuf, long n, int type) { | |
| 1990/0513/sys/src/9/port/devmnt.c:458,478 – 1990/0604/sys/src/9/port/devmnt.c:559,565 | ||
| 1990/0227 | void mntremove(Chan *c) { | |
| 1990/0312 |
| |
| 1990/0227 |
| |
| 1990/0604 | mntclunk(c, Tremove); | |
| 1990/0227 | } void | |
| 1990/0513/sys/src/9/port/devmnt.c:550,560 – 1990/0604/sys/src/9/port/devmnt.c:637,684 | ||
| 1990/0227 | } void | |
| 1990/0604 | mnterrdequeue(MntQ *q, Mnthdr *mh) /* queue is unlocked */ { Mnthdr *w; qlock(q); /* take self from queue if necessary */ if(q->reader == u->p){ /* advance a writer to reader */ w = q->writer; if(w){ q->reader = w->p; q->writer = w->next; wakeup(&w->r); }else{ q->reader = 0; q->writer = 0; } }else{ w = q->writer; if(w == mh) q->writer = w->next; else{ while(w){ if(w->next == mh){ w->next = mh->next; break; } w = w->next; } } } qunlock(q); } void | |
| 1990/0227 | mntxmit(Mnt *m, Mnthdr *mh) { ulong n; Mntbuf *mbr, *mbw; | |
| 1990/03081 |
| |
| 1990/0604 | Mnthdr *w, *ow; Chan *mntpt; MntQ *q; int qlocked; | |
| 1990/0227 | mbr = mballoc(); mbw = mballoc(); | |
| 1990/0513/sys/src/9/port/devmnt.c:564,601 – 1990/0604/sys/src/9/port/devmnt.c:688,724 | ||
| 1990/0227 | nexterror(); } n = convS2M(&mh->thdr, mbw->buf); | |
| 1990/0604 | q = m->q; if(q == 0) error(0, Eshutdown); #ifdef BIT3 | |
| 1990/03081 | /* | |
| 1990/0511 | * Bit3 does its own multiplexing. (Well, the file server does.) * The code is different enough that it's broken out separately here. | |
| 1990/03081 | */ | |
| 1990/0511 |
| |
| 1990/0604 | if(devchar[q->msg->type] != '3') | |
| 1990/0511 | goto Normal; | |
| 1990/0324 |
| |
| 1990/0511 |
| |
| 1990/03081 |
| |
| 1990/0511 |
| |
| 1990/0604 | incref(q); | |
| 1990/0227 | if(waserror()){ | |
| 1990/0511 |
| |
| 1990/0604 | mqfree(q); | |
| 1990/0227 | nexterror(); } | |
| 1990/03081 |
| |
| 1990/0227 |
| |
| 1990/0604 | if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ print("short write in mntxmit\n"); error(0, Eshortmsg); | |
| 1990/0227 | } /* * Read response */ | |
| 1990/03081 |
| |
| 1990/0511 |
| |
| 1990/0604 | n = (*devtab[q->msg->type].read)(q->msg, mbr->buf, BUFSIZE); mqfree(q); | |
| 1990/0511 | poperror(); if(convM2S(mbr->buf, &mh->rhdr, n) == 0){ | |
| 1990/0604 | print("format error in mntxmit\n"); error(0, Ebadmsg); | |
| 1990/0511 | } /* | |
| 1990/0513/sys/src/9/port/devmnt.c:602,613 – 1990/0604/sys/src/9/port/devmnt.c:725,736 | ||
| 1990/0511 | * Various checks */ if(mh->rhdr.type != mh->thdr.type+1){ | |
| 1990/0604 | print("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1); error(0, Ebadmsg); | |
| 1990/0511 | } if(mh->rhdr.fid != mh->thdr.fid){ | |
| 1990/0604 | print("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type); error(0, Ebadmsg); | |
| 1990/0511 | } if(mh->rhdr.err){ mntpt = m->mntpt; /* unsafe, but Errors are unsafe anyway */ | |
| 1990/0513/sys/src/9/port/devmnt.c:627,672 – 1990/0604/sys/src/9/port/devmnt.c:750,846 | ||
| 1990/0511 | return; Normal: | |
| 1990/0324 |
| |
| 1990/0511 |
| |
| 1990/0604 | #endif incref(q); qlock(q); qlocked = 1; | |
| 1990/0511 | if(waserror()){ | |
| 1990/03081 |
| |
| 1990/0604 | if(qlocked) qunlock(q); mqfree(q); | |
| 1990/0511 | nexterror(); | |
| 1990/03081 | } | |
| 1990/0511 |
| |
| 1990/0604 | if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){ print("short write in mntxmit\n"); error(0, Eshortmsg); | |
| 1990/0511 | } | |
| 1990/0227 |
| |
| 1990/0604 | if(q->reader == 0){ /* i will read */ q->reader = u->p; Read: qunlock(q); qlocked = 0; n = (*devtab[q->msg->type].read)(q->msg, mbr->buf, BUFSIZE); if(convM2S(mbr->buf, &mh->rhdr, n) == 0){ print("format error in mntxmit\n"); mnterrdequeue(q, mh); error(0, Ebadmsg); } /* * Response might not be mine */ qlock(q); qlocked = 1; if(mh->rhdr.fid == mh->thdr.fid && mh->rhdr.type == mh->thdr.type+1){ /* it's mine */ q->reader = 0; if(w = q->writer){ /* advance a writer to reader */ q->reader = w->p; q->writer = w->next; wakeup(&w->r); } qunlock(q); qlocked = 0; goto Respond; } /* * Hand response to correct recipient */ if(q->writer == 0) print("response with empty queue\n"); for(ow=0,w=q->writer; w; ow=w,w=w->next) if(mh->rhdr.fid == w->thdr.fid && mh->rhdr.type == w->thdr.type+1){ Mntbuf *t; t = mbr; mbr = w->mbr; w->mbr = t; memcpy(&w->rhdr, &mh->rhdr, sizeof mh->rhdr); /* take recipient from queue */ if(ow == 0) q->writer = w->next; else ow->next = w->next; wakeup(&w->r); goto Read; } goto Read; }else{ mh->mbr = mbr; mh->p = u->p; /* put self in queue */ mh->next = q->writer; q->writer = mh; qunlock(q); qlocked = 0; if(waserror()){ /* interrupted sleep */ print("interrupted i/o\n"); mnterrdequeue(q, mh); nexterror(); } sleep(&mh->r, return0, 0); poperror(); qlock(q); qlocked = 1; if(q->reader == u->p) /* i got promoted */ goto Read; mbr = mh->mbr; /* pick up my buffer */ qunlock(q); qlocked = 0; goto Respond; | |
| 1990/0227 | } | |
| 1990/0604 | Respond: mqfree(q); poperror(); | |
| 1990/0227 | if(mh->rhdr.err){ mntpt = m->mntpt; /* unsafe, but Errors are unsafe anyway */ if(mntpt) | |