Fcall request; /* Outgoing file system protocol message */
Fcall reply; /* Incoming reply */
Mnt* m; /* Mount device during rpc */
- Rendez r; /* Place to hang out */
+ Rendez* z; /* Place to hang out */
uchar* rpc; /* I/O Data buffer */
uint rpclen; /* len of buffer */
- Block *b; /* reply blocks */
- char done; /* Rpc completed */
+ Block* b; /* reply blocks */
uvlong stime; /* start time for mnt statistics */
ulong reqlen; /* request length for mnt statistics */
ulong replen; /* reply length for mnt statistics */
Mntrpc* flushed; /* message this one flushes */
+ char done; /* Rpc completed */
};
enum
Mnt* mntchk(Chan*);
void mntdirfix(uchar*, Chan*);
Mntrpc* mntflushalloc(Mntrpc*, ulong);
-void mntflushfree(Mnt*, Mntrpc*);
+Mntrpc* mntflushfree(Mnt*, Mntrpc*);
void mntfree(Mntrpc*);
void mntgate(Mnt*);
-void mntpntfree(Mnt*);
void mntqrm(Mnt*, Mntrpc*);
Mntrpc* mntralloc(Chan*, ulong);
long mntrdwr(int, Chan*, void*, long, vlong);
char Esbadstat[] = "invalid directory entry received from server";
char Enoversion[] = "version not established for mount channel";
+void (*mntstats)(int, Chan*, uvlong, ulong);
-void (*mntstats)(int, Chan*, uvlong, ulong);
static void
mntreset(void)
uchar *msg;
Mnt *m;
char *v;
+ Queue *q;
long k, l;
uvlong oo;
char buf[128];
k = strlen(f.version);
if(strncmp(f.version, v, k) != 0)
error("bad 9P version returned from server");
+ if(returnlen > 0 && returnlen < k)
+ error(Eshort);
+
+ v = nil;
+ kstrdup(&v, f.version);
+ q = qopen(10*MAXRPC, 0, nil, nil);
+ if(q == nil){
+ free(v);
+ exhausted("mount queues");
+ }
/* now build Mnt associated with this connection */
lock(&mntalloc);
else {
m = malloc(sizeof(Mnt));
if(m == 0) {
+ qfree(q);
+ free(v);
unlock(&mntalloc);
exhausted("mount devices");
}
}
m->list = mntalloc.list;
mntalloc.list = m;
- m->version = nil;
- kstrdup(&m->version, f.version);
+ m->version = v;
m->id = mntalloc.id++;
- m->q = qopen(10*MAXRPC, 0, nil, nil);
+ m->q = q;
m->msize = f.msize;
unlock(&mntalloc);
- if(returnlen > 0){
- if(returnlen < k)
- error(Eshort);
- memmove(version, f.version, k);
- }
+ if(returnlen > 0)
+ memmove(version, f.version, k); /* length was checked above */
poperror(); /* msg */
free(msg);
void
muxclose(Mnt *m)
{
- Mntrpc *q, *r;
+ Mnt *f, **l;
+ Mntrpc *r;
- for(q = m->queue; q; q = r) {
- r = q->list;
- mntfree(q);
+ while((r = m->queue) != nil){
+ m->queue = r->list;
+ mntfree(r);
}
m->id = 0;
free(m->version);
m->version = nil;
- mntpntfree(m);
-}
-
-void
-mntpntfree(Mnt *m)
-{
- Mnt *f, **l;
- Queue *q;
+ qfree(m->q);
+ m->q = nil;
lock(&mntalloc);
l = &mntalloc.list;
}
m->list = mntalloc.mntfree;
mntalloc.mntfree = m;
- q = m->q;
unlock(&mntalloc);
-
- qfree(q);
}
static void
if(m->rip == up)
mntgate(m);
if(strcmp(up->errstr, Eintr) != 0){
- mntflushfree(m, r);
+ r = mntflushfree(m, r);
+ switch(r->request.type){
+ case Tremove:
+ case Tclunk:
+ /* botch, abandon fid */
+ if(strcmp(up->errstr, Ehungup) != 0)
+ r->c->fid = 0;
+ }
nexterror();
}
r = mntflushalloc(r, m->msize);
}
lock(m);
+ r->z = &up->sleep;
r->m = m;
r->list = m->queue;
m->queue = r;
if(m->msize == 0)
panic("msize");
n = convS2M(&r->request, r->rpc, m->msize);
- if(n < 0)
- panic("bad message type in mountio");
+ if(n <= 0){
+ print("mountio: proc %s %lud: convS2M returned %d for tag %d fid %d T%d\n",
+ up->text, up->pid, n, r->request.tag, r->request.fid, r->request.type);
+ error(Emountrpc);
+ }
+
if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n)
error(Emountrpc);
r->stime = fastticks(nil);
if(m->rip == 0)
break;
unlock(m);
- sleep(&r->r, rpcattn, r);
+ sleep(r->z, rpcattn, r);
if(r->done){
poperror();
mntflushfree(m, r);
m->rip = 0;
for(q = m->queue; q; q = q->list) {
if(q->done == 0)
- if(wakeup(&q->r))
+ if(wakeup(q->z))
break;
}
unlock(m);
mountmux(Mnt *m, Mntrpc *r)
{
Mntrpc **l, *q;
+ Rendez *z;
lock(m);
l = &m->queue;
/* look for a reply to a message */
if(q->request.tag == r->reply.tag) {
*l = q->list;
+ if(mntstats != nil)
+ (*mntstats)(q->request.type,
+ m->c, q->stime,
+ q->reqlen + r->replen);
if(q != r) {
/*
* Completed someone else.
q->reply = r->reply;
q->b = r->b;
r->b = nil;
- }
- q->done = 1;
+ z = q->z;
+ } else
+ z = nil;
+ q->done = 1; /* hands off */
+ if(z != nil)
+ wakeup(z);
unlock(m);
- if(mntstats != nil)
- (*mntstats)(q->request.type,
- m->c, q->stime,
- q->reqlen + r->replen);
- if(q != r)
- wakeup(&q->r);
return;
}
l = &q->list;
* flush and the original message from the unanswered
* request queue. Mark the original message as done
* and if it hasn't been answered set the reply to to
- * Rflush.
+ * Rflush. Return the original rpc.
*/
-void
+Mntrpc*
mntflushfree(Mnt *m, Mntrpc *r)
{
Mntrpc *fr;
r->reply.type = Rflush;
mntqrm(m, r);
}
- if(fr)
- mntfree(r);
+ if(fr == nil)
+ break;
+ mntfree(r);
r = fr;
}
+ return r;
}
int
/* This routine is mostly vestiges of prior lives; now it's just sanity checking */
if(c->mchan == nil)
- panic("mntchk 1: nil mchan c %s\n", chanpath(c));
+ panic("mntchk 1: nil mchan c %s", chanpath(c));
m = c->mchan->mux;