A pc/devrtc.c => pc/devrtc.c +337 -0
@@ 0,0 1,337 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "errno.h"
+#include "devtab.h"
+
+enum {
+ Paddr= 0x70, /* address port */
+ Pdata= 0x71, /* data port */
+
+ Seconds= 0x00,
+ Minutes= 0x02,
+ Hours= 0x04,
+ Mday= 0x07,
+ Month= 0x08,
+ Year= 0x09,
+ Status= 0x0A,
+
+ Nbcd= 6,
+};
+
+typedef struct Rtc Rtc;
+struct Rtc
+{
+ int sec;
+ int min;
+ int hour;
+ int mday;
+ int mon;
+ int year;
+};
+
+QLock rtclock; /* mutex on clock operations */
+
+#define NRTC 1
+Dirtab rtcdir[]={
+ "rtc", {1, 0}, 0, 0600,
+};
+
+ulong rtc2sec(Rtc*);
+void sec2rtc(ulong, Rtc*);
+int *yrsize(int);
+
+void
+rtcreset(void)
+{
+}
+
+void
+rtcinit(void)
+{
+}
+
+Chan*
+rtcattach(char *spec)
+{
+ return devattach('r', spec);
+}
+
+Chan*
+rtcclone(Chan *c, Chan *nc)
+{
+ return devclone(c, nc);
+}
+
+int
+rtcwalk(Chan *c, char *name)
+{
+ return devwalk(c, name, rtcdir, NRTC, devgen);
+}
+
+void
+rtcstat(Chan *c, char *dp)
+{
+ devstat(c, dp, rtcdir, NRTC, devgen);
+}
+
+Chan*
+rtcopen(Chan *c, int omode)
+{
+ return devopen(c, omode, rtcdir, NRTC, devgen);
+}
+
+void
+rtccreate(Chan *c, char *name, int omode, ulong perm)
+{
+ error(Eperm);
+}
+
+void
+rtcclose(Chan *c)
+{
+}
+
+#define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4))
+
+long
+rtctime(void)
+{
+ int i,j;
+ uchar ch;
+ uchar bcdclock[Nbcd];
+ char atime[64];
+ Rtc rtc;
+
+ outb(Paddr, Status);
+ while(inb(Pdata) & 1)
+ ;
+ outb(Paddr, Seconds); bcdclock[0] = inb(Pdata);
+ outb(Paddr, Minutes); bcdclock[1] = inb(Pdata);
+ outb(Paddr, Hours); bcdclock[2] = inb(Pdata);
+ outb(Paddr, Mday); bcdclock[3] = inb(Pdata);
+ outb(Paddr, Month); bcdclock[4] = inb(Pdata);
+ outb(Paddr, Year); bcdclock[5] = inb(Pdata);
+
+ /*
+ * convert from BCD
+ */
+ rtc.sec = GETBCD(0);
+ rtc.min = GETBCD(1);
+ rtc.hour = GETBCD(2);
+ rtc.mday = GETBCD(3);
+ rtc.mon = GETBCD(4);
+ rtc.year = GETBCD(5);
+
+ /*
+ * the world starts jan 1 1970
+ */
+ if(rtc.year < 70)
+ rtc.year += 2000;
+ else
+ rtc.year += 1900;
+ return rtc2sec(&rtc);
+}
+
+long
+rtcread(Chan *c, void *buf, long n, ulong offset)
+{
+ ulong t, ot;
+
+ if(c->qid.path & CHDIR)
+ return devdirread(c, buf, n, rtcdir, NRTC, devgen);
+
+ qlock(&rtclock);
+ t = rtctime();
+ do{
+ ot = t;
+ t = rtctime(); /* make sure there's no skew */
+ }while(t != ot);
+ qunlock(&rtclock);
+ n = readnum(offset, buf, n, t, 12);
+ return n;
+
+}
+
+#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)
+
+long
+rtcwrite(Chan *c, void *buf, long n, ulong offset)
+{
+ Rtc rtc;
+ ulong secs;
+ int i,j;
+ uchar ch;
+ uchar bcdclock[Nbcd];
+ uchar *nv;
+ char *cp, *ep;
+
+ if(offset!=0)
+ error(Ebadarg);
+
+ /*
+ * read the time
+ */
+ cp = ep = buf;
+ ep += n;
+ while(cp < ep){
+ if(*cp>='0' && *cp<='9')
+ break;
+ cp++;
+ }
+ secs = strtoul(cp, 0, 0);
+
+ /*
+ * convert to bcd
+ */
+ sec2rtc(secs, &rtc);
+ PUTBCD(rtc.sec, 0);
+ PUTBCD(rtc.min, 1);
+ PUTBCD(rtc.hour, 2);
+ PUTBCD(rtc.mday, 3);
+ PUTBCD(rtc.mon, 4);
+ PUTBCD(rtc.year, 5);
+
+ /*
+ * write the clock
+ */
+ qlock(&rtclock);
+ outb(Paddr, Seconds); outb(Pdata, bcdclock[0]);
+ outb(Paddr, Minutes); outb(Pdata, bcdclock[1]);
+ outb(Paddr, Hours); outb(Pdata, bcdclock[2]);
+ outb(Paddr, Mday); outb(Pdata, bcdclock[3]);
+ outb(Paddr, Month); outb(Pdata, bcdclock[4]);
+ outb(Paddr, Year); outb(Pdata, bcdclock[5]);
+ qunlock(&rtclock);
+
+ return n;
+}
+
+void
+rtcremove(Chan *c)
+{
+ error(Eperm);
+}
+
+void
+rtcwstat(Chan *c, char *dp)
+{
+ error(Eperm);
+}
+
+#define SEC2MIN 60L
+#define SEC2HOUR (60L*SEC2MIN)
+#define SEC2DAY (24L*SEC2HOUR)
+
+/*
+ * days per month plus days/year
+ */
+static int dmsize[] =
+{
+ 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+static int ldmsize[] =
+{
+ 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * return the days/month for the given year
+ */
+int *
+yrsize(int yr)
+{
+ if((yr % 4) == 0)
+ return ldmsize;
+ else
+ return dmsize;
+}
+
+/*
+ * compute seconds since Jan 1 1970
+ */
+ulong
+rtc2sec(Rtc *rtc)
+{
+ ulong secs;
+ int i;
+ int *d2m;
+
+ secs = 0;
+
+ /*
+ * seconds per year
+ */
+ for(i = 1970; i < rtc->year; i++){
+ d2m = yrsize(i);
+ secs += d2m[0] * SEC2DAY;
+ }
+
+ /*
+ * seconds per month
+ */
+ d2m = yrsize(rtc->year);
+ for(i = 1; i < rtc->mon; i++)
+ secs += d2m[i] * SEC2DAY;
+
+ secs += (rtc->mday-1) * SEC2DAY;
+ secs += rtc->hour * SEC2HOUR;
+ secs += rtc->min * SEC2MIN;
+ secs += rtc->sec;
+
+ return secs;
+}
+
+/*
+ * compute rtc from seconds since Jan 1 1970
+ */
+void
+sec2rtc(ulong secs, Rtc *rtc)
+{
+ int d;
+ long hms, day;
+ int *d2m;
+
+ /*
+ * break initial number into days
+ */
+ hms = secs % SEC2DAY;
+ day = secs / SEC2DAY;
+ if(hms < 0) {
+ hms += SEC2DAY;
+ day -= 1;
+ }
+
+ /*
+ * generate hours:minutes:seconds
+ */
+ rtc->sec = hms % 60;
+ d = hms / 60;
+ rtc->min = d % 60;
+ d /= 60;
+ rtc->hour = d;
+
+ /*
+ * year number
+ */
+ if(day >= 0)
+ for(d = 1970; day >= *yrsize(d); d++)
+ day -= *yrsize(d);
+ else
+ for (d = 1970; day < 0; d--)
+ day += *yrsize(d-1);
+ rtc->year = d;
+
+ /*
+ * generate month
+ */
+ d2m = yrsize(rtc->year);
+ for(d = 1; day >= d2m[d]; d++)
+ day -= d2m[d];
+ rtc->mday = day + 1;
+ rtc->mon = d;
+
+ return;
+}
M pc/kbd.c => pc/kbd.c +29 -3
@@ 35,6 35,7 @@ enum {
Latin= Spec|0x63,
Caps= Spec|0x64,
Num= Spec|0x65,
+ Middle= Spec|0x66,
No= Spec|0x7F, /* no mapping */
Home= KF|13,
@@ 59,7 60,7 @@ uchar kbtab[] =
[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,
-[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
[0x48] No, No, No, No, No, No, No, No,
[0x50] No, No, No, No, No, No, No, KF|11,
@@ 75,7 76,7 @@ uchar kbtabshift[] =
[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,
-[0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
+[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
[0x48] No, No, No, No, No, No, No, No,
[0x50] No, No, No, No, No, No, No, KF|11,
@@ 231,6 232,9 @@ struct latin
*/
KIOQ kbdq;
+static int mousebuttons;
+static int middlebutton;
+
/*
* predeclared
*/
@@ 367,7 371,8 @@ mymouseputc(int c)
if(msg[0] & 0x20)
msg[2] |= 0xFF00;
- mouse.newbuttons = b[msg[0]&7];
+ mousebuttons = b[msg[0]&7];
+ mouse.newbuttons = mousebuttons | middlebutton;
mouse.dx = msg[1];
mouse.dy = -msg[2];
mouse.track = 1;
@@ 377,6 382,21 @@ mymouseputc(int c)
}
/*
+ * Ctrl key used as middle button pressed
+ */
+static void
+middle(int newval)
+{
+ middlebutton = newval;
+ mouse.newbuttons = mousebuttons | middlebutton;
+ mouse.dx = 0;
+ mouse.dy = 0;
+ mouse.track = 1;
+ spllo(); /* mouse tracking kills uart0 */
+ mouseclock();
+}
+
+/*
* keyboard interrupt
*/
int
@@ 458,6 478,9 @@ kbdintr0(void)
case Ctrl:
ctl = 0;
break;
+ case Middle:
+ middle(0);
+ break;
}
return 0;
}
@@ 502,6 525,9 @@ kbdintr0(void)
case Ctrl:
ctl = 1;
return 0;
+ case Middle:
+ middle(2);
+ return 0;
}
}
kbdputc(&kbdq, c);
M port/devcons.c => port/devcons.c +1 -1
@@ 161,7 161,7 @@ panic(char *fmt, ...)
char buf[PRINTSIZE];
int n;
- strcpy(buf, "panic: ");
+ strcpy(buf, "inconceivable: ");
n = doprint(buf+7, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
buf[n] = '\n';
putstrn(buf, n+1);
M port/devmnt.c => port/devmnt.c +573 -743
@@ 4,241 4,110 @@
#include "dat.h"
#include "fns.h"
#include "errno.h"
-
#include "devtab.h"
-
#include "fcall.h"
-typedef struct Mnt Mnt;
-typedef struct Mnthdr Mnthdr;
-typedef struct MntQ MntQ;
-
-struct Mnt
-{
- Ref; /* for number of chans, incl. mntpt but not msg */
- ulong mntid; /* serial # */
- Chan *mntpt; /* channel in user's name space */
- MntQ *q;
-};
-
-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 */
+typedef struct Mntrpc Mntrpc;
+typedef struct Mnt Mnt;
+
+struct Mntrpc
+{
+ Mntrpc *list; /* Free/pending list */
+ Fcall request; /* Outgoing file system protocol message */
+ Fcall reply; /* Incoming reply */
+ Mnt *m; /* Mount device during rpc */
+ Rendez r; /* Place to hang out */
+ char *rpc; /* I/O Data buffer */
+ char done; /* Rpc completed */
+ char bfree; /* Buffer may be freed after flush */
+ char flushed; /* Flush was sent */
+ ushort flushtag; /* Tag to send flush on */
+ ushort flushbase; /* Base tag of flush window for this buffer */
+ char flush[MAXMSG]; /* Somewhere to build flush */
};
-#define BITROUND 256
-#define BUFSIZE (MAXFDATA+MAXMSG)
-typedef struct Mntbuf Mntbuf;
-struct Mntbuf
+struct Mnt
{
- Mntbuf *next;
- char buf[BUFSIZE+BITROUND]; /* BUG */
+ Ref; /* Count of attached channels */
+ Chan *c; /* Channel to file service */
+ Proc *rip; /* Reader in progress */
+ Mntrpc *queue; /* Queue of pending requests on this channel */
+ int id; /* Multiplexor id for channel check */
+ Mnt *list; /* Free list */
+ char mux; /* Set if the device aleady does the multiplexing */
};
-struct
+struct Mntalloc
{
Lock;
- Mntbuf *free;
-}mntbufalloc;
-
-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 */
- Fcall thdr;
- Fcall rhdr;
- Rendez r;
- Proc *p;
- Mntbuf *mbr;
- int readreply; /* true if we are reader or our reply has come */
+ Mnt *mntfree;
+ Mnt *mntarena;
+ Mntrpc *rpcfree;
+ Mntrpc *rpcarena;
+ int id;
+}mntalloc;
+
+#define BITBOTCH 256
+#define MAXRPC (MAXFDATA+MAXMSG+BITBOTCH)
+#define limit(n, max) (n > max ? max : n)
+
+Chan *mattach(Mnt*, char*, char*);
+Mntrpc *mntralloc(void);
+void mntfree(Mntrpc*);
+int rpcattn(Mntrpc*);
+void mountrpc(Mnt*, Mntrpc*);
+void mountio(Mnt*, Mntrpc*);
+Mnt *mntchk(Chan*);
+void mountmux(Mnt*, Mntrpc*);
+long mntrdwr(int , Chan*, void*,long , ulong);
+int mntflush(Mnt*, Mntrpc*);
+void mntqrm(Mnt*, Mntrpc*);
+void mntdirfix(uchar*, Chan*);
+void mntgate(Mnt*);
+void mntrpcread(Mnt*, Mntrpc*);
+
+enum
+{
+ Tagspace = 1,
+ Flushspace = 64,
+ Flushtag = 512,
};
-struct
-{
- Lock;
- Mnthdr *arena;
- Mnthdr *free;
-}mnthdralloc;
-
-struct
-{
- Lock;
- QLock;
- MntQ *arena;
- MntQ *free;
-}mntqalloc;
-
-struct
-{
- Lock;
- long id;
-}mntid;
-
-Mnt *mnt;
-void mntxmit(Mnt*, Mnthdr*);
-
-Mntbuf*
-mballoc(void)
-{
- Mntbuf *mb;
-
-loop:
- lock(&mntbufalloc);
- if(mb = mntbufalloc.free){ /* assign = */
- mntbufalloc.free = mb->next;
- unlock(&mntbufalloc);
- return mb;
- }
- unlock(&mntbufalloc);
- print("no mntbufs\n");
- if(u == 0)
- panic("mballoc");
- u->p->state = Wakeme;
- alarm(1000, wakeme, u->p);
- sched();
- goto loop;
-}
-
-void
-mbfree(Mntbuf *mb)
-{
- lock(&mntbufalloc);
- mb->next = mntbufalloc.free;
- mntbufalloc.free = mb;
- unlock(&mntbufalloc);
-}
-
-Mnthdr*
-mhalloc(void)
-{
- Mnthdr *mh;
-
-loop:
- lock(&mnthdralloc);
- if(mh = mnthdralloc.free){ /* assign = */
- mnthdralloc.free = mh->next;
-if(mh->active) print("mh->active\n");
-if(mh->flushing) print("mh->flushing\n");
-if(mh->mbr) print("mh->mbr\n");
- mh->mbr = 0;
- unlock(&mnthdralloc);
- return mh;
- }
- unlock(&mnthdralloc);
- print("no mnthdrs\n");
- if(u == 0)
- panic("mhalloc");
- u->p->state = Wakeme;
- alarm(1000, wakeme, u->p);
- sched();
- goto loop;
-}
-
-void
-mhfree(Mnthdr *mh)
-{
- if(mh->flushing)
- return;
- mh->active = 0;
- lock(&mnthdralloc);
- mh->next = mnthdralloc.free;
- mnthdralloc.free = mh;
- unlock(&mnthdralloc);
-}
-
-MntQ*
-mqalloc(Chan *msg) /* mntqalloc is qlocked */
-{
- MntQ *q;
-
- if(q = mntqalloc.free){ /* assign = */
- mntqalloc.free = q->next;
- lock(q);
- q->ref = 1;
- q->msg = msg;
- unlock(q);
- incref(msg);
- q->writer = 0;
- q->reader = 0;
- return q;
- }
- 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);
-}
-
-Mnt*
-mntdev(Chan *c, int noerr)
-{
- Mnt *m;
- int i;
-
- m = &mnt[c->mntindex];
- if(m->mntid==c->dev && m->q!=0)
- return m;
- if(noerr)
- return 0;
- print("mntdev shutdown %d %d %d %lux\n", c->dev, c->mntindex,
- m->mntid, m->q);
- error(Eshutdown);
-}
-
void
mntreset(void)
{
- int i;
- Mntbuf *mb;
- Mnthdr *mh;
- MntQ *mq;
-
- 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;
-
- mh = ialloc(conf.nmnthdr*sizeof(Mnthdr), 0);
- for(i=0; i<conf.nmnthdr-1; i++){
- mh[i].next = &mh[i+1];
- mh[i].thdr.tag = i;
- }
- mh[i].next = 0;
- mh[i].thdr.tag = i;
- mnthdralloc.arena = mh;
- mnthdralloc.free = mh;
-
- 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;
+ Mnt *me, *md;
+ Mntrpc *re, *rd;
+ ushort tag, ftag;
+
+ mntalloc.mntarena = ialloc(conf.nmntdev*sizeof(Mnt), 0);
+ mntalloc.mntfree = mntalloc.mntarena;
+ me = &mntalloc.mntfree[conf.nmntdev];
+ for(md = mntalloc.mntfree; md < me; md++)
+ md->list = md+1;
+ me[-1].list = 0;
+
+ if(conf.nmntbuf > Flushtag) {
+ print("devmnt: buffers limited to %d\n", Flushtag);
+ conf.nmntbuf = Flushtag;
+ }
+
+ tag = Tagspace;
+ ftag = Flushtag;
+ mntalloc.rpcfree = ialloc(conf.nmntbuf*sizeof(Mntrpc), 0);
+ mntalloc.rpcarena = mntalloc.rpcfree;
+ re = &mntalloc.rpcfree[conf.nmntbuf];
+ for(rd = mntalloc.rpcfree; rd < re; rd++) {
+ rd->list = rd+1;
+ rd->request.tag = tag++;
+ rd->flushbase = ftag;
+ rd->flushtag = ftag;
+ ftag += Flushspace;
+ rd->rpc = ialloc(MAXRPC, 0);
+ }
+ re[-1].list = 0;
+
+ mntalloc.id = 1;
}
void
@@ 247,79 116,86 @@ mntinit(void)
}
Chan*
-mntattach(char *crud)
+mntattach(char *muxattach)
{
- int i;
- Mnt *m, *mm;
- Mnthdr *mh;
- MntQ *q;
- Chan *c, *cm;
+ Mnt *m, *e;
struct bogus{
Chan *chan;
char *spec;
char *auth;
}bogus;
- bogus = *((struct bogus *)crud);
-
- m = mnt;
- for(i=0; i<conf.nmntdev; i++,m++){
- lock(m);
- if(m->ref == 0)
- goto Found;
- unlock(m);
+ bogus = *((struct bogus *)muxattach);
+ e = &mntalloc.mntarena[conf.nmntdev];
+ for(m = mntalloc.mntarena; m < e; m++) {
+ if(m->c == bogus.chan && m->id) {
+ lock(m);
+ if(m->ref > 0 && m->id && m->c == bogus.chan) {
+ m->ref++;
+ unlock(m);
+ return mattach(m, bogus.spec, bogus.auth);
+ }
+ unlock(m);
+ }
}
- error(Enomntdev);
-
- Found:
+ lock(&mntalloc);
+ if(mntalloc.mntfree == 0) {
+ unlock(&mntalloc);
+ error(Enomntdev);
+ }
+ m = mntalloc.mntfree;
+ mntalloc.mntfree = m->list;
+ m->id = mntalloc.id++;
+ lock(m);
+ unlock(&mntalloc);
m->ref = 1;
+ m->queue = 0;
+ m->rip = 0;
+ m->c = bogus.chan;
+
+ switch(devchar[m->c->type]) {
+ case 'H': /* Hotrod */
+ case '3': /* BIT3 */
+ m->mux = 1;
+ break;
+ default:
+ m->mux = 0;
+ }
+ incref(m->c);
unlock(m);
- lock(&mntid);
- m->mntid = ++mntid.id;
- unlock(&mntid);
- c = devattach('M', bogus.spec);
- c->dev = m->mntid;
- c->mntindex = m-mnt;
- m->mntpt = c;
- cm = bogus.chan;
-
- /*
- * Look for queue to same msg channel
- */
- q = mntqalloc.arena;
- qlock(&mntqalloc);
- 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(cm);
- out:
- qunlock(&mntqalloc);
- mh = mhalloc();
+ return mattach(m, bogus.spec, bogus.auth);
+}
+
+Chan *
+mattach(Mnt *m, char *spec, char *auth)
+{
+ Chan *c;
+ Mntrpc *r;
+
+ r = mntralloc();
+
+ c = devattach('M', spec);
+ c->dev = m->id;
+ c->mntindex = m-mntalloc.mntarena;
+
if(waserror()){
- mhfree(mh);
+ mntfree(r);
close(c);
nexterror();
}
- mh->thdr.type = Tattach;
- mh->thdr.fid = c->fid;
- memmove(mh->thdr.uname, u->p->pgrp->user, NAMELEN);
- strcpy(mh->thdr.aname, bogus.spec);
- strcpy(mh->thdr.auth, bogus.auth);
- mntxmit(m, mh);
- c->qid = mh->rhdr.qid;
- c->mchan = m->q->msg;
+ r->request.type = Tattach;
+ r->request.fid = c->fid;
+ memmove(r->request.uname, u->p->pgrp->user, NAMELEN);
+ strncpy(r->request.aname, spec, NAMELEN);
+ strncpy(r->request.auth, auth, NAMELEN);
+ mountrpc(m, r);
+
+ c->qid = r->reply.qid;
+ c->mchan = m->c;
c->mqid = c->qid;
- mhfree(mh);
poperror();
+ mntfree(r);
return c;
}
@@ 327,28 203,27 @@ Chan*
mntclone(Chan *c, Chan *nc)
{
Mnt *m;
- Mnthdr *mh;
- int new;
+ Mntrpc *r;
+ int alloc = 0;
- new = 0;
- if(nc == 0){
+ m = mntchk(c);
+ r = mntralloc();
+ if(nc == 0) {
nc = newchan();
- new = 1;
- if(waserror()){
- close(nc);
- nexterror();
- }
+ alloc = 1;
}
- m = mntdev(c, 0);
- mh = mhalloc();
if(waserror()){
- mhfree(mh);
+ mntfree(r);
+ if(alloc)
+ close(nc);
nexterror();
}
- mh->thdr.type = Tclone;
- mh->thdr.fid = c->fid;
- mh->thdr.newfid = nc->fid;
- mntxmit(m, mh);
+
+ r->request.type = Tclone;
+ r->request.fid = c->fid;
+ r->request.newfid = nc->fid;
+ mountrpc(m, r);
+
nc->type = c->type;
nc->dev = c->dev;
nc->qid = c->qid;
@@ 358,14 233,12 @@ mntclone(Chan *c, Chan *nc)
nc->mnt = c->mnt;
nc->mountid = c->mountid;
nc->aux = c->aux;
- nc->mntindex = c->mntindex;
nc->mchan = c->mchan;
nc->mqid = c->qid;
- mhfree(mh);
- poperror();
- if(new)
- poperror();
incref(m);
+
+ poperror();
+ mntfree(r);
return nc;
}
@@ 373,73 246,71 @@ int
mntwalk(Chan *c, char *name)
{
Mnt *m;
- Mnthdr *mh;
- int found;
-
- found = 1;
- m = mntdev(c, 0);
- mh = mhalloc();
- mh->thdr.type = Twalk;
- mh->thdr.fid = c->fid;
- strcpy(mh->thdr.name, name);
- if(waserror()){ /* BUG: can check type of error? */
- found = 0;
- goto Out;
+ Mntrpc *r;
+
+ m = mntchk(c);
+ r = mntralloc();
+ if(waserror()) {
+ mntfree(r);
+ return 0;
}
- mntxmit(m, mh);
- c->qid = mh->rhdr.qid;
+ r->request.type = Twalk;
+ r->request.fid = c->fid;
+ strncpy(r->request.name, name, NAMELEN);
+ mountrpc(m, r);
+
+ c->qid = r->reply.qid;
+
poperror();
- Out:
- mhfree(mh);
- return found;
+ mntfree(r);
+ return 1;
}
void
mntstat(Chan *c, char *dp)
{
Mnt *m;
- Mnthdr *mh;
+ Mntrpc *r;
- m = mntdev(c, 0);
- mh = mhalloc();
- if(waserror()){
- mhfree(mh);
+ m = mntchk(c);
+ r = mntralloc();
+ if(waserror()) {
+ mntfree(r);
nexterror();
}
- mh->thdr.type = Tstat;
- mh->thdr.fid = c->fid;
- mntxmit(m, mh);
- memmove(dp, mh->rhdr.stat, DIRLEN);
- dp[DIRLEN-4] = devchar[c->type];
- dp[DIRLEN-3] = 0;
- dp[DIRLEN-2] = c->dev;
- dp[DIRLEN-1] = c->dev>>8;
- mhfree(mh);
+ r->request.type = Tstat;
+ r->request.fid = c->fid;
+ mountrpc(m, r);
+
+ memmove(dp, r->reply.stat, DIRLEN);
+ mntdirfix((uchar*)dp, c);
poperror();
+ mntfree(r);
}
Chan*
mntopen(Chan *c, int omode)
{
Mnt *m;
- Mnthdr *mh;
+ Mntrpc *r;
- m = mntdev(c, 0);
- mh = mhalloc();
- if(waserror()){
- mhfree(mh);
+ m = mntchk(c);
+ r = mntralloc();
+ if(waserror()) {
+ mntfree(r);
nexterror();
}
- mh->thdr.type = Topen;
- mh->thdr.fid = c->fid;
- mh->thdr.mode = omode;
- mntxmit(m, mh);
- c->qid = mh->rhdr.qid;
- mhfree(mh);
- poperror();
+ r->request.type = Topen;
+ r->request.fid = c->fid;
+ r->request.mode = omode;
+ mountrpc(m, r);
+
+ c->qid = r->reply.qid;
c->offset = 0;
c->mode = openmode(omode);
c->flag |= COPEN;
+ poperror();
+ mntfree(r);
return c;
}
@@ 447,60 318,58 @@ void
mntcreate(Chan *c, char *name, int omode, ulong perm)
{
Mnt *m;
- Mnthdr *mh;
+ Mntrpc *r;
- m = mntdev(c, 0);
- mh = mhalloc();
- if(waserror()){
- mhfree(mh);
+ m = mntchk(c);
+ r = mntralloc();
+ if(waserror()) {
+ mntfree(r);
nexterror();
}
- mh->thdr.type = Tcreate;
- mh->thdr.fid = c->fid;
- strcpy(mh->thdr.name, name);
- mh->thdr.mode = omode;
- mh->thdr.perm = perm;
- mntxmit(m, mh);
- c->qid = mh->rhdr.qid;
- mhfree(mh);
- poperror();
+ r->request.type = Tcreate;
+ r->request.fid = c->fid;
+ r->request.mode = omode;
+ r->request.perm = perm;
+ strncpy(r->request.name, name, NAMELEN);
+ mountrpc(m, r);
+
+ c->qid = r->reply.qid;
c->flag |= COPEN;
c->mode = openmode(omode);
- c->qid = mh->rhdr.qid;
+ poperror();
+ mntfree(r);
}
void
mntclunk(Chan *c, int t)
{
Mnt *m;
- Mnthdr *mh;
- MntQ *q;
- int waserr;
-
- m = mntdev(c, 0);
- mh = mhalloc();
- mh->thdr.type = t;
- mh->thdr.fid = c->fid;
- waserr = 0;
- if(waserror()) /* gotta clean up as if there wasn't */
- waserr = 1;
- else
- mntxmit(m, mh);
- mhfree(mh);
- if(c == m->mntpt)
- m->mntpt = 0;
- 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();
- poperror();
+ Mntrpc *r, *n, *q;
+
+ m = mntchk(c);
+ r = mntralloc();
+ if(waserror()){
+ mntfree(r);
+ if(decref(m) == 0) {
+ for(q = m->queue; q; q = r) {
+ r = q->list;
+ q->flushed = 0;
+ mntfree(q);
+ }
+ m->id = 0;
+ close(m->c);
+ lock(&mntalloc);
+ m->list = mntalloc.mntfree;
+ mntalloc.mntfree = m;
+ unlock(&mntalloc);
+ }
+ return;
+ }
+
+ r->request.type = t;
+ r->request.fid = c->fid;
+ mountrpc(m, r);
+ nexterror();
}
void
@@ 509,428 378,389 @@ mntclose(Chan *c)
mntclunk(c, Tclunk);
}
-long
-mntreadwrite(Chan *c, void *vbuf, long n, int type, ulong offset)
+void
+mntremove(Chan *c)
+{
+ mntclunk(c, Tremove);
+}
+
+void
+mntwstat(Chan *c, char *dp)
{
Mnt *m;
- Mnthdr *mh;
- long nt, nr, count;
- char *buf;
-
- buf = vbuf;
- count = 0;
- m = mntdev(c, 0);
- mh = mhalloc();
- if(waserror()){
- mhfree(mh);
+ Mntrpc *r;
+
+ m = mntchk(c);
+ r = mntralloc();
+ if(waserror()) {
+ mntfree(r);
nexterror();
}
- mh->thdr.type = type;
- mh->thdr.fid = c->fid;
- Loop:
- nt = n;
- if(nt > MAXFDATA)
- nt = MAXFDATA;
- mh->thdr.offset = offset;
- mh->thdr.count = nt;
- mh->thdr.data = buf;
- mntxmit(m, mh);
- nr = mh->rhdr.count;
- offset += nr;
- count += nr;
- buf += nr;
- n -= nr;
- if(n && nr==nt)
- goto Loop;
- mhfree(mh);
+ r->request.type = Twstat;
+ r->request.fid = c->fid;
+ memmove(r->request.stat, dp, DIRLEN);
+ mountrpc(m, r);
poperror();
- return count;
+ mntfree(r);
}
long
mntread(Chan *c, void *buf, long n, ulong offset)
{
- long i;
- uchar *b;
-
- n = mntreadwrite(c, buf, n, Tread, offset);
- if(c->qid.path & CHDIR){
- b = (uchar*)buf;
- for(i=n-DIRLEN; i>=0; i-=DIRLEN){
- b[DIRLEN-4] = devchar[c->type];
- b[DIRLEN-3] = 0;
- b[DIRLEN-2] = c->dev;
- b[DIRLEN-1] = c->dev>>8;
- b += DIRLEN;
- }
- }
+ uchar *p, *e;
+
+ n = mntrdwr(Tread, c, buf, n, offset);
+ if(c->qid.path & CHDIR)
+ for(p = (uchar*)buf, e = &p[n]; p < e; p += DIRLEN)
+ mntdirfix(p, c);
+
return n;
}
long
mntwrite(Chan *c, void *buf, long n, ulong offset)
{
- return mntreadwrite(c, buf, n, Twrite, offset);
+ return mntrdwr(Twrite, c, buf, n, offset);
}
-void
-mntremove(Chan *c)
+long
+mntrdwr(int type, Chan *c, void *buf, long n, ulong offset)
{
- mntclunk(c, Tremove);
+ Mnt *m;
+ Mntrpc *r;
+ ulong cnt, nr;
+ char *uba;
+
+ m = mntchk(c);
+ uba = buf;
+ for(cnt = 0; n; n -= nr) {
+ r = mntralloc();
+ if(waserror()) {
+ mntfree(r);
+ nexterror();
+ }
+ r->request.type = type;
+ r->request.fid = c->fid;
+ r->request.offset = offset;
+ r->request.data = uba;
+ r->request.count = limit(n, MAXFDATA);
+ mountrpc(m, r);
+ nr = r->reply.count;
+ if(type == Tread)
+ memmove(uba, r->reply.data, nr);
+ poperror();
+ mntfree(r);
+ offset += nr;
+ uba += nr;
+ cnt += nr;
+ if(nr != r->request.count)
+ break;
+ }
+ return cnt;
}
void
-mntwstat(Chan *c, char *dp)
+mountrpc(Mnt *m, Mntrpc *r)
{
- Mnt *m;
- Mnthdr *mh;
-
- m = mntdev(c, 0);
- mh = mhalloc();
- if(waserror()){
- mhfree(mh);
- nexterror();
- }
- mh->thdr.type = Twstat;
- mh->thdr.fid = c->fid;
- memmove(mh->thdr.stat, dp, DIRLEN);
- mntxmit(m, mh);
- mhfree(mh);
- poperror();
-}
+ r->reply.tag = 0; /* safety check */
+ mountio(m, r);
+ if(r->reply.type == Rerror)
+ errors(r->reply.ename);
+ if(r->reply.type == Rflush)
+ errors(errstrtab[Eintr]);
-void
-mntwunlink(MntQ *q, Mnthdr *w) /* queue is locked and w is a writer */
-{
- if(w->next)
- w->next->prev = w->prev;
- if(w->prev)
- w->prev->next = w->next;
- else{
- q->writer = w->next;
- if(q->writer)
- q->writer->prev = 0;
+ if(r->reply.type != r->request.type+1) {
+ print("devmnt: mismatched reply 0x%lux T%d R%d tags req %d fls %d rep %d\n",
+ r, r->request.type, r->reply.type,
+ r->request.tag, r->flushtag, r->reply.tag);
+ errors("protocol error");
}
}
-/*
- * m->q is unlocked. Send Tflush message to flush omh->tag.
- * Cut off all errors. Caller will free omh
- */
void
-mntflush(Mnt *m, Mnthdr *omh) /* queue is unlocked */
+mountio(Mnt *m, Mntrpc *r)
{
- Mnthdr *mh;
+ int n;
+
+ lock(m);
+ r->m = m;
+ r->list = m->queue;
+ m->queue = r;
+ unlock(m);
- if(omh->thdr.type == Tflush){
- omh->flushing = 0;
+ /* Transmit a file system rpc */
+ n = convS2M(&r->request, r->rpc);
+ if(waserror()) {
+ qunlock(&m->c->wrl);
+ mntqrm(m, r);
+ nexterror();
+ }
+ qlock(&m->c->wrl);
+ if((*devtab[m->c->type].write)(m->c, r->rpc, n, 0) != n)
+ error(Eshortmsg);
+ qunlock(&m->c->wrl);
+ poperror();
+
+ if(m->mux) {
+ mntqrm(m, r);
+ mntrpcread(m, r);
return;
}
- mh = mhalloc();
- if(waserror()){
- omh->flushing = 0;
- mhfree(mh);
- return; /* no more errors please */
+ /* Gate readers onto the mount point one at a time */
+ for(;;) {
+ lock(m);
+ if(m->rip == 0)
+ break;
+ unlock(m);
+ if(waserror()) {
+ if(mntflush(m, r) == 0)
+ nexterror();
+ continue;
+ }
+ sleep(&r->r, rpcattn, r);
+ poperror();
+ if(r->done)
+ return;
}
- mh->thdr.type = Tflush;
- mh->thdr.oldtag = omh->thdr.tag;
- mntxmit(m, mh);
- omh->flushing = 0;
- mhfree(mh);
- poperror();
+ m->rip = u->p;
+ unlock(m);
+ while(r->done == 0) {
+ mntrpcread(m, r);
+ mountmux(m, r);
+ }
+ mntgate(m);
}
void
-mnterrdequeue(Mnt *m, Mnthdr *mh) /* queue is unlocked */
-{
- Mnthdr *w;
- MntQ *q;
-
- mh->flushing = 1;
- q = m->q;
- qlock(q);
- /* take self from queue if necessary */
- if(q->reader == u->p){ /* advance a writer to reader */
- w = q->writer;
- if(w){
- mntwunlink(q, w);
- q->reader = w->p;
- wakeup(&w->r);
- }else{
- q->reader = 0;
- q->writer = 0;
+mntrpcread(Mnt *m, Mntrpc *r)
+{
+ int n;
+
+ for(;;) {
+ if(waserror()) {
+ qunlock(&m->c->rdl);
+ if(mntflush(m, r) == 0) {
+ if(m->mux == 0)
+ mntgate(m);
+ nexterror();
+ }
+ continue;
}
- }else
- mntwunlink(q, mh);
- qunlock(q);
- mntflush(m, mh);
+ qlock(&m->c->rdl);
+ r->reply.type = 0;
+ r->reply.tag = 0;
+ n = (*devtab[m->c->type].read)(m->c, r->rpc, MAXRPC, 0);
+ qunlock(&m->c->rdl);
+ poperror();
+ if(n == 0)
+ continue;
+ if(convM2S(r->rpc, &r->reply, n) != 0)
+ return;
+ }
}
-int
-mntreadreply(void *a)
+void
+mntgate(Mnt *m)
{
- return ((Mnthdr *)a)->readreply;
+ Mntrpc *q;
+
+ lock(m);
+ m->rip = 0;
+ for(q = m->queue; q; q = q->list)
+ if(q->done == 0) {
+ lock(&q->r);
+ if(q->r.p) {
+ unlock(&q->r);
+ unlock(m);
+ wakeup(&q->r);
+ return;
+ }
+ unlock(&q->r);
+ }
+ unlock(m);
}
void
-mntxmit(Mnt *m, Mnthdr *mh)
-{
- ulong n;
- Mntbuf *mbw;
- Mnthdr *w, *ow;
- MntQ *q;
- int qlocked, tag, written;
-
- mh->mbr = 0;
- mbw = mballoc();
- if(waserror()){ /* 1 */
- if(mh->mbr){
- mbfree(mh->mbr);
- mh->mbr = 0;
+mountmux(Mnt *m, Mntrpc *r)
+{
+ Mntrpc **l, *q;
+ int done;
+ char *dp;
+
+ lock(m);
+ l = &m->queue;
+ for(q = *l; q; q = q->list) {
+ if(q->request.tag == r->reply.tag) {
+ if(q->flushed == 0)
+ *l = q->list;
+ q->done = 1;
+ unlock(m);
+ goto dispatch;
}
- mbfree(mbw);
- nexterror();
- }
- n = convS2M(&mh->thdr, mbw->buf);
- q = m->q;
- if(q == 0)
- error(Eshutdown);
-#ifdef BIT3
- /*
- * Bit3 and Hotrod do their own multiplexing. (Well, the file server does.)
- * The code is different enough that it's broken out separately here.
- */
- if(devchar[q->msg->type]!='3' && devchar[q->msg->type]!='H')
- goto Normal;
-
- incref(q);
- if(waserror()){ /* 2 */
- mqfree(q);
- nexterror();
- }
- if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n, 0) != n){
- print("short write in mntxmit\n");
- error(Eshortmsg);
+ if(q->flushtag == r->reply.tag) {
+ *l = q->list;
+ q->flushed = 0;
+ done = q->done;
+ q->done = 1;
+ unlock(m);
+ if(done == 0)
+ goto dispatch;
+ if(q->bfree)
+ mntfree(q);
+ return;
+ }
+ l = &q->list;
}
+ unlock(m);
+ return;
- /*
- * Read response
- */
- if(waserror()){ /* 3 */
- mntflush(m, mh);
- nexterror();
- }
- mh->mbr = mballoc();
- n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE, 0);
- poperror(); /* 3 */
- mqfree(q);
- poperror(); /* 2 */
-
- if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){
- print("format error in mntxmit\n");
- error(Ebadmsg);
+dispatch:
+ if(q != r) { /* Completed someone else */
+ dp = q->rpc;
+ q->rpc = r->rpc;
+ r->rpc = dp;
+ memmove(&q->reply, &r->reply, sizeof(Fcall));
+ wakeup(&q->r);
}
+}
- /*
- * Various checks
- */
- if(mh->rhdr.tag != mh->thdr.tag){
- print("tag mismatch %d %d\n", mh->rhdr.tag, mh->thdr.tag);
- error(Ebadmsg);
- }
- if(mh->rhdr.type == Rerror){
- if(m->mntpt)
- errors(mh->rhdr.ename);
- error(Eshutdown);
- }
- if(mh->rhdr.type != mh->thdr.type+1){
- print("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1);
- error(Ebadmsg);
- }
- if(mh->rhdr.fid != mh->thdr.fid){
- print("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type);
- error(Ebadmsg);
- }
+int
+mntflush(Mnt *m, Mntrpc *r)
+{
+ Fcall flush;
+ int n;
- /*
- * Copy out on read
- */
- if(mh->thdr.type == Tread)
- memmove(mh->thdr.data, mh->rhdr.data, mh->rhdr.count);
- mbfree(mh->mbr);
- mh->mbr = 0;
- mbfree(mbw);
- poperror(); /* 1 */
- return;
+ r->flushtag++;
+ if((r->flushtag-r->flushbase) == Flushspace)
+ r->flushtag -= Flushspace;
- Normal:
-#endif
- incref(q);
- qlock(q);
- qlocked = 1;
- if(waserror()){ /* 2 */
- if(qlocked)
- qunlock(q);
- mqfree(q);
- nexterror();
- }
- mh->readreply = 0;
- mh->active = 1;
- if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n, 0) != n){
- print("short write in mntxmit\n");
- error(Eshortmsg);
+ flush.type = Tflush;
+ flush.tag = r->flushtag;
+ flush.oldtag = r->request.tag;
+ n = convS2M(&flush, r->flush);
+
+ if(waserror()) {
+ qunlock(&m->c->wrl);
+ if(strcmp(u->error, errstrtab[Eintr]) == 0)
+ return 1;
+ mntqrm(m, r);
+ return 0;
}
- if(q->reader == 0){ /* i will read */
- q->reader = u->p;
- Read:
- USED(qlocked);
- qunlock(q);
- qlocked = 0;
- if(waserror()){ /* 3 */
- mnterrdequeue(m, mh);
- nexterror();
- }
- mh->mbr = mballoc();
- do{
- n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE, 0);
- }while(n == 0);
- poperror(); /* 3 */
- if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){
- if(1){ /* BUG? IS THIS RIGHT? IGNORE AND RETRY */
- print(" MR ");
- qlock(q);
- qlocked = 1;
- goto FreeRead;
- }else{
- mnterrdequeue(m, mh);
- error(Ebadmsg);
- }
- }
- /*
- * Response might not be mine
- */
- USED(qlocked);
- qlock(q);
- qlocked = 1;
- tag = mh->rhdr.tag;
- if(tag == mh->thdr.tag){ /* it's mine */
- if(mh->rhdr.type != Rerror)
- if(mh->rhdr.type != mh->thdr.type+1){
- print(" T%c ", devchar[m->q->msg->type]);
- goto FreeRead;
- }
- q->reader = 0;
- if(w = q->writer){ /* advance a writer to reader */
- mntwunlink(q, w);
- q->reader = w->p;
- w->readreply = 1;
- wakeup(&w->r);
- }
- mh->active = 0;
- USED(qlocked);
- qunlock(q);
- qlocked = 0;
- goto Respond;
- }
- /*
- * Hand response to correct recipient
- */
- if(tag<0 || tag>=conf.nmnthdr){
- print("unknown tag %d\n", tag);
- FreeRead:
- mbfree(mh->mbr);
- mh->mbr = 0;
- goto Read;
- }
- w = &mnthdralloc.arena[tag];
- if(w->flushing || !w->active) /* nothing to do; mntflush will clean up */
- goto FreeRead;
- if(mh->rhdr.type != Rerror)
- if(mh->rhdr.type != w->thdr.type+1){
- print(" t%c ", devchar[m->q->msg->type]);
- goto FreeRead;
+ qlock(&m->c->wrl);
+ (*devtab[m->c->type].write)(m->c, r->flush, n, 0);
+ qunlock(&m->c->wrl);
+ poperror();
+ lock(m);
+ if(!r->done)
+ r->flushed = 1;
+ unlock(m);
+ return 1;
+}
+
+Mntrpc *
+mntralloc(void)
+{
+ Mntrpc *new;
+
+ for(;;) {
+ lock(&mntalloc);
+ if(new = mntalloc.rpcfree) {
+ mntalloc.rpcfree = new->list;
+ unlock(&mntalloc);
+ new->done = 0;
+ new->bfree = 0;
+ return new;
}
- w->mbr = mh->mbr;
- mh->mbr = 0;
- memmove(&w->rhdr, &mh->rhdr, sizeof mh->rhdr);
- mntwunlink(q, w);
- w->readreply = 1;
- wakeup(&w->r);
- goto Read;
- }else{
- mh->p = u->p;
- /* put self in queue */
- mh->next = q->writer;
- mh->prev = 0;
- if(q->writer)
- q->writer->prev = mh;
- q->writer = mh;
- qunlock(q);
- qlocked = 0;
- if(waserror()){ /* interrupted sleep */
- mnterrdequeue(m, mh);
- nexterror();
+ unlock(&mntalloc);
+ resrcwait("no mount buffers");
+ }
+}
+
+void
+mntfree(Mntrpc *r)
+{
+ Mntrpc *q;
+ Mnt *m, *e;
+ int i;
+
+ r->bfree = 1;
+ if(r->flushed)
+ return;
+
+ lock(&mntalloc);
+ r->list = mntalloc.rpcfree;
+ mntalloc.rpcfree = r;
+ unlock(&mntalloc);
+}
+
+void
+mntqrm(Mnt *m, Mntrpc *r)
+{
+ Mntrpc **l, *f;
+
+ lock(m);
+ r->done = 1;
+ r->flushed = 0;
+
+ l = &m->queue;
+ for(f = *l; f; f = f->list) {
+ if(f == r) {
+ *l = r->list;
+ break;
}
- sleep(&mh->r, mntreadreply, mh);
- poperror();
- USED(qlocked);
- qlock(q);
- qlocked = 1;
- if(q->reader == u->p) /* i got promoted */
- goto Read;
- mh->active = 0;
- USED(qlocked);
- qunlock(q);
- qlocked = 0;
- goto Respond;
+ l = &f->list;
}
+ unlock(m);
+}
+
+Mnt *
+mntchk(Chan *c)
+{
+ Mnt *m;
- Respond:
- mqfree(q);
- poperror(); /* 2 */
- if(mh->rhdr.type == Rerror){
- if(m->mntpt)
- errors(mh->rhdr.ename);
+ m = &mntalloc.mntarena[c->mntindex];
+ if(m->id != c->dev)
error(Eshutdown);
- }else if(mh->rhdr.type != mh->thdr.type+1){
- print("bad type %d not %d in mntxmit\n", mh->rhdr.type, mh->thdr.type+1);
-/*XXX*/ print("chan %c %d %lux %lux\n", devchar[m->q->msg->type],
- m->q->msg->dev, m->q->msg->qid.path,
- m->q->msg->stream);
- error(Ebadmsg);
- }
- /*
- * Copy out on read
- */
- if(mh->thdr.type == Tread){
- if(mh->rhdr.count > mh->thdr.count)
- error(Ebadcnt);
- memmove(mh->thdr.data, mh->rhdr.data, mh->rhdr.count);
- }
- mbfree(mh->mbr);
- mh->mbr = 0;
- mbfree(mbw);
- USED(qlocked);
- poperror(); /* 1 */
+ return m;
+}
+
+void
+mntdirfix(uchar *dirbuf, Chan *c)
+{
+ dirbuf[DIRLEN-4] = devchar[c->type];
+ dirbuf[DIRLEN-3] = 0;
+ dirbuf[DIRLEN-2] = c->dev;
+ dirbuf[DIRLEN-1] = c->dev>>8;
+}
+
+int
+rpcattn(Mntrpc *r)
+{
+ return r->done || r->m->rip == 0;
}
void
mntdump(void)
{
- int i;
- MntQ *q;
- Mnthdr *h;
- Proc *p;
+ Mnt *me, *m;
+ Mntrpc *re, *r;
- for(i=0; i<conf.nmntdev; i++){
- q = &mntqalloc.arena[i];
- if(!q->msg)
+ me = &mntalloc.mntarena[conf.nmntdev];
+ for(m = mntalloc.mntarena; m < me; m++) {
+ if(m->ref == 0)
continue;
- p = q->reader;
- print("q rdr %d wrtr ", p? p->pid : 0);
- for(h=q->writer; h; h=h->next)
- print("(%lux %lux %d)", h, &h->r, (p=h->p)? p->pid : 0);
- print("\n");
- }
+ print("mount %d: mux %d queue %lux rip 0x%lux %d %s\n", m->id, m->mux, m->queue,
+ m->rip,
+ m->rip ? m->rip->pid : 0, m->rip ? m->rip->text : "no");
+ }
+ print("rpcfree 0x%lux\n", mntalloc.rpcfree);
+ re = &mntalloc.rpcarena[conf.nmntbuf];
+ for(r = mntalloc.rpcarena; r < re; r++)
+ print("%.8lux %.8lux T%d R%d tags req %d fls %d rep %d d %d b %d f %d\n",
+ r, r->list, r->request.type, r->reply.type,
+ r->request.tag, r->flushtag, r->reply.tag,
+ r->done, r->bfree, r->flushed);
+
}
+