check everything in so i can move to linux and valgrind.

This commit is contained in:
rsc 2003-12-09 06:06:07 +00:00
parent 4e6ed88aa8
commit ceb0477083
5 changed files with 491 additions and 106 deletions

View file

@ -70,13 +70,14 @@ char adir[40];
int isunix; int isunix;
Queue *outq; Queue *outq;
Queue *inq; Queue *inq;
int verbose;
void *gethash(Hash**, uint); void *gethash(Hash**, uint);
int puthash(Hash**, uint, void*); int puthash(Hash**, uint, void*);
int delhash(Hash**, uint, void*); int delhash(Hash**, uint, void*);
Msg *mread9p(int); Msg *mread9p(Ioproc*, int);
int mwrite9p(int, Msg*); int mwrite9p(Ioproc*, int, uchar*);
uchar *read9ppkt(int); uchar *read9ppkt(Ioproc*, int);
int write9ppkt(int, uchar*); int write9ppkt(int, uchar*);
Msg *msgnew(void); Msg *msgnew(void);
void msgput(Msg*); void msgput(Msg*);
@ -85,29 +86,50 @@ Fid *fidnew(int);
void fidput(Fid*); void fidput(Fid*);
void *emalloc(int); void *emalloc(int);
void *erealloc(void*, int); void *erealloc(void*, int);
Queue *qalloc(void);
int sendq(Queue*, void*); int sendq(Queue*, void*);
void *recvq(Queue*); void *recvq(Queue*);
void selectthread(void*); void selectthread(void*);
void connthread(void*); void connthread(void*);
void connoutthread(void*);
void listenthread(void*); void listenthread(void*);
void outputthread(void*);
void inputthread(void*);
void rewritehdr(Fcall*, uchar*); void rewritehdr(Fcall*, uchar*);
int tlisten(char*, char*); int tlisten(char*, char*);
int taccept(int, char*); int taccept(int, char*);
int iolisten(Ioproc*, char*, char*);
int ioaccept(Ioproc*, int, char*);
void void
usage(void) usage(void)
{ {
fprint(2, "usage: 9pserve [-u] address\n"); fprint(2, "usage: 9pserve [-s service] [-u] address\n");
fprint(2, "\treads/writes 9P messages on stdin/stdout\n"); fprint(2, "\treads/writes 9P messages on stdin/stdout\n");
exits("usage"); exits("usage");
} }
uchar vbuf[128];
void void
threadmain(int argc, char **argv) threadmain(int argc, char **argv)
{ {
char *file;
int n;
Fcall f;
ARGBEGIN{ ARGBEGIN{
default: default:
usage(); usage();
case 'v':
verbose++;
break;
case 's':
close(0);
if(open(file=EARGF(usage()), ORDWR) != 0)
sysfatal("open %s: %r", file);
dup(0, 1);
break;
case 'u': case 'u':
isunix = 1; isunix = 1;
break; break;
@ -115,45 +137,68 @@ threadmain(int argc, char **argv)
if(argc != 1) if(argc != 1)
usage(); usage();
addr = argv[0];
if((afd = announce(addr, adir)) < 0) if((afd = announce(addr, adir)) < 0)
sysfatal("announce %s: %r", addr); sysfatal("announce %s: %r", addr);
threadcreateidle(selectthread, nil, STACK); fmtinstall('D', dirfmt);
fmtinstall('M', dirmodefmt);
fmtinstall('F', fcallfmt);
fmtinstall('H', encodefmt);
outq = qalloc();
inq = qalloc();
// threadcreateidle(selectthread, nil, STACK);
threadcreate(inputthread, nil, STACK);
threadcreate(outputthread, nil, STACK);
f.type = Tversion;
f.version = "9P2000";
f.msize = 8192;
f.tag = NOTAG;
n = convS2M(&f, vbuf, sizeof vbuf);
if(verbose > 1) fprint(2, "* <- %F\n", &f);
write(1, vbuf, n);
n = read9pmsg(0, vbuf, sizeof vbuf);
if(convM2S(vbuf, n, &f) != n)
sysfatal("convM2S failure");
if(verbose > 1) fprint(2, "* -> %F\n", &f);
threadcreate(listenthread, nil, STACK);
} }
void void
listenthread(void *arg) listenthread(void *arg)
{ {
Conn *c; Conn *c;
Ioproc *io;
io = ioproc();
USED(arg); USED(arg);
for(;;){ for(;;){
c = malloc(sizeof(Conn)); c = emalloc(sizeof(Conn));
if(c == nil){ c->inc = chancreate(sizeof(void*), 0);
fprint(2, "out of memory\n"); c->internal = chancreate(sizeof(void*), 0);
sleep(60*1000); c->inq = qalloc();
continue; c->outq = qalloc();
} c->fd = iolisten(io, adir, c->dir);
c->fd = tlisten(adir, c->dir);
if(c->fd < 0){ if(c->fd < 0){
fprint(2, "listen: %r\n"); if(verbose) fprint(2, "listen: %r\n");
close(afd); close(afd);
free(c); free(c);
return; return;
} }
if(verbose) fprint(2, "incoming call on %s\n", c->dir);
threadcreate(connthread, c, STACK); threadcreate(connthread, c, STACK);
} }
} }
void void
err(Msg *m, char *ename) sendmsg(Msg *m)
{ {
int n, nn; int n, nn;
m->rx.type = Rerror;
m->rx.ename = ename;
m->rx.tag = m->ctag;
n = sizeS2M(&m->rx); n = sizeS2M(&m->rx);
m->rpkt = emalloc(n); m->rpkt = emalloc(n);
nn = convS2M(&m->rx, m->rpkt, n); nn = convS2M(&m->rx, m->rpkt, n);
@ -162,6 +207,28 @@ err(Msg *m, char *ename)
sendq(m->c->outq, m); sendq(m->c->outq, m);
} }
void
sendomsg(Msg *m)
{
int n, nn;
n = sizeS2M(&m->tx);
m->tpkt = emalloc(n);
nn = convS2M(&m->tx, m->tpkt, n);
if(nn != n)
sysfatal("sizeS2M + convS2M disagree");
sendq(outq, m);
}
void
err(Msg *m, char *ename)
{
m->rx.type = Rerror;
m->rx.ename = ename;
m->rx.tag = m->tx.tag;
sendmsg(m);
}
void void
connthread(void *arg) connthread(void *arg)
{ {
@ -170,31 +237,54 @@ connthread(void *arg)
Hash *h; Hash *h;
Msg *m, *om; Msg *m, *om;
Fid *f; Fid *f;
Ioproc *io;
c = arg; c = arg;
fd = taccept(c->fd, c->dir); io = ioproc();
fd = ioaccept(io, c->fd, c->dir);
if(fd < 0){ if(fd < 0){
fprint(2, "accept %s: %r\n", c->dir); if(verbose) fprint(2, "accept %s: %r\n", c->dir);
goto out; goto out;
} }
close(c->fd); close(c->fd);
c->fd = fd; c->fd = fd;
while((m = mread9p(c->fd)) != nil){ threadcreate(connoutthread, c, STACK);
while((m = mread9p(io, c->fd)) != nil){
if(verbose > 1) fprint(2, "%s -> %F\n", c->dir, &m->tx);
m->c = c; m->c = c;
m->ctag = m->tx.tag;
c->nmsg++; c->nmsg++;
if(puthash(c->tag, m->tx.tag, m) < 0){ if(puthash(c->tag, m->tx.tag, m) < 0){
err(m, "duplicate tag"); err(m, "duplicate tag");
continue; continue;
} }
m->ref++;
switch(m->tx.type){ switch(m->tx.type){
case Tversion:
m->rx.tag = m->tx.tag;
m->rx.msize = m->tx.msize;
if(m->rx.msize > 8192)
m->rx.msize = 8192;
m->rx.version = "9P2000";
m->rx.type = Rversion;
sendmsg(m);
continue;
case Tflush: case Tflush:
if((m->oldm = gethash(c->tag, m->tx.oldtag)) == nil){ if((m->oldm = gethash(c->tag, m->tx.oldtag)) == nil){
m->rx.tag = Rflush; m->rx.tag = m->tx.tag;
sendq(c->outq, m); m->rx.type = Rflush;
sendmsg(m);
continue; continue;
} }
m->oldm->ref++;
break; break;
case Tattach: case Tattach:
m->afid = nil;
if(m->tx.afid != NOFID
&& (m->afid = gethash(c->fid, m->tx.afid)) == nil){
err(m, "unknown fid");
continue;
}
m->fid = fidnew(m->tx.fid); m->fid = fidnew(m->tx.fid);
if(puthash(c->fid, m->tx.fid, m->fid) < 0){ if(puthash(c->fid, m->tx.fid, m->fid) < 0){
err(m, "duplicate fid"); err(m, "duplicate fid");
@ -207,6 +297,7 @@ connthread(void *arg)
err(m, "unknown fid"); err(m, "unknown fid");
continue; continue;
} }
m->fid->ref++;
if(m->tx.newfid == m->tx.fid){ if(m->tx.newfid == m->tx.fid){
m->fid->ref++; m->fid->ref++;
m->newfid = m->fid; m->newfid = m->fid;
@ -220,21 +311,19 @@ connthread(void *arg)
} }
break; break;
case Tauth: case Tauth:
if((m->afid = gethash(c->fid, m->tx.afid)) == nil){ m->afid = fidnew(m->tx.afid);
err(m, "unknown fid"); if(puthash(c->fid, m->tx.afid, m->afid) < 0){
continue;
}
m->fid = fidnew(m->tx.fid);
if(puthash(c->fid, m->tx.fid, m->fid) < 0){
err(m, "duplicate fid"); err(m, "duplicate fid");
continue; continue;
} }
m->fid->ref++; m->afid->ref++;
break; break;
case Tcreate:
case Topen: case Topen:
case Tclunk: case Tclunk:
case Tread: case Tread:
case Twrite: case Twrite:
case Tremove:
case Tstat: case Tstat:
case Twstat: case Twstat:
if((m->fid = gethash(c->fid, m->tx.fid)) == nil){ if((m->fid = gethash(c->fid, m->tx.fid)) == nil){
@ -257,7 +346,7 @@ connthread(void *arg)
m->tx.afid = m->afid->fid; m->tx.afid = m->afid->fid;
if(m->oldm) if(m->oldm)
m->tx.oldtag = m->oldm->tag; m->tx.oldtag = m->oldm->tag;
rewritehdr(&m->tx, m->tpkt); /* reference passes to outq */
sendq(outq, m); sendq(outq, m);
while(c->nmsg >= MAXMSG){ while(c->nmsg >= MAXMSG){
c->inputstalled = 1; c->inputstalled = 1;
@ -265,6 +354,8 @@ connthread(void *arg)
} }
} }
if(verbose) fprint(2, "%s eof\n", c->dir);
/* flush all outstanding messages */ /* flush all outstanding messages */
for(i=0; i<NHASH; i++){ for(i=0; i<NHASH; i++){
for(h=c->tag[i]; h; h=h->next){ for(h=c->tag[i]; h; h=h->next){
@ -277,8 +368,10 @@ connthread(void *arg)
m->tx.oldtag = om->tag; m->tx.oldtag = om->tag;
m->oldm = om; m->oldm = om;
om->ref++; om->ref++;
sendq(outq, m); m->ref++; /* for outq */
sendomsg(m);
recvp(c->internal); recvp(c->internal);
msgput(m);
} }
} }
@ -294,8 +387,10 @@ connthread(void *arg)
m->tx.fid = f->fid; m->tx.fid = f->fid;
m->fid = f; m->fid = f;
f->ref++; f->ref++;
sendq(outq, m); m->ref++;
sendomsg(m);
recvp(c->internal); recvp(c->internal);
msgput(m);
} }
} }
@ -312,57 +407,72 @@ connoutthread(void *arg)
int err; int err;
Conn *c; Conn *c;
Msg *m, *om; Msg *m, *om;
Ioproc *io;
c = arg; c = arg;
io = ioproc();
while((m = recvq(c->outq)) != nil){ while((m = recvq(c->outq)) != nil){
err = m->tx.type+1 != m->rx.type; err = m->tx.type+1 != m->rx.type;
switch(m->tx.type){ switch(m->tx.type){
case Tflush: case Tflush:
om = m->oldm; om = m->oldm;
if(om)
if(delhash(om->c->tag, om->ctag, om) == 0) if(delhash(om->c->tag, om->ctag, om) == 0)
msgput(om); msgput(om);
break; break;
case Tclunk: case Tclunk:
case Tremove:
if(m->fid)
if(delhash(m->c->fid, m->fid->cfid, m->fid) == 0) if(delhash(m->c->fid, m->fid->cfid, m->fid) == 0)
fidput(m->fid); fidput(m->fid);
break; break;
case Tauth: case Tauth:
if(err) if(err && m->afid){
if(delhash(m->c->fid, m->afid->cfid, m->fid) == 0) fprint(2, "auth error\n");
if(delhash(m->c->fid, m->afid->cfid, m->afid) == 0)
fidput(m->fid); fidput(m->fid);
}
break;
case Tattach: case Tattach:
if(err) if(err && m->fid)
if(delhash(m->c->fid, m->fid->cfid, m->fid) == 0) if(delhash(m->c->fid, m->fid->cfid, m->fid) == 0)
fidput(m->fid); fidput(m->fid);
break; break;
case Twalk: case Twalk:
if(err && m->tx.fid != m->tx.newfid) if(err && m->tx.fid != m->tx.newfid && m->newfid)
if(delhash(m->c->fid, m->newfid->cfid, m->newfid) == 0) if(delhash(m->c->fid, m->newfid->cfid, m->newfid) == 0)
fidput(m->newfid); fidput(m->newfid);
break; break;
} }
if(mwrite9p(c->fd, m) < 0)
fprint(2, "write error: %r\n");
if(delhash(m->c->tag, m->ctag, m) == 0) if(delhash(m->c->tag, m->ctag, m) == 0)
msgput(m); msgput(m);
if(verbose > 1) fprint(2, "%s <- %F\n", c->dir, &m->rx);
rewritehdr(&m->rx, m->rpkt);
if(mwrite9p(io, c->fd, m->rpkt) < 0)
if(verbose) fprint(2, "write error: %r\n");
msgput(m); msgput(m);
if(c->inputstalled && c->nmsg < MAXMSG) if(c->inputstalled && c->nmsg < MAXMSG)
nbsendp(c->inc, 0); nbsendp(c->inc, 0);
} }
closeioproc(io);
} }
void void
outputthread(void *arg) outputthread(void *arg)
{ {
Msg *m; Msg *m;
Ioproc *io;
USED(arg); USED(arg);
io = ioproc();
while((m = recvq(outq)) != nil){ while((m = recvq(outq)) != nil){
if(mwrite9p(1, m) < 0) if(verbose > 1) fprint(2, "* <- %F\n", &m->tx);
rewritehdr(&m->tx, m->tpkt);
if(mwrite9p(io, 1, m->tpkt) < 0)
sysfatal("output error: %r"); sysfatal("output error: %r");
msgput(m); msgput(m);
} }
closeioproc(io);
} }
void void
@ -371,19 +481,22 @@ inputthread(void *arg)
uchar *pkt; uchar *pkt;
int n, nn, tag; int n, nn, tag;
Msg *m; Msg *m;
Ioproc *io;
while((pkt = read9ppkt(0)) != nil){ io = ioproc();
USED(arg);
while((pkt = read9ppkt(io, 0)) != nil){
n = GBIT32(pkt); n = GBIT32(pkt);
if(n < 7){ if(n < 7){
fprint(2, "short 9P packet\n"); fprint(2, "short 9P packet from server\n");
free(pkt); free(pkt);
continue; continue;
} }
if(verbose > 2) fprint(2, "read %.*H\n", n, pkt);
tag = GBIT16(pkt+5); tag = GBIT16(pkt+5);
if((m = msgget(tag)) == nil){ if((m = msgget(tag)) == nil){
fprint(2, "unexpected 9P response tag %d\n", tag); fprint(2, "unexpected 9P response tag %d\n", tag);
free(pkt); free(pkt);
msgput(m);
continue; continue;
} }
if((nn = convM2S(pkt, n, &m->rx)) != n){ if((nn = convM2S(pkt, n, &m->rx)) != n){
@ -392,11 +505,15 @@ inputthread(void *arg)
msgput(m); msgput(m);
continue; continue;
} }
if(verbose > 1) fprint(2, "* -> %F\n", &m->rx);
m->rpkt = pkt; m->rpkt = pkt;
m->rx.tag = m->ctag; m->rx.tag = m->ctag;
rewritehdr(&m->rx, m->rpkt); if(m->internal)
sendp(m->c->internal, 0);
else
sendq(m->c->outq, m); sendq(m->c->outq, m);
} }
closeioproc(io);
} }
void* void*
@ -417,8 +534,10 @@ delhash(Hash **ht, uint n, void *v)
for(l=&ht[n%NHASH]; h=*l; l=&h->next) for(l=&ht[n%NHASH]; h=*l; l=&h->next)
if(h->n == n){ if(h->n == n){
if(h->v != v) if(h->v != v){
fprint(2, "hash error\n"); if(verbose) fprint(2, "delhash %d got %p want %p\n", n, h->v, v);
return -1;
}
*l = h->next; *l = h->next;
free(h); free(h);
return 0; return 0;
@ -451,13 +570,14 @@ fidnew(int cfid)
Fid *f; Fid *f;
if(freefid == nil){ if(freefid == nil){
fidtab = erealloc(fidtab, nfidtab*sizeof(fidtab[0])); fidtab = erealloc(fidtab, (nfidtab+1)*sizeof(fidtab[0]));
fidtab[nfidtab] = emalloc(sizeof(Fid)); fidtab[nfidtab] = emalloc(sizeof(Fid));
freefid = fidtab[nfidtab++]; freefid = fidtab[nfidtab];
freefid->fid = nfidtab++;
} }
f = freefid; f = freefid;
freefid = f->next; freefid = f->next;
f->cfid = f->cfid; f->cfid = cfid;
f->ref = 1; f->ref = 1;
return f; return f;
} }
@ -465,6 +585,8 @@ fidnew(int cfid)
void void
fidput(Fid *f) fidput(Fid *f)
{ {
if(f == nil)
return;
assert(f->ref > 0); assert(f->ref > 0);
if(--f->ref > 0) if(--f->ref > 0)
return; return;
@ -483,9 +605,10 @@ msgnew(void)
Msg *m; Msg *m;
if(freemsg == nil){ if(freemsg == nil){
msgtab = erealloc(msgtab, nmsgtab*sizeof(msgtab[0])); msgtab = erealloc(msgtab, (nmsgtab+1)*sizeof(msgtab[0]));
msgtab[nmsgtab] = emalloc(sizeof(Msg)); msgtab[nmsgtab] = emalloc(sizeof(Msg));
freemsg = msgtab[nmsgtab++]; freemsg = msgtab[nmsgtab];
freemsg->tag = nmsgtab++;
} }
m = freemsg; m = freemsg;
freemsg = m->next; freemsg = m->next;
@ -496,21 +619,51 @@ msgnew(void)
void void
msgput(Msg *m) msgput(Msg *m)
{ {
if(verbose > 2) fprint(2, "msgput tag %d/%d ref %d\n", m->tag, m->ctag, m->ref);
assert(m->ref > 0); assert(m->ref > 0);
if(--m->ref > 0) if(--m->ref > 0)
return; return;
m->c->nmsg--;
m->c = nil;
fidput(m->fid);
fidput(m->afid);
fidput(m->newfid);
free(m->tpkt);
free(m->rpkt);
m->fid = nil;
m->afid = nil;
m->newfid = nil;
m->tpkt = nil;
m->rpkt = nil;
m->next = freemsg; m->next = freemsg;
freemsg = m; freemsg = m;
} }
Msg*
msgget(int n)
{
Msg *m;
if(n < 0 || n >= nmsgtab)
return nil;
m = msgtab[n];
if(m->ref == 0)
return nil;
m->ref++;
return m;
}
void* void*
emalloc(int n) emalloc(int n)
{ {
void *v; void *v;
v = mallocz(n, 1); v = mallocz(n, 1);
if(v == nil) if(v == nil){
sysfatal("out of memory"); abort();
sysfatal("out of memory allocating %d", n);
}
return v; return v;
} }
@ -518,8 +671,10 @@ void*
erealloc(void *v, int n) erealloc(void *v, int n)
{ {
v = realloc(v, n); v = realloc(v, n);
if(v == nil) if(v == nil){
sysfatal("out of memory"); abort();
sysfatal("out of memory reallocating %d", n);
}
return v; return v;
} }
@ -595,3 +750,197 @@ recvq(Queue *q)
free(e); free(e);
return p; return p;
} }
uchar*
read9ppkt(Ioproc *io, int fd)
{
uchar buf[4], *pkt;
int n, nn;
n = ioreadn(io, fd, buf, 4);
if(n != 4)
return nil;
n = GBIT32(buf);
pkt = emalloc(n);
PBIT32(pkt, n);
nn = ioreadn(io, fd, pkt+4, n-4);
if(nn != n-4){
free(pkt);
return nil;
}
return pkt;
}
Msg*
mread9p(Ioproc *io, int fd)
{
int n, nn;
uchar *pkt;
Msg *m;
if((pkt = read9ppkt(io, fd)) == nil)
return nil;
m = msgnew();
m->tpkt = pkt;
n = GBIT32(pkt);
nn = convM2S(pkt, n, &m->tx);
if(nn != n){
fprint(2, "read bad packet from %d\n", fd);
return nil;
}
return m;
}
int
mwrite9p(Ioproc *io, int fd, uchar *pkt)
{
int n;
n = GBIT32(pkt);
if(verbose > 2) fprint(2, "write %d %d %.*H\n", fd, n, n, pkt);
if(iowrite(io, fd, pkt, n) != n){
fprint(2, "write error: %r\n");
return -1;
}
return 0;
}
void
restring(uchar *pkt, int pn, char *s)
{
int n;
if(s < (char*)pkt || s >= (char*)pkt+pn)
return;
n = strlen(s);
memmove(s+1, s, n);
PBIT16((uchar*)s-1, n);
}
void
rewritehdr(Fcall *f, uchar *pkt)
{
int i, n;
n = GBIT32(pkt);
PBIT16(pkt+5, f->tag);
switch(f->type){
case Tversion:
case Rversion:
restring(pkt, n, f->version);
break;
case Tauth:
PBIT32(pkt+7, f->afid);
restring(pkt, n, f->uname);
restring(pkt, n, f->aname);
break;
case Tflush:
PBIT16(pkt+7, f->oldtag);
break;
case Tattach:
restring(pkt, n, f->uname);
restring(pkt, n, f->aname);
PBIT32(pkt+7, f->fid);
PBIT32(pkt+11, f->afid);
break;
case Twalk:
PBIT32(pkt+7, f->fid);
PBIT32(pkt+11, f->newfid);
for(i=0; i<f->nwname; i++)
restring(pkt, n, f->wname[i]);
break;
case Tcreate:
restring(pkt, n, f->name);
/* fall through */
case Topen:
case Tread:
case Twrite:
case Tclunk:
case Tremove:
case Tstat:
case Twstat:
PBIT32(pkt+7, f->fid);
break;
case Rerror:
restring(pkt, n, f->ename);
break;
}
}
#ifdef _LIB9_H_
/* unix select-based polling */
Ioproc*
ioproc(void)
{
return nil;
}
long
ioread(Ioproc *io, int fd, void *v, long n)
{
USED(io);
xxx;
}
long
iowrite(Ioproc *io, int fd, void *v, long n)
{
USED(io);
xxx;
}
int
iolisten(Ioproc *io, char *a, char *b)
{
USED(io);
xxx;
}
int
ioaccept(Ioproc *io, int fd, char *dir)
{
USED(io);
xxx;
}
#else
/* real plan 9 io procs */
static long
_iolisten(va_list *arg)
{
char *a, *b;
a = va_arg(*arg, char*);
b = va_arg(*arg, char*);
return listen(a, b);
}
int
iolisten(Ioproc *io, char *a, char *b)
{
return iocall(io, _iolisten, a, b);
}
static long
_ioaccept(va_list *arg)
{
int fd;
char *dir;
fd = va_arg(*arg, int);
dir = va_arg(*arg, char*);
return accept(fd, dir);
}
int
ioaccept(Ioproc *io, int fd, char *dir)
{
return iocall(io, _ioaccept, fd, dir);
}
#endif

View file

@ -22,6 +22,10 @@ fsinit(int fd)
{ {
Fsys *fs; Fsys *fs;
fmtinstall('F', fcallfmt);
fmtinstall('D', dirfmt);
fmtinstall('M', dirmodefmt);
fs = mallocz(sizeof(Fsys), 1); fs = mallocz(sizeof(Fsys), 1);
if(fs == nil) if(fs == nil)
return nil; return nil;
@ -141,8 +145,12 @@ fsrpc(Fsys *fs, Fcall *tx, Fcall *rx, void **freep)
n = sizeS2M(tx); n = sizeS2M(tx);
tpkt = malloc(n); tpkt = malloc(n);
fprint(2, "tpkt %p\n", tpkt);
if(freep)
*freep = nil;
if(tpkt == nil) if(tpkt == nil)
return -1; return -1;
fprint(2, "<- %F\n", tx);
nn = convS2M(tx, tpkt, n); nn = convS2M(tx, tpkt, n);
if(nn != n){ if(nn != n){
free(tpkt); free(tpkt);
@ -151,7 +159,9 @@ fsrpc(Fsys *fs, Fcall *tx, Fcall *rx, void **freep)
return -1; return -1;
} }
rpkt = muxrpc(&fs->mux, tpkt); rpkt = muxrpc(&fs->mux, tpkt);
fprint(2, "tpkt %p\n", tpkt);
free(tpkt); free(tpkt);
fprint(2, "tpkt freed\n");
if(rpkt == nil) if(rpkt == nil)
return -1; return -1;
n = GBIT32((uchar*)rpkt); n = GBIT32((uchar*)rpkt);
@ -162,6 +172,7 @@ fsrpc(Fsys *fs, Fcall *tx, Fcall *rx, void **freep)
fprint(2, "%r\n"); fprint(2, "%r\n");
return -1; return -1;
} }
fprint(2, "-> %F\n", rx);
if(rx->type == Rerror){ if(rx->type == Rerror){
werrstr("%s", rx->ename); werrstr("%s", rx->ename);
free(rpkt); free(rpkt);
@ -261,7 +272,7 @@ _fsrecv(Mux *mux)
fprint(2, "libfs out of memory reading 9p packet; here comes trouble\n"); fprint(2, "libfs out of memory reading 9p packet; here comes trouble\n");
return nil; return nil;
} }
PBIT32(buf, n); PBIT32(pkt, n);
if(readn(fs->fd, pkt+4, n-4) != n-4){ if(readn(fs->fd, pkt+4, n-4) != n-4){
free(pkt); free(pkt);
return nil; return nil;

View file

@ -14,6 +14,7 @@ fspread(Fid *fid, void *buf, long n, vlong offset)
void *freep; void *freep;
tx.type = Tread; tx.type = Tread;
tx.fid = fid->fid;
if(offset == -1){ if(offset == -1){
qlock(&fid->lk); qlock(&fid->lk);
tx.offset = fid->offset; tx.offset = fid->offset;
@ -32,7 +33,7 @@ fspread(Fid *fid, void *buf, long n, vlong offset)
memmove(buf, rx.data, rx.count); memmove(buf, rx.data, rx.count);
if(offset == -1){ if(offset == -1){
qlock(&fid->lk); qlock(&fid->lk);
tx.offset += n; fid->offset += rx.count;
qunlock(&fid->lk); qunlock(&fid->lk);
} }
} }

View file

@ -8,39 +8,39 @@
#include "fsimpl.h" #include "fsimpl.h"
long long
fspwrite(Fid *fd, void *buf, long n, vlong offset) fspwrite(Fid *fid, void *buf, long n, vlong offset)
{ {
Fcall tx, rx; Fcall tx, rx;
void *freep; void *freep;
tx.type = Tread; tx.type = Twrite;
tx.fid = fid->fid;
if(offset == -1){ if(offset == -1){
qlock(&fd->lk); qlock(&fid->lk);
tx.offset = fd->offset; tx.offset = fid->offset;
fd->offset += n; qunlock(&fid->lk);
qunlock(&fd->lk);
}else }else
tx.offset = offset; tx.offset = offset;
tx.count = n; tx.count = n;
tx.data = buf; tx.data = buf;
fsrpc(fd->fs, &tx, &rx, &freep); fsrpc(fid->fs, &tx, &rx, &freep);
if(rx.type == Rerror){ if(rx.type == Rerror){
if(offset == -1){
qlock(&fd->lk);
fd->offset -= n;
qunlock(&fd->lk);
}
werrstr("%s", rx.ename); werrstr("%s", rx.ename);
free(freep); free(freep);
return -1; return -1;
} }
if(offset == -1 && rx.count){
qlock(&fid->lk);
fid->offset += rx.count;
qunlock(&fid->lk);
}
free(freep); free(freep);
return rx.count; return rx.count;
} }
long long
fswrite(Fid *fd, void *buf, long n) fswrite(Fid *fid, void *buf, long n)
{ {
return fspwrite(fd, buf, n, -1); return fspwrite(fid, buf, n, -1);
} }

View file

@ -27,7 +27,7 @@ muxinit(Mux *mux)
void* void*
muxrpc(Mux *mux, void *tx) muxrpc(Mux *mux, void *tx)
{ {
uint tag; int tag;
Muxrpc *r, *r2; Muxrpc *r, *r2;
void *p; void *p;
@ -38,17 +38,13 @@ muxrpc(Mux *mux, void *tx)
r->r.l = &mux->lk; r->r.l = &mux->lk;
/* assign the tag */ /* assign the tag */
qlock(&mux->lk);
tag = gettag(mux, r); tag = gettag(mux, r);
if(mux->settag(mux, tx, tag) < 0){ qunlock(&mux->lk);
if(tag < 0 || mux->settag(mux, tx, tag) < 0 || _muxsend(mux, tx) < 0){
qlock(&mux->lk);
puttag(mux, r); puttag(mux, r);
free(r); qunlock(&mux->lk);
return nil;
}
/* send the packet */
if(_muxsend(mux, tx) < 0){
puttag(mux, r);
free(r);
return nil; return nil;
} }
@ -95,7 +91,6 @@ muxrpc(Mux *mux, void *tx)
} }
p = r->p; p = r->p;
puttag(mux, r); puttag(mux, r);
free(r);
qunlock(&mux->lk); qunlock(&mux->lk);
return p; return p;
} }
@ -121,32 +116,61 @@ dequeue(Mux *mux, Muxrpc *r)
static int static int
gettag(Mux *mux, Muxrpc *r) gettag(Mux *mux, Muxrpc *r)
{ {
int i; int i, mw;
Muxrpc **w;
Again: for(;;){
while(mux->nwait == mux->mwait) /* wait for a free tag */
while(mux->nwait == mux->mwait){
if(mux->mwait < mux->maxtag-mux->mintag){
mw = mux->mwait;
if(mw == 0)
mw = 1;
else
mw <<= 1;
w = realloc(mux->wait, mw*sizeof(w[0]));
if(w == nil)
return -1;
mux->wait = w;
mux->freetag = mux->mwait;
mux->mwait = mw;
break;
}
rsleep(&mux->tagrend); rsleep(&mux->tagrend);
}
i=mux->freetag; i=mux->freetag;
if(mux->wait[i] == 0) if(mux->wait[i] == 0)
goto Found; goto Found;
for(i=0; i<mux->mwait; i++) for(; i<mux->mwait; i++)
if(mux->wait[i] == 0){ if(mux->wait[i] == 0)
goto Found;
for(i=0; i<mux->freetag; i++)
if(mux->wait[i] == 0)
goto Found;
/* should not fall out of while without free tag */
fprint(2, "libfs: nwait botch\n");
abort();
}
Found: Found:
mux->nwait++; mux->nwait++;
mux->wait[i] = r; mux->wait[i] = r;
r->tag = i; r->tag = i+mux->mintag;
return i; return i;
} }
fprint(2, "libfs: nwait botch\n");
goto Again;
}
static void static void
puttag(Mux *mux, Muxrpc *r) puttag(Mux *mux, Muxrpc *r)
{ {
assert(mux->wait[r->tag] == r); int i;
mux->wait[r->tag] = nil;
i = r->tag - mux->mintag;
assert(mux->wait[i] == r);
mux->wait[i] = nil;
mux->nwait--; mux->nwait--;
mux->freetag = r->tag; mux->freetag = i;
rwakeup(&mux->tagrend); rwakeup(&mux->tagrend);
fprint(2, "free %p\n", r);
free(r);
} }