# HG changeset patch # User Francisco J Ballesteros # Date 1322734753 -3600 # Node ID f23a243e5c73e63b226208799180a0aa6cb95242 # Parent 006370f4d855372860acedfb06f1d0b65e67634a ix: ix R=nixiedev, noah.evans CC=nix-dev http://codereview.appspot.com/5451063 Committer: Noah Evans diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/ch.c --- a/sys/src/cmd/ix/ch.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/ch.c Thu Dec 01 11:19:13 2011 +0100 @@ -6,7 +6,6 @@ * Messages must be received from returned channels by clients. * (NB: where channel has type Ch*) * - * * Termination: * chwproc is a client for a tses (writer) * cmuxproc is a client for a tses (reader) @@ -37,24 +36,29 @@ * drainch * eof: * send last (null msg ok) + * + * The client is not required to read from the channel at all times, + * the mux queues messages and sends them only when the client is + * ready to receive them. */ #include #include #include -#include #include /* *BIG* macros */ #include "conf.h" #include "msg.h" #include "ch.h" #include "dbg.h" -typedef struct Chmsg Chmsg; +enum +{ + /* cmuxproc() alts */ + Amkc = 0, + Aendc, + Asrc, + Afixedents, /* first Ch rc in alts */ +}; -struct Chmsg -{ - Msg *m; - int last; -}; static void cmdump(Cmux *cm) @@ -136,7 +140,6 @@ chanfree(ch->dc); } - /* * A channel might have been terminated for writing, yet the * peer may be still busy processing outgoing requests. @@ -149,7 +152,7 @@ Msg *m; uchar *buf; - m = emalloc(sizeof *m); + m = mallocz(sizeof *m, 1); buf = msgpushhdr(m, BIT16SZ); PBIT16(buf, CFend|ch->id); sendp(ch->cm->swc, m); @@ -167,9 +170,10 @@ ch->rclosed = ch->wclosed = ch->flushing = 0; sendul(ch->dc, 1); /* resurrect chwproc */ ch->dead = 0; + assert(cm->alts[Afixedents+i].c == ch->rc && cm->alts[Afixedents+i].op == CHANNOP); return ch; } - ch = emalloc(sizeof *ch); + ch = mallocz(sizeof *ch, 1); cm->chs[i] = ch; ch->id = i; ch->rc = echancreate(sizeof(Chmsg), 0); @@ -177,6 +181,8 @@ ch->dc = echancreate(sizeof(ulong), 0); ch->cm = cm; ch->notnew = notnew; + cm->alts[Afixedents+i].c = ch->rc; + cm->alts[Afixedents+i].op = CHANNOP; threadcreate(chwproc, ch, Stack); return ch; } @@ -184,13 +190,18 @@ static void grow(Cmux *cm, int n) { - int elsz; + int i, elsz; if(n > CFidmask) sysfatal("growto: no more channel ids"); if(cm->nachs < n){ + cm->alts = realloc(cm->alts, (Afixedents+n+1) * sizeof(Alt)); + for(i = cm->nachs; i < n+1; i++) + cm->alts[Afixedents+i].op = CHANNOP; + cm->alts[Afixedents+n].op = CHANEND; + elsz = sizeof cm->chs[0]; - cm->chs = erealloc(cm->chs, n * elsz); + cm->chs = realloc(cm->chs, n * elsz); memset(&cm->chs[cm->nachs], 0, (n - cm->nachs) * elsz); cm->nachs = n; } @@ -225,24 +236,27 @@ dsprint("cmux[%p]: delch: ch%d keep=%d (%d chs)\n", cm, ch->id, keep, cm->nuse); if(ch->dead == 0 || keep != 0) cm->nuse--; - if(keep) + if(keep){ + cm->alts[Afixedents+ch->id].op = CHANNOP; ch->dead = 1; - else{ + }else{ chanfree(ch->rc); chanfree(ch->wc); sendul(ch->dc, 0); ch->rc = ch->wc = nil; assert(cm->chs[ch->id] == ch); cm->chs[ch->id] = nil; + cm->alts[Afixedents+ch->id] = (Alt){nil, nil, CHANNOP, 0, 0, 0}; + free(ch->chms); free(ch); } } /* * Demux message already received in cm->rc and return - * the Ch for it, perhaps a new Ch. + * the Ch id for it, perhaps it's a new Ch. */ -static Ch* +static int cdemux(Cmux *cm, Msg *m, int *lastp) { uint id, flags; @@ -252,7 +266,7 @@ if(msglen(m) < BIT16SZ){ werrstr("short message header"); - return nil; + return -1; } hdr = msgpophdr(m, BIT16SZ); assert(hdr != nil); @@ -263,15 +277,15 @@ if(flags&CFnew){ ch = addch(cm, id, 1); if(ch == nil) - return nil; + return -1; sendp(cm->newc, ch); }else if(id >= cm->nchs || cm->chs[id] == nil || cm->chs[id]->dead){ werrstr("no channel %d", id); - return nil; + return -1; } *lastp = flags&CFend; - return cm->chs[id]; + return id; } static void @@ -290,6 +304,35 @@ } static void +queuechm(Cmux *cm, int id, Chmsg chm) +{ + Ch *ch; + + ch = cm->chs[id]; + if(ch->nchms == ch->nachms){ + ch->nachms += Incr; + ch->chms = realloc(ch->chms, ch->nachms*sizeof(Chmsg)); + cm->alts[Afixedents+id].v = &ch->chms[0]; + } + ch->chms[ch->nchms++] = chm; + cm->alts[Afixedents+id].op = CHANSND; +} + +static void +dequeuechm(Cmux *cm, int id) +{ + Ch *ch; + + ch = cm->chs[id]; + assert(ch->nchms > 0); + ch->nchms--; + if(ch->nchms > 0) + memmove(&ch->chms[0], &ch->chms[1], ch->nchms*sizeof(Chmsg)); + else + cm->alts[Afixedents+id].op = CHANNOP; +} + +static void allabort(Cmux *cm) { int i; @@ -301,10 +344,8 @@ if(!cm->chs[i]->rclosed){ chm.m = nil; chm.last = 1; - send(cm->chs[i]->rc, &chm); - cm->chs[i]->rclosed = 1; - } - if(cm->chs[i]->wclosed) + queuechm(cm, i, chm); + }else if(cm->chs[i]->wclosed) delch(cm, cm->chs[i], Free); }else delch(cm, cm->chs[i], Free); @@ -320,21 +361,17 @@ Chmsg chm; Msg *m; Ch *ch; - Alt alts[] = { - {nil, &dummy, CHANRCV}, - {nil, &ch, CHANRCV}, - {nil, &m, CHANRCV}, - {nil, nil, CHANEND}, - }; + int id; cm = a; threadsetname("cmuxproc %p", a); dpprint("cmuxproc[%p]: starting\n", a); - alts[0].c = cm->mkc; - alts[1].c = cm->endc; - alts[2].c = cm->src; - for(;;) - switch(alt(alts)){ + cm->alts[Amkc] = (Alt){cm->mkc, &dummy, CHANRCV, 0, 0, 0}; + cm->alts[Aendc] = (Alt){cm->endc, &ch, CHANRCV, 0, 0, 0}; + cm->alts[Asrc] = (Alt){cm->src, &m, CHANRCV, 0, 0, 0}; + cm->alts[Afixedents] = (Alt){nil, nil, CHANEND, 0, 0, 0}; + for(;;){ + switch(id = alt(cm->alts)){ case Mkc: ch = addch(cm, -1, 0); sendp(cm->mkrc, ch); @@ -375,18 +412,28 @@ goto Done; } chm.m = m; - ch = cdemux(cm, m, &chm.last); - if(ch == nil){ + id = cdemux(cm, m, &chm.last); + if(id < 0){ dsprint("cdemux: drop msg: %r\n"); cmdump(cm); freemsg(m); break; } + ch = cm->chs[id]; if(!ch->rclosed && !ch->flushing) - send(ch->rc, &chm); + queuechm(cm, id, chm); else freemsg(m); - if(chm.last){ + break; + case -1: + sysfatal("cmuxproc[%p]: alt", a); + default: + id -= Afixedents; + if(id < 0 || id >= cm->nachs) + sysfatal("cmuxproc[%p]: alt id %d", a, id); + ch = cm->chs[id]; + assert(ch != nil && ch->nchms > 0); + if(ch->chms[0].last){ if(ch->rclosed){ dsprint("cmuxproc[%p]: ch%d flush\n", a, ch->id); ch->flushing = 1; @@ -395,10 +442,9 @@ if(ch->wclosed) delch(cm, ch, Keep); } - break; - default: - sysfatal("cmuxproc[%p]: alt", a); + dequeuechm(cm, id); } + } Done: allclosed(cm); dsprint("cmuxproc[%p]: done\n", a); @@ -407,6 +453,7 @@ chanfree(cm->mkrc); chanfree(cm->endc); free(cm->chs); + free(cm->alts); free(cm); threadexits(nil); } @@ -416,7 +463,7 @@ { Cmux *cm; - cm = emalloc(sizeof *cm); + cm = mallocz(sizeof *cm, 1); cm->src = src; cm->swc = swc; cm->sec = sec; @@ -424,6 +471,8 @@ cm->mkc = echancreate(sizeof(ulong), 0); cm->mkrc = echancreate(sizeof(Ch*), 0); cm->endc = echancreate(sizeof(ulong), 0); + cm->alts = mallocz(sizeof(Alt)*(Afixedents+1), 1); + /* * Could be a thread, but then the caller * would have to be aware and don't block the process. diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/ch.h --- a/sys/src/cmd/ix/ch.h Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/ch.h Thu Dec 01 11:19:13 2011 +0100 @@ -1,5 +1,6 @@ typedef struct Ch Ch; typedef struct Cmux Cmux; +typedef struct Chmsg Chmsg; enum @@ -10,6 +11,13 @@ CFidmask = 0x3FFF, Chhdrsz = BIT16SZ, + +}; + +struct Chmsg +{ + Msg *m; + int last; }; struct Ch @@ -25,6 +33,10 @@ int wclosed; int flushing; + Chmsg *chms; + int nchms; + int nachms; + int dead; /* gone channel, waiting to be reused */ Channel *dc; }; @@ -38,12 +50,13 @@ Channel*swc; /* multiplexed session write channel */ Channel*sec; /* multiplexed session error channel */ Channel*mkc; /* of ulong; request a new ch */ - Channel*mkrc; /* of Ch*; reply with new ch */ + Channel*mkrc; /* of Ch*; reply ......with new ch */ Channel*endc; /* of Ch*; to release ch */ Ch** chs; /* array of channels in this session */ int nuse; /* # of channels in use */ int nchs; /* number of channels used */ int nachs; /* number of channels allocated */ + Alt *alts; /* cmux chans + one read channel per Ch */ }; /* |c/f2p ch.c */ diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/conf.h --- a/sys/src/cmd/ix/conf.h Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/conf.h Thu Dec 01 11:19:13 2011 +0100 @@ -1,7 +1,7 @@ enum { KiB = 1024, - Stack = 8*KiB, /* stack size for threads */ + Stack = 32*KiB, /* stack size for threads */ Hbufsz = 8, /* room for message headers */ Msgsz = 8*KiB, /* message size */ diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/dbg.h --- a/sys/src/cmd/ix/dbg.h Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/dbg.h Thu Dec 01 11:19:13 2011 +0100 @@ -8,7 +8,9 @@ * 't': test client * 'n': nsfile * 'c': cache + * 'D': disk */ +#define dDprint if(!dbg['D']){}else print #define dPprint if(!dbg['P']){}else print #define dcprint if(!dbg['c']){}else print #define dfprint if(!dbg['f']){}else print diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/fmt.c --- a/sys/src/cmd/ix/fmt.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/fmt.c Thu Dec 01 11:19:13 2011 +0100 @@ -2,13 +2,9 @@ #include #include -#include "fs.h" +#include "ix.h" -static uint dumpsome(char*, char*, char*, long); -static void fdirconv(char*, char*, Dir*); -static char *qidtype(char*, uchar); -#define QIDFMT "(%.16llux %lud %s)" static char* cname[CMAX] = { @@ -21,192 +17,189 @@ }; int -fscallfmt(Fmt *fmt) +ixcallfmt(Fmt *fmt) { - Fscall *f; - int type; - char buf[512], tmp[200]; + IXcall *f; + int type, i; + char buf[512]; char *p, *e, *s; - Dir *d; - Qid *q; e = buf+sizeof(buf); - f = va_arg(fmt->args, Fscall*); + f = va_arg(fmt->args, IXcall*); type = f->type; switch(type){ - case Tcond: - if(f->cond >= CMAX) - s = "??"; - else - s = cname[f->cond]; - p = seprint(buf, e, "Tcond %s", s); - if(f->nstat > sizeof tmp) - seprint(p, e, " stat(%d bytes)", f->nstat); - else{ - d = (Dir*)tmp; - convM2D(f->stat, f->nstat, d, (char*)(d+1)); - seprint(p, e, " stat "); - fdirconv(p+6, e, d); - } + case IXTversion: + seprint(buf, e, "Tversion msize %ud version '%s'", f->msize, f->version); + break; + case IXRversion: + seprint(buf, e, "Rversion msize %ud version '%s'", f->msize, f->version); break; - case Rcond: - seprint(buf, e, "Rcond"); + case IXTsession: + seprint(buf, e, "Tsession ssid %ud uname '%s' keep %d", f->ssid, f->uname, f->keep); break; - case Tfid: - seprint(buf, e, "Tfid fid %ud cflags %d", f->fid, f->cflags); + case IXRsession: + seprint(buf, e, "Rsession ssid %ud afid %ud uname '%s'", + f->ssid, f->afid, f->uname); break; - case Rfid: + + case IXTsid: + seprint(buf, e, "Tsid ssid %ud", f->ssid); + break; + case IXRsid: + seprint(buf, e, "Rsid"); + break; + + case IXTendsession: + seprint(buf, e, "Tendsession"); + break; + case IXRendsession: + seprint(buf, e, "Rendsession"); + break; + + case IXTfid: + seprint(buf, e, "Tfid fid %ud", f->fid); + break; + case IXRfid: seprint(buf, e, "Rfid"); break; - case Tclone: - seprint(buf, e, "Tclone cflags %d", f->cflags); + + case IXTattach: + seprint(buf, e, "Tattach aname '%s'", f->aname); break; - case Rclone: - seprint(buf, e, "Rclone newfid %d", f->newfid); + case IXRattach: + seprint(buf, e, "Rattach fid %d", f->fid); break; - case Tversion: /* 100 */ - seprint(buf, e, "Tversion msize %ud version '%s'", f->msize, f->version); + + case IXRerror: + seprint(buf, e, "Rerror ename '%s'", f->ename); break; - case Rversion: - seprint(buf, e, "Rversion msize %ud version '%s'", f->msize, f->version); + + case IXTclone: + seprint(buf, e, "Tclone cflags %#x", f->cflags); break; - case Tauth: /* 102 */ - seprint(buf, e, "Tauth afid %d uname %s aname %s", - f->afid, f->uname, f->aname); + case IXRclone: + seprint(buf, e, "Rclone fid %d", f->fid); break; - case Rauth: - seprint(buf, e, "Rauth qid " QIDFMT, - f->aqid.path, f->aqid.vers, qidtype(tmp, f->aqid.type)); + + + case IXTwalk: + s = seprint(buf, e, "Twalk"); + for(i = 0; i < f->nwname; i++) + s = seprint(s, e, " '%s'", f->wname[i]); break; - case Tattach: /* 104 */ - seprint(buf, e, "Tattach afid %d uname %s aname %s", - f->afid, f->uname, f->aname); + case IXRwalk: + seprint(buf, e, "Rwalk"); break; - case Rattach: - seprint(buf, e, "Rattach fid %d qid " QIDFMT, - f->fid, f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type)); - break; - case Rerror: /* 107; 106 (Terror) illegal */ - seprint(buf, e, "Rerror ename %s", f->ename); - break; - case Twalk: /* 110 */ - seprint(buf, e, "Twalk wname %s", f->wname); - break; - case Rwalk: - q = &f->wqid; - seprint(buf, e, "Rwalk wqid " QIDFMT, - q->path, q->vers, qidtype(tmp, q->type)); - break; - case Topen: /* 112 */ + + case IXTopen: seprint(buf, e, "Topen mode %d", f->mode); break; - case Ropen: - seprint(buf, e, "Ropen qid " QIDFMT " iounit %ud ", - f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit); + case IXRopen: + seprint(buf, e, "Ropen"); break; - case Tcreate: /* 114 */ + + case IXTcreate: seprint(buf, e, "Tcreate name %s perm %M mode %d", f->name, (ulong)f->perm, f->mode); break; - case Rcreate: - seprint(buf, e, "Rcreate qid " QIDFMT " iounit %ud ", - f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit); + case IXRcreate: + seprint(buf, e, "Rcreate"); break; - case Tread: /* 116 */ + + case IXTread: seprint(buf, e, "Tread nmsg %d offset %lld count %ud", f->nmsg, f->offset, f->count); break; - case Rread: - p = seprint(buf, e, "Rread count %ud ", f->count); - dumpsome(p, e, f->data, f->count); + case IXRread: + s = seprint(buf, e, "Rread count %ud ", f->count); + dumpsome(s, e, f->data, f->count); break; - case Twrite: /* 118 */ - p = seprint(buf, e, "Twrite offset %lld count %ud ", - f->offset, f->count); + + case IXTwrite: + p = seprint(buf, e, "Twrite offset %lld endoffset %lld count %ud ", + f->offset, f->endoffset, f->count); dumpsome(p, e, f->data, f->count); break; - case Rwrite: - seprint(buf, e, "Rwrite count %ud", f->count); + case IXRwrite: + seprint(buf, e, "Rwrite offset %lld count %ud", f->offset, f->count); break; - case Tclunk: /* 120 */ + + case IXTclunk: seprint(buf, e, "Tclunk"); break; - case Rclunk: + case IXRclunk: seprint(buf, e, "Rclunk"); break; - case Tremove: /* 122 */ + case IXTclose: + seprint(buf, e, "Tclose"); + break; + case IXRclose: + seprint(buf, e, "Rclose"); + break; + case IXTremove: seprint(buf, e, "Tremove"); break; - case Rremove: + case IXRremove: seprint(buf, e, "Rremove"); break; - case Tstat: /* 124 */ - seprint(buf, e, "Tstat"); + + case IXTattr: + seprint(buf, e, "Tattr attr '%s'", f->attr); break; - case Rstat: - p = seprint(buf, e, "Rstat "); - if(f->nstat > sizeof tmp) - seprint(p, e, " stat(%d bytes)", f->nstat); - else{ - d = (Dir*)tmp; - convM2D(f->stat, f->nstat, d, (char*)(d+1)); - seprint(p, e, " stat "); - fdirconv(p+6, e, d); - } + case IXRattr: + p = seprint(buf, e, "Rattr value "); + dumpsome(p, e, f->value, f->nvalue); break; - case Twstat: /* 126 */ - p = seprint(buf, e, "Twstat"); - if(f->nstat > sizeof tmp) - seprint(p, e, " stat(%d bytes)", f->nstat); - else{ - d = (Dir*)tmp; - convM2D(f->stat, f->nstat, d, (char*)(d+1)); - seprint(p, e, " stat "); - fdirconv(p+6, e, d); - } + + case IXTwattr: + p = seprint(buf, e, "Twattr attr '%s' value ", f->attr); + dumpsome(p, e, f->value, f->nvalue); break; - case Rwstat: - seprint(buf, e, "Rwstat"); + case IXRwattr: + seprint(buf, e, "Rwattr"); break; + + case IXTcond: + if(f->op >= CMAX) + s = "??"; + else + s = cname[f->op]; + p = seprint(buf, e, "Tcond op %s", s); + p = seprint(p, e, "attr '%s' value ", f->attr); + dumpsome(p, e, f->value, f->nvalue); + break; + case IXRcond: + seprint(buf, e, "Rcond"); + break; + + case IXTmove: + seprint(buf, e, "Tmove dirfid %d newname '%s'", f->dirfid, f->newname); + break; + case IXRmove: + seprint(buf, e, "Rmove"); + break; + + case IXTcopy: + seprint(buf, e, "Tcopy nmsg %d offset %lld count %ud dstfid %ud dstoffset %lld", + f->nmsg, f->offset, f->count, f->dstfid, f->dstoffset); + break; + case IXRcopy: + seprint(buf, e, "Rcopy count %ud", f->count); + break; + + case IXTflush: + seprint(buf, e, "Tflush"); + break; + case IXRflush: + seprint(buf, e, "Rflush"); + break; + default: seprint(buf, e, "unknown type %d", type); } return fmtstrcpy(fmt, buf); } -static char* -qidtype(char *s, uchar t) -{ - char *p; - - p = s; - if(t & QTDIR) - *p++ = 'd'; - if(t & QTAPPEND) - *p++ = 'a'; - if(t & QTEXCL) - *p++ = 'l'; - if(t & QTAUTH) - *p++ = 'A'; - *p = '\0'; - return s; -} - -static void -fdirconv(char *buf, char *e, Dir *d) -{ - char tmp[16]; - - seprint(buf, e, "'%s' '%s' '%s' '%s' " - "q " QIDFMT " m %#luo " - "at %ld mt %ld l %lld " - "t %d d %d", - d->name, d->uid, d->gid, d->muid, - d->qid.path, d->qid.vers, qidtype(tmp, d->qid.type), d->mode, - d->atime, d->mtime, d->length, - d->type, d->dev); -} - /* * dump out count (or DUMPL, if count is bigger) bytes from * buf to ans, as a string if they are all printable, @@ -214,12 +207,14 @@ */ #define DUMPL 64 -static uint -dumpsome(char *ans, char *e, char *buf, long count) +uint +dumpsome(char *ans, char *e, void *b, long count) { int i, printable; char *p; + char *buf; + buf = b; if(buf == nil){ seprint(ans, e, ""); return strlen(ans); diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/fs.c --- a/sys/src/cmd/ix/fs.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/fs.c Thu Dec 01 11:19:13 2011 +0100 @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -11,39 +10,41 @@ #include "tses.h" #include "ch.h" #include "dbg.h" -#include "fs.h" -#include "file.h" +#include "ix.h" +#include "ixfile.h" + +enum +{ + SSID = 42 +}; /* * Mbuf convention: * Msg.io[0] always refers to the message buffer. */ -/* - * Flushing is done by aborting the Ch where the RPC is being sent. - * When ch is flushing, it will not deliver more messages to the - * reader. - * Thus, the client should not flush before receiving replies to - * requests like Tclone or Topen which allocate new resources. - * It should flush only when replies received from us make it clear - * what's the state on its behalf. - * - * This makes flush processing a lot simpler than it could be. - */ - typedef struct Fs Fs; typedef struct Rpc Rpc; typedef struct Fid Fid; +typedef struct Ses Ses; +struct Ses +{ + QLock; + Ref; + char *uname; + int ssid; + Ses *next; /* in avail sessions list */ + Fid **fids; + int nfids; + Fid *free; + void *tag; /* to remove those not kept */ +}; struct Fs { QLock; - Fid **fids; - int nfids; - Fid *free; - - Ses *s; /* session (i.e., tcp connection) */ + Con *s; /* transport session (i.e., tcp connection) */ Cmux *cm; /* channel multiplexor */ Channel *argc; /* to pass args to workers */ ulong msize; /* maximum data size */ @@ -58,6 +59,7 @@ int fd; /* meaningful to File only */ int cflags; /* OCEND|OCERR */ int omode; + int aborting; }; struct Rpc @@ -65,8 +67,9 @@ Fs *fs; Ch *ch; Msg *m; + Ses *ix; Fid *fid; - Fscall t, r; + IXcall t, r; int last; }; @@ -76,7 +79,11 @@ Small, }; +static QLock ixslk; static Ssrv *ssrv; +static Ses *ixs; /* sessions in server */ + +static int ssid = SSID; /* server session id; any number would do */ static Channel *poolc[2]; static int npools[2]; static ulong poolmsz[2] = @@ -85,63 +92,78 @@ [Small] Smsgsz, }; +static QLock hugelock; /* BUG: single lock for the fs */ +static int nfids; static Fid* -newfid(Fs *fs) +newfid(Ses *ix) { Fid *fid; - qlock(fs); - if(fs->free != nil){ - fid = fs->free; - fs->free = fid->next; - qunlock(fs); + qlock(ix); + nfids++; + if(ix->free != nil){ + fid = ix->free; + ix->free = fid->next; + qunlock(ix); return fid; } - if((fs->nfids%Incr) == 0) - fs->fids = erealloc(fs->fids, (fs->nfids+Incr)*sizeof(Fid*)); - fid = emalloc(sizeof *fid); - fs->fids[fs->nfids] = fid; - fid->id = fs->nfids++; + if((ix->nfids%Incr) == 0) + ix->fids = realloc(ix->fids, (ix->nfids+Incr)*sizeof(Fid*)); + fid = mallocz(sizeof *fid, 1); + ix->fids[ix->nfids] = fid; + fid->id = ix->nfids++; fid->ref = 1; fid->omode = -1; fid->fd = -1; - qunlock(fs); + fid->aborting = 0; + qunlock(ix); return fid; } static void -putfid(Fs *fs, Fid *fid) +clunkfid(Fid *fid) { + if(fid->file != nil){ + if(fid->fd != -1) + closefile(fid->file, fid->fd, fid->aborting); + putfile(fid->file); + } + fid->file = nil; + fid->fd = -1; + fid->omode = -1; +} + + +static void +putfid(Ses *ix, Fid *fid) +{ + assert(ix != nil); if(decref(fid) == 0){ - qlock(fs); - fid->next = fs->free; - fs->free = fid; - if(fid->file != nil){ - if(fid->fd != -1) - closefile(fid->file, fid->fd); - putfile(fid->file); - } - fid->file = nil; - fid->fd = -1; - fid->omode = -1; - qunlock(fs); + qlock(ix); + nfids--; + dfprint("free fid. %d fids in use\n", nfids); + fid->next = ix->free; + ix->free = fid; + clunkfid(fid); + qunlock(ix); } } static Fid* -getfid(Fs *fs, int id) +getfid(Ses *ix, int id) { Fid *fid; - qlock(fs); - if(id < 0 || id >= fs->nfids || fs->fids[id]->file == nil){ - qunlock(fs); + assert(ix != nil); + qlock(ix); + if(id < 0 || id >= ix->nfids || ix->fids[id]->file == nil){ + qunlock(ix); return nil; } - fid = fs->fids[id]; + fid = ix->fids[id]; incref(fid); - qunlock(fs); + qunlock(ix); return fid; } @@ -182,6 +204,101 @@ return recvp(poolc[sz]); } +static void +freeses(Ses *ix) +{ + int i; + + for(i = 0; i < ix->nfids; i++) + free(ix->fids[i]); + free(ix->fids); + free(ix->uname); + free(ix); +} + +static Ses* +getses(int ssid) +{ + Ses *ix; + + qlock(&ixslk); + for(ix = ixs; ix != nil; ix = ix->next) + if(ix->ssid == ssid){ + incref(ix); + break; + } + qunlock(&ixslk); + return ix; +} + +static void +_putses(Ses *ix) +{ + Ses **s; + + if(ix == nil || decref(ix) > 0) + return; + dfprint("putses: free session id %d\n", ix->ssid); + for(s = &ixs; *s != nil; s = &(*s)->next) + if(*s == ix){ + *s = ix->next; + freeses(ix); + return; + } + sysfatal("session not found in putses"); +} + +static void +putses(Ses *ix) +{ + Ses **s; + + if(ix == nil || decref(ix) > 0) + return; + dfprint("putses: free session id %d\n", ix->ssid); + qlock(&ixslk); + for(s = &ixs; *s != nil; s = &(*s)->next) + if(*s == ix){ + *s = ix->next; + freeses(ix); + qunlock(&ixslk); + return; + } + sysfatal("session not found in putses"); +} + +static Ses* +newses(void *tag) +{ + Ses *ix; + static int ssidgen; + + assert(tag != nil); + qlock(&ixslk); + ix = mallocz(sizeof *ix, 1); + ix->ref = 1; + ix->next = ixs; + ix->ssid = ++ssidgen; + ix->tag = tag; + ixs = ix; + qunlock(&ixslk); + return ix; +} + +static void +killses(void *tag) +{ + Ses *ns, *s; + + qlock(&ixslk); + for(s = ixs; s != nil; s = ns){ + ns = s->next; + if(s->tag == tag) + _putses(s); + } + qunlock(&ixslk); +} + static int fsreply(Rpc *rpc) { @@ -194,15 +311,16 @@ m->hdr = nil; io = &m->io[0]; /* - * Rread reads data directly after the packed reply Fscall + * Rread puts data directly after the packed reply Fscall * and sets io's rp and wp by itself. + * The same goes for Rattr. */ dfprint("%cch%d-> %G\n", rpc->last?'|':'-', rpc->ch->id, &rpc->r); - if(rpc->r.type == Rread) - n = pack(&rpc->r, io->bp, packedsize(&rpc->r)); + if(rpc->r.type == IXRread || rpc->r.type == IXRattr) + n = ixpack(&rpc->r, io->bp, ixpackedsize(&rpc->r)); else{ ioreset(io); - n = pack(&rpc->r, io->wp, IOCAP(io)); + n = ixpack(&rpc->r, io->wp, IOCAP(io)); io->wp += n; } if(n <= 0) @@ -213,8 +331,10 @@ rpc->last = 1; } if(rpc->last != 0 && rpc->fid != nil && (rpc->fid->cflags&OCEND) != 0){ - putfid(rpc->fs, rpc->fid); /* held by client */ - putfid(rpc->fs, rpc->fid); /* held by rpc */ + if(rpc->r.type == IXRerror) + rpc->fid->aborting++; + putfid(rpc->ix, rpc->fid); /* held by client */ + putfid(rpc->ix, rpc->fid); /* held by rpc */ rpc->fid = nil; } return rc; @@ -223,7 +343,7 @@ static int fserror(Rpc *rpc, char *e) { - rpc->r.type = Rerror; + rpc->r.type = IXRerror; rpc->r.ename = e; rpc->last = 1; fsreply(rpc); @@ -236,7 +356,7 @@ char *e; e = smprint("%r"); - rpc->r.type = Rerror; + rpc->r.type = IXRerror; rpc->r.ename = e; rpc->last = 1; if(rpc->fid != nil && (rpc->fid->cflags&OCERR) != 0) @@ -254,53 +374,116 @@ dfprint("fsversion: msize %uld\n", rpc->fs->msize); } rpc->r.msize = rpc->fs->msize; - if(strcmp(rpc->t.version, "ix") != 0) + if(strcmp(rpc->t.version, "3.1415926P") != 0) return fserror(rpc, "wrong version"); - rpc->r.version = "ix"; + rpc->r.version = "3.1415926P"; return fsreply(rpc); } static int -fsauth(Rpc *rpc) +fssession(Rpc *rpc) { - return fserror(rpc, "no auth required"); + Ses *s; + + /* only the owner can set a session by now */ + if(strcmp(rpc->t.uname, getuser()) != 0) + return fserror(rpc, "bad user in session"); + + if(rpc->t.ssid != Nossid) + s = getses(rpc->t.ssid); + else{ + s = newses(rpc->fs); /* use fs as the tag */ + incref(s); /* it's allocated now until endsession */ + } + if(rpc->t.keep) + s->tag = nil; /* forget thet tag: keep it when done */ + putses(rpc->ix); + rpc->ix = s; + if(s == nil) + return fserror(rpc, "unknown session id"); + rpc->ix->uname = strdup(rpc->t.uname); + rpc->r.afid = ~0; + rpc->r.ssid = s->ssid; + rpc->r.uname = getuser(); + dfprint("fssession: session id %d ref %d\n", s->ssid, s->ref); + return fsreply(rpc); +} + +static int +fssid(Rpc *rpc) +{ + Ses *ix; + + ix = getses(rpc->t.ssid); + putses(rpc->ix); + rpc->ix = ix; + if(ix == nil) + return fserror(rpc, "unknown session id"); + return fsreply(rpc); +} + +static int +fsendsession(Rpc *rpc) +{ + Ses *ix; + + if(rpc->ix == nil) + return fserror(rpc, "session not set"); + putses(rpc->ix); + ix = rpc->ix; + rpc->ix = nil; + + putses(ix); /* should destroy it when unused */ + return fsreply(rpc); +} + +static int +fsfid(Rpc *rpc) +{ + if(rpc->ix == nil) + return fserror(rpc, "session not set"); + if(rpc->fid != nil) + putfid(rpc->ix, rpc->fid); + rpc->fid = getfid(rpc->ix, rpc->t.fid); + if(rpc->fid == nil) + return fserror(rpc, "no such fid"); + rpc->fid->cflags = rpc->t.cflags; + return fsreply(rpc); } static int fsattach(Rpc *rpc) { - if(strcmp(rpc->t.uname, getuser()) != 0) - return fserror(rpc, "bad user in attach"); + if(rpc->ix == nil) + return fserror(rpc, "session not set"); + /* * rpc->t.aname ignored - * rpc->t.fid is not used */ - if(rpc->t.afid != NOFID) - return fserror(rpc, "auth not supported"); - rpc->fid = newfid(rpc->fs); - incref(rpc->fid); /* client's reference */ + rpc->fid = newfid(rpc->ix); + incref(rpc->fid); /* client's reference */ rpc->r.fid = rpc->fid->id; rpc->fid->file = rootfile(); - rpc->r.qid = fileqid(rpc->fid->file); return fsreply(rpc); } - static int fsclone(Rpc *rpc) { Fid *nfid; Fid *fid; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); - nfid = newfid(rpc->fs); /* ref held by client */ - rpc->r.newfid = nfid->id; + nfid = newfid(rpc->ix); /* ref held by client */ + rpc->r.fid = nfid->id; nfid->omode = fid->omode; nfid->file = fid->file; - incref(nfid->file); - putfid(rpc->fs, fid); /* held by rpc */ + increffile(nfid->file); + putfid(rpc->ix, fid); /* held by rpc */ rpc->fid = nfid; nfid->cflags = rpc->t.cflags; incref(nfid); /* held by rpc */ @@ -311,15 +494,22 @@ fswalk(Rpc *rpc) { Fid *fid; + int i; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); if(fid->omode != -1) return fserror(rpc, "can't walk an open fid"); - if(walkfile(&fid->file, rpc->t.wname) < 0) - return fssyserror(rpc); - rpc->r.wqid = fileqid(fid->file); + /* + * NB: This differs from 9p. A walk succeeds only if all + * names can be walked. + */ + for(i = 0; i < rpc->t.nwname; i++) + if(walkfile(&fid->file, rpc->t.wname[i]) < 0) + return fssyserror(rpc); return fsreply(rpc); } @@ -328,6 +518,8 @@ { Fid *fid; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); @@ -337,8 +529,6 @@ if(fid->fd < 0) return fssyserror(rpc); fid->omode = rpc->t.mode; - rpc->r.qid = fileqid(fid->file); - rpc->r.iounit = 0; return fsreply(rpc); } @@ -348,6 +538,8 @@ int fd; Fid *fid; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); @@ -358,8 +550,6 @@ return fssyserror(rpc); fid->fd = fd; fid->omode = rpc->t.mode; - rpc->r.qid = fileqid(fid->file); - rpc->r.iounit = 0; return fsreply(rpc); } @@ -371,6 +561,8 @@ Fid *fid; int i, saved, last; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); @@ -388,12 +580,12 @@ nr = rpc->t.count; rpc->m->hdr = nil; ioreset(io); - io->wp += packedsize(&rpc->r); + io->wp += ixpackedsize(&rpc->r); if(nr < 0 || nr > IOCAP(io)) nr = IOCAP(io); if(IOLEN(io)+nr > rpc->fs->msize) nr = rpc->fs->msize - IOLEN(io); - rpc->r.data = (char*)io->wp; + rpc->r.data = io->wp; nr = preadfile(fid->file, fid->fd, io->wp, nr, rpc->t.offset); if(nr < 0) return fssyserror(rpc); @@ -402,12 +594,13 @@ rpc->r.count = nr; saved = rpc->last; - rpc->last = 0; - last = saved && (rpc->last = i == rpc->t.nmsg || nr == 0); - if(fsreply(rpc) < 0) + rpc->last = last = (saved && (i == rpc->t.nmsg || nr == 0)); + if(fsreply(rpc) < 0){ + rpc->last = saved; return -1; + } rpc->last = saved; - if(last) + if(last || nr == 0) break; rpc->m = newmsg(rpc->fs->s->pool); } @@ -419,18 +612,21 @@ { long nw; Fid *fid; - Fscall *t; + IXcall *t; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); if(fid->omode < 0 || (fid->omode&3) == OREAD) return fserror(rpc, "fid not open for writing"); t = &rpc->t; - nw = pwritefile(fid->file, fid->fd, t->data, t->count, t->offset); + nw = pwritefile(fid->file, fid->fd, t->data, t->count, &t->offset, t->offset+t->count); if(nw < 0) return fssyserror(rpc); rpc->r.count = nw; + rpc->r.offset = t->offset; return fsreply(rpc); } @@ -439,34 +635,61 @@ { Fid * fid; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); - putfid(rpc->fs, fid); + fid->aborting++; + putfid(rpc->ix, fid); /* in session */ + putfid(rpc->ix, fid); /* in rpc */ rpc->fid = nil; return fsreply(rpc); } static int +fsclose(Rpc *rpc) +{ + Fid * fid; + int isopen; + + if(rpc->ix == nil) + return fserror(rpc, "session not set"); + fid = rpc->fid; + if(fid == nil) + return fserror(rpc, "fid not set"); + isopen = fid->omode >= 0; + assert(fid->aborting == 0); + putfid(rpc->ix, fid); /* in session */ + putfid(rpc->ix, fid); /* in rpc */ + rpc->fid = nil; + if(!isopen) + return fserror(rpc, "fid not open"); + return fsreply(rpc); +} + +static int fsremove(Rpc *rpc) { Fid * fid; int r; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); if(fid->omode >= 0){ - closefile(fid->file, fid->fd); + closefile(fid->file, fid->fd, fid->aborting); fid->fd = -1; fid->omode = -1; } - putfid(rpc->fs, fid); /* held by client */ + putfid(rpc->ix, fid); /* held by client */ /* file goes when rpc->fid reference is released later */ r = removefile(fid->file); - putfid(rpc->fs, fid); /* held by rpc */ + putfid(rpc->ix, fid); /* held by rpc */ rpc->fid = nil; if(r < 0) return fssyserror(rpc); @@ -475,72 +698,51 @@ } static int -fsstat(Rpc *rpc) +fsattr(Rpc *rpc) { Fid *fid; - Dir *d; - uchar buf[512]; /* bug: fixes stat size */ + Io *io; + long nr; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); - d = statfile(fid->file, 1); - if(d == nil) - return fssyserror(rpc); - rpc->r.nstat = convD2M(d, buf, sizeof buf); - if(rpc->r.nstat <= BIT32SZ) - sysfatal("fsstat: buf too short"); - rpc->r.stat = buf; - free(d); - /* - * We are probably using a small buffer, get a large - * one for the reply. + * Get a large buffer; we are probably using a small one. */ freemsg(rpc->m); rpc->m = newmsg(rpc->fs->s->pool); + io = &rpc->m->io[0]; + rpc->m->hdr = nil; + ioreset(io); + io->wp += ixpackedsize(&rpc->r); + rpc->r.value = io->wp; + nr = fileattr(fid->file, rpc->t.attr, rpc->r.value, IOCAP(io)); + if(nr < 0) + return fssyserror(rpc); + rpc->r.nvalue = nr; + io->wp += nr; return fsreply(rpc); } static int -fswstat(Rpc *rpc) +fswattr(Rpc *rpc) { Fid *fid; - Dir d; - char buf[512]; /* bug: fixes stat size */ + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); - if(convM2D(rpc->t.stat, rpc->t.nstat, &d, buf) <= BIT32SZ) - return fserror(rpc, "bad stat data"); - if(wstatfile(fid->file, &d) < 0) + if(filewattr(fid->file, rpc->t.attr, rpc->t.value, IOLEN(rpc->m->io)) < 0) return fssyserror(rpc); return fsreply(rpc); } static int -cmpulong(uvlong u1, uvlong u2, int cond) -{ - switch(cond){ - case CEQ: - return u1 == u2; - case CNE: - return u1 != u2; - case CLE: - return u1 >= u2; - case CLT: - return u1 > u2; - case CGT: - return u1 < u2; - case CGE: - return u2 <= u2; - default: - return 0; - } -} - -static int cmpstr(char *s1, char *s2, int cond) { switch(cond){ @@ -565,108 +767,106 @@ fscond(Rpc *rpc) { Fid *fid; - Dir cd, *d; - char buf[512]; /* bug: fixes stat size */ + char buf[128]; /* bug: fixes stat size */ + char buf2[128]; + Msg *m; + long n; + if(rpc->ix == nil) + return fserror(rpc, "session not set"); fid = rpc->fid; if(fid == nil) return fserror(rpc, "fid not set"); - if(convM2D(rpc->t.stat, rpc->t.nstat, &cd, buf) <= BIT32SZ) - sysfatal("fswstat: bug"); - d = statfile(fid->file, 1); - if(d == nil) + m = rpc->m; + if(IOLEN(m->io) >= sizeof buf - 1) + return fserror(rpc, "fscond: bug: attr value too large"); + memmove(buf, m->io->rp, IOLEN(m->io)); + buf[IOLEN(m->io)] = 0; + n = fileattr(fid->file, rpc->t.attr, (uchar*)buf2, sizeof buf2 - 1); + if(n < 0) return fssyserror(rpc); - if(cd.qid.path != ~0ULL && cmpulong(cd.qid.path, d->qid.path, rpc->t.cond) == 0){ - free(d); - return fserror(rpc, "false qid.path"); - } - if(cd.qid.vers != ~0UL && cmpulong(cd.qid.vers, d->qid.vers, rpc->t.cond) == 0){ - free(d); - return fserror(rpc, "false qid.vers"); - } - if(cd.mode != ~0 && cmpulong(cd.mode, d->mode, rpc->t.cond) == 0){ - free(d); - return fserror(rpc, "false mode"); - } - if(cd.atime != ~0 && cmpulong(cd.atime, d->atime, rpc->t.cond) == 0){ - free(d); - return fserror(rpc, "false atime"); - } - if(cd.mtime != ~0 && cmpulong(cd.mtime, d->mtime, rpc->t.cond) == 0){ - free(d); - return fserror(rpc, "false mtime"); - } - if(cd.length != ~0ULL && cmpulong(cd.length, d->length, rpc->t.cond)==0){ - free(d); - return fserror(rpc, "false length"); - } - if(cd.name != nil && cmpstr(cd.name, d->name, rpc->t.cond) == 0){ - free(d); - return fserror(rpc, "false name"); - } - if(cd.uid != nil && cmpstr(cd.uid, d->uid, rpc->t.cond) == 0){ - free(d); - return fserror(rpc, "false uid"); - } - if(cd.gid != nil && cmpstr(cd.gid, d->gid, rpc->t.cond) == 0){ - free(d); - return fserror(rpc, "false gid"); - } - if(cd.muid != nil && cmpstr(cd.muid, d->muid, rpc->t.cond) == 0){ - free(d); - return fserror(rpc, "false muid"); - } - free(d); + buf[n] = 0; + if(cmpstr(buf, buf2, rpc->t.op) == 0) + return fserror(rpc, "false"); return fsreply(rpc); } static int -fsfid(Rpc *rpc) +fsmove(Rpc *rpc) { - if(rpc->fid != nil) - putfid(rpc->fs, rpc->fid); - rpc->fid = getfid(rpc->fs, rpc->t.fid); - if(rpc->fid == nil) - return fserror(rpc, "no such fid"); - rpc->fid->cflags = rpc->t.cflags; - return fsreply(rpc); + if(rpc->ix == nil) + return fserror(rpc, "session not set"); + return fserror(rpc, "move not supported"); +} + +static int +fscopy(Rpc *rpc) +{ + if(rpc->ix == nil) + return fserror(rpc, "session not set"); + return fserror(rpc, "copy not supported"); +} + +static int +fsflush(Rpc *rpc) +{ + if(rpc->ix == nil) + return fserror(rpc, "session not set"); + return fserror(rpc, "abort the channel for flushing"); } typedef int (*Rpcfn)(Rpc*); static Rpcfn reqfn[Tmax] = { -[Tversion] fsversion, -[Tauth] fsauth, -[Tattach] fsattach, -[Tclone] fsclone, -[Twalk] fswalk, -[Topen] fsopen, -[Tcreate] fscreate, -[Tread] fsread, -[Twrite] fswrite, -[Tclunk] fsclunk, -[Tremove] fsremove, -[Tstat] fsstat, -[Twstat] fswstat, -[Tfid] fsfid, -[Tcond] fscond, +[IXTversion] fsversion, +[IXTsession] fssession, +[IXTsid] fssid, +[IXTendsession] fsendsession, +[IXTfid] fsfid, +[IXTattach] fsattach, +[IXTclone] fsclone, +[IXTwalk] fswalk, +[IXTopen] fsopen, +[IXTcreate] fscreate, +[IXTread] fsread, +[IXTwrite] fswrite, +[IXTclunk] fsclunk, +[IXTclose] fsclose, +[IXTremove] fsremove, +[IXTattr] fsattr, +[IXTwattr] fswattr, +[IXTcond] fscond, +[IXTmove] fsmove, +[IXTcopy] fscopy, +[IXTflush] fsflush, }; static int fsrpc(Rpc *rpc) { Msg *m; - int r; + int r, n; m = rpc->m; if(IOLEN(&m->io[0]) == 0){ dfprint("ch%d: eof\n", rpc->ch->id); goto Fail; } - if(unpack(m->io[0].rp, IOLEN(&m->io[0]), &rpc->t) <= 0){ + n = ixunpack(m->io[0].rp, IOLEN(&m->io[0]), &rpc->t); + if(n <= 0){ dfprint("ch%d: unknown message: %r\n", rpc->ch->id); goto Fail; } + m->io->rp += n; + switch(rpc->t.type){ + case IXTwrite: + rpc->t.count = IOLEN(m->io); + break; + case IXTwattr: + case IXTcond: + rpc->t.nvalue = IOLEN(m->io); + break; + } dfprint("<-ch%d%c %G\n", rpc->ch->id, rpc->last?'|':'-', &rpc->t); if(rpc->t.type >= nelem(reqfn) || reqfn[rpc->t.type] == nil){ dfprint("bad msg type %d\n", rpc->t.type); @@ -691,14 +891,15 @@ Rpc rpc; c = a; + threadsetname("fsrpcproc fs %p ch %p", rpc.fs, rpc.ch); + memset(&rpc, 0, sizeof rpc); rpc.fid = nil; rpc.fs = recvp(c); rpc.ch = recvp(c); - rpc.last = 0; - threadsetname("fsrpcproc fs %p ch %p", rpc.fs, rpc.ch); id = rpc.ch->id; dfprint("fsrpc[%p!%d]: new chan %s\n", rpc.fs->s, id, rpc.fs->s->addr); while((rpc.m = chrecv(rpc.ch, &rpc.last)) != nil){ + qlock(&hugelock); waslast = rpc.last; if(fsrpc(&rpc) < 0 && !waslast){ drainch(rpc.ch); @@ -706,10 +907,15 @@ } if(rpc.last) break; + qunlock(&hugelock); } if(rpc.fid != nil) - putfid(rpc.fs, rpc.fid); - dfprint("fsrpc[%p!%d]: done\n", rpc.fs->s, id); + putfid(rpc.ix, rpc.fid); + if(rpc.ix != nil) + putses(rpc.ix); + qunlock(&hugelock); + dfprint("fsrpc[%p!%d]: done.\n", rpc.fs->s, id); + dfprint("%d fids in use; %d files in use\n", nfids, ixnfiles); threadexits(nil); } @@ -718,7 +924,6 @@ { Fs fs; Ch *ch; - int i; threadsetname("fssrvproc %p", a); dfprint("fssrvproc[%p]: started\n", &fs); @@ -734,12 +939,10 @@ sendp(fs.argc, &fs); sendp(fs.argc, ch); } + /* mux released by itself */ closemux(fs.cm); chanfree(fs.argc); - /* mux released by itself */ - for(i = 0; i < fs.nfids; i++) - free(fs.fids[i]); - free(fs.fids); + killses(&fs); dfprint("fssrvproc[%p]: done\n", &fs); threadexits(nil); } @@ -770,19 +973,13 @@ continue; } dfprint("cmd: %s\n", cmd); - if(strcmp(cmd, "sync") == 0){ - filesync(); - fprint(fd, "synced\n"); - fprint(2, "synced\n"); - }else if(strcmp(cmd, "halt") == 0){ + if(strcmp(cmd, "halt") == 0){ free(cmd); break; }else fprint(fd, "%s?\n", cmd); free(cmd); } - fprint(2, "consproc: halting\n"); - filesync(); fprint(fd, "halted\n"); fprint(2, "halted\n"); dfprint("consproc done\n"); @@ -795,7 +992,7 @@ char *fn; int p[2], fd; - fn = esmprint("/srv/%s", srv); + fn = smprint("/srv/%s", srv); fd = create(fn, OWRITE|ORCLOSE|OCEXEC, 0660); if(fd < 0){ free(fn); @@ -811,7 +1008,7 @@ } void -fsinit(char *addr, char *srv) +ixinit(char *addr, char *srv) { ssrv = newsrv(addr); if(ssrv == nil) @@ -823,9 +1020,9 @@ } void -fssrv(void) +ixsrv(void) { - Ses *s; + Con *s; while((s = recvp(ssrv->newc)) != nil) threadcreate(fssrvproc, s, Stack); diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/ix.c --- a/sys/src/cmd/ix/ix.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/ix.c Thu Dec 01 11:19:13 2011 +0100 @@ -1,6 +1,5 @@ #include #include -#include #include #include @@ -10,10 +9,11 @@ #include "tses.h" #include "ch.h" #include "dbg.h" -#include "fs.h" -#include "file.h" +#include "ix.h" +#include "ixfile.h" #define SRVADDR "tcp!*!9999" +#define TESTDIR "/sys/src/cmd/ix/Testfs" int mainstacksize = Stack; @@ -53,13 +53,13 @@ else if(argc > 1) usage(); - fmtinstall('G', fscallfmt); - fmtinstall('D', dirfmt); + outofmemoryexits(1); + fmtinstall('G', ixcallfmt); fmtinstall('M', dirmodefmt); fmtinstall('T', filefmt); - fileinit("/usr/nemo/bin", 0); - fsinit(addr, srv); - fssrv(); + fileinit(TESTDIR); + ixinit(addr, srv); + ixsrv(); dtprint("testsrv: exiting\n"); threadexits(nil); } diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/ixget.c --- a/sys/src/cmd/ix/ixget.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/ixget.c Thu Dec 01 11:19:13 2011 +0100 @@ -1,42 +1,24 @@ /* * Test program for ix. - * Get files or directories. * + ! mk all + ! slay 8.ix 8.ixget 8.ixp |rc X/\[/D - ! mk all - ! slay 8.ix 8.ixget|rc + ! rm -r /usr/nemo/src/9/ixp/Testfs/* + ! 8.ixp -DDfn ! slay 8.ixget|rc - ! 8.ix -Dfn - ! 8.ix -Dfsn >/tmp/LOG >[2=1] & - tail -F /tmp/LOG & - >/tmp/SRV.out >[2=1] - ! ls -lq /usr/nemo/acme.dump /tmp/acme.dump - ! cd /tmp ; /usr/nemo/src/tram/8.ixget -fDsf acme.dump >[2=1] - ! cd /tmp ; /usr/nemo/src/tram/8.ixget -cDsf acme.dump>[2=1] - >/tmp/GET.out>[2=1] - ! cd /tmp ; /usr/nemo/src/tram/8.ixget -Df acme.dump - ! touch $home/acme.dump - >/tmp/PUT.out>[2=1] + ! cd /tmp ; /usr/nemo/src/9/ixp/8.ixget -Dstf acme.dump >[2=1] + ! cmp /tmp/acme.dump /sys/src/cmd/ix/test/acme.dump + ! cd /tmp ; /usr/nemo/src/9/ixp/8.ixget -pDstf adump>[2=1] + ! cmp /tmp/adump /sys/src/cmd/ix/test/adump ! tstack 8.ix ! tstack 8.ixget - ! leak -s 8.ix|rc|acid 8.ix - ! leak -s 8.ixget|rc|acid 8.ixget - ! unmount /tmp/acme.dump /usr/nemo/acme.dump - ! cmp /tmp/ohist /usr/nemo/ohist - ! cmp /tmp/adump /usr/nemo/adump - ! rm -f /tmp/^(acme.dump PULL ohist) /usr/nemo/adump - * - * Issues: - * - test unexpected server errors - * - test unexpected client errors - * - adapt to test cond - * e.g.: get if newer, get if vers newer - * and clunk + ! 8.ix -Dfn + */ #include #include -#include #include #include @@ -46,7 +28,7 @@ #include "tses.h" #include "ch.h" #include "dbg.h" -#include "fs.h" +#include "ix.h" #include "ixreqs.h" #define CLIADDR "tcp!localhost!9999" @@ -54,13 +36,15 @@ int mainstacksize = Stack; static Cmux *cm; -static Ses *ses; +static Con *ses; Mpool *pool, *spool; static Channel *wc; static int rootfid = -1; static ulong msz; static int doflush; static int twritehdrsz; +static int tcondhdrsz; +static int ssid; static long wdata(int fd, void *a, long cnt, uvlong off) @@ -69,25 +53,148 @@ return pwrite(fd, a, cnt, off); } -static long -wdent(int fd, void *a, long cnt, uvlong) +static void +printfile(char *s, char *e) { - Dir d; - int n; - char buf[512]; - uchar *data; - long tot; + char *str, *val; - data = a; - for(tot = 0; tot < cnt; tot += n){ - n = convM2D(data+tot, cnt-tot, &d, buf); - if(n <= BIT32SZ) - break; - fprint(fd, "%D\n", &d); + print("dir:\n"); + while(s < e){ + s = (char*)gstring((uchar*)s, (uchar*)e, &str); + if(s == nil) + return; + s = (char*)gstring((uchar*)s, (uchar*)e, &val); + if(s == nil) + return; + if(strcmp(str, "name") == 0 || strcmp(str, "uid") == 0 || + strcmp(str, "gid") == 0 || strcmp(str, "muid") == 0) + print("\t[%s] = '%s'\n", str, val); + else if(strcmp(str, "mode") == 0) + print("\t[%s] = %M\n", str, GBIT32(val)); + else + print("\t[%s] = %#ullx\n", str, GBIT64(val)); } - return cnt; } +static void +printdir(char *buf, int count) +{ + int tot, n; + + for(tot = 0; tot < count; tot += n){ + if(count-tot < BIT32SZ) + break; + n = GBIT32(buf+tot); + tot += BIT32SZ; + if(tot+n > count){ + print("wrong count in dir entry\n"); + break; + } + printfile(buf+tot, buf+tot+n); + } +} + +static void +getstat(Ch *ch, int last) +{ + ixtattr(ch, "name", last); + ixtattr(ch, "path", last); + ixtattr(ch, "vers", last); + ixtattr(ch, "atime", last); + ixtattr(ch, "prev", last); + ixtattr(ch, "length", last); + ixtattr(ch, "mode", last); + ixtattr(ch, "uid", last); + ixtattr(ch, "gid", last); + ixtattr(ch, "muid", last); +} + +static int +gotu64(Ch *ch, uvlong *ip) +{ + Msg *m; + + m = ixrattr(ch); + if(m == nil) + return -1; + if(IOLEN(m->io) < BIT64SZ){ + freemsg(m); + return -1; + } + *ip = GBIT64(m->io->rp); + freemsg(m); + return 0; +} + +static int +gotu32(Ch *ch, ulong *ip) +{ + Msg *m; + + m = ixrattr(ch); + if(m == nil) + return -1; + if(IOLEN(m->io) < BIT32SZ){ + freemsg(m); + return -1; + } + *ip = GBIT32(m->io->rp); + freemsg(m); + return 0; +} + +static int +gotstr(Ch *ch, char **cp) +{ + Msg *m; + + m = ixrattr(ch); + if(m == nil) + return -1; + if(IOLEN(m->io) == 0){ + freemsg(m); + return -1; + } + *m->io->wp = 0; /* BUG, but ok for this */ + *cp = strdup((char*)m->io->rp); + freemsg(m); + return 0; +} + +static int +gotstat(Ch *ch, Dir *d) +{ + uvlong x; + + nulldir(d); + if(gotstr(ch, &d->name) < 0) + return -1; + if(gotu64(ch, &d->qid.path) < 0) + return -1; + if(gotu64(ch, &x) < 0) + return -1; + d->qid.vers = x; + if(gotu64(ch, &x) < 0) + return -1; + d->atime = x; + if(gotu64(ch, &x) < 0) + return -1; + /* prev */ + if(gotu64(ch, (uvlong*)&d->length) < 0) + return -1; + if(gotu32(ch, &d->mode) < 0) + return -1; + if(gotstr(ch, &d->uid) < 0) + return -1; + if(gotstr(ch, &d->gid) < 0) + return -1; + if(gotstr(ch, &d->muid) < 0) + return -1; + + d->qid.type = ((d->mode >>24) & 0xFF); + return 0; +} + /* * If doflush, this will test a flush (abortch) before * retrieving all data. @@ -100,11 +207,10 @@ static void getproc(void *a) { - char *path, *els[64], *fn; - int nels, fd, i; + char *path, *els[64], *fn, *dirbuf; + int nels, fd; Ch *ch; Dir d; - char buf[512]; long nr; uvlong offset; Msg *m; @@ -113,36 +219,40 @@ threadsetname("getproc %s", path); if(*path == '/') path++; - path = estrdup(path); + path = strdup(path); nels = getfields(path, els, nelem(els), 1, "/"); if(nels < 1) sysfatal("short path"); fn = els[nels-1]; ch = newch(cm); - xtfid(ch, rootfid, 0); - xtclone(ch, OCEND|OCERR, 0); - for(i = 0; i < nels; i++) - xtwalk(ch, els[i], 0); - xtstat(ch, 0); - xtopen(ch, OREAD, 0); - xtread(ch, -1, 0ULL, msz, 1); + ixtsid(ch, ssid, 0); + ixtfid(ch, rootfid, 0); + ixtclone(ch, OCEND|OCERR, 0); + ixtwalk(ch, nels, els, 0); + getstat(ch, 0); + ixtopen(ch, OREAD, 0); + ixtread(ch, -1, msz, 0ULL, 1); /* fid automatically clunked on errors and eof */ + dirbuf = nil; fd = -1; - if(xrfid(ch) < 0){ + if(ixrsid(ch) < 0){ + fprint(2, "%s: sid: %r\n", a); + goto Done; + } + if(ixrfid(ch) < 0){ fprint(2, "%s: fid: %r\n", a); goto Done; } - if(xrclone(ch) < 0){ + if(ixrclone(ch, nil) < 0){ fprint(2, "%s: clone: %r\n", a); goto Done; } - for(i = 0; i < nels; i++) - if(xrwalk(ch, nil) < 0){ - fprint(2, "%s: walk[%s]: %r\n", a, els[i]); - goto Done; - } - if(xrstat(ch, &d, buf) < 0){ + if(ixrwalk(ch) < 0){ + fprint(2, "%s: walk: %r\n", a); + goto Done; + } + if(gotstat(ch, &d) < 0){ fprint(2, "%s: stat: %r\n", a); goto Done; } @@ -153,7 +263,7 @@ fprint(2, "create %s: %r\n", fn); goto Done; } - if(xropen(ch) < 0){ + if(ixropen(ch) < 0){ fprint(2, "%s: open: %r\n", a); goto Done; } @@ -164,28 +274,34 @@ abortch(ch); goto Done; } - m = xrread(ch); + m = ixrread(ch); if(m == nil){ fprint(2, "%s: read: %r\n", a); goto Done; } nr = IOLEN(m->io); if(nr > 0) - if(d.qid.type&QTDIR) - nr = wdent(fd, m->io->rp, nr, offset); - else + if(d.qid.type&QTDIR){ + dirbuf = realloc(dirbuf, offset+nr); + memmove(dirbuf+offset, m->io->rp, nr); + }else nr = wdata(fd, m->io->rp, nr, offset); offset += nr; freemsg(m); }while(nr > 0); close(fd); fd = -1; - + if(dirbuf != nil){ + printdir(dirbuf, offset); + free(dirbuf); + dirbuf = nil; + } Done: if(fd >= 0){ close(fd); remove(fn); } + free(dirbuf); sendul(wc, 0); free(path); threadexits(nil); @@ -195,11 +311,10 @@ static void condproc(void *a) { - char *path, *els[64], *fn; - int nels, fd, i; + char *path, *els[64], *fn, *dirbuf; + int nels, fd; Ch *ch; Dir d; - char buf[512]; long nr; uvlong offset; Dir *ld; @@ -209,7 +324,7 @@ threadsetname("condproc %s", path); if(*path == '/') path++; - path = estrdup(path); + path = strdup(path); nels = getfields(path, els, nelem(els), 1, "/"); if(nels < 1) sysfatal("short path"); @@ -218,38 +333,45 @@ if(ld == nil) sysfatal("%s: dirstat: %r", fn); ch = newch(cm); - xtfid(ch, rootfid, 0); - xtclone(ch, OCEND|OCERR, 0); - for(i = 0; i < nels; i++) - xtwalk(ch, els[i], 0); + ixtsid(ch, ssid, 0); + ixtfid(ch, rootfid, 0); + ixtclone(ch, OCEND|OCERR, 0); + ixtwalk(ch, nels, els, 0); nulldir(&d); d.qid = ld->qid; - xtcond(ch, CNE, &d, 0); + m = newmsg(pool); + m->io->wp += tcondhdrsz; + PBIT64(m->io->wp, d.qid.path); m->io->wp += BIT64SZ; + ixtcond(ch, m, CEQ, "path", BIT64SZ+BIT32SZ+BIT8SZ, 0); free(ld); - xtstat(ch, 0); - xtopen(ch, OREAD, 0); - xtread(ch, -1, 0ULL, msz, 1); + getstat(ch, 0); + ixtopen(ch, OREAD, 0); + ixtread(ch, -1, msz, 0ULL, 1); /* fid automatically clunked on errors and eof */ + dirbuf = nil; fd = -1; - if(xrfid(ch) < 0){ + if(ixrsid(ch) < 0){ + fprint(2, "%s: sid: %r\n", a); + goto Done; + } + if(ixrfid(ch) < 0){ fprint(2, "%s: fid: %r\n", a); goto Done; } - if(xrclone(ch) < 0){ + if(ixrclone(ch, nil) < 0){ fprint(2, "%s: clone: %r\n", a); goto Done; } - for(i = 0; i < nels; i++) - if(xrwalk(ch, nil) < 0){ - fprint(2, "%s: walk[%s]: %r\n", a, els[i]); - goto Done; - } - if(xrcond(ch) < 0){ + if(ixrwalk(ch) < 0){ + fprint(2, "%s: walk: %r\n", a); + goto Done; + } + if(ixrcond(ch) < 0){ fprint(2, "%s: cond: %r\n", a); goto Done; } - if(xrstat(ch, &d, buf) < 0){ + if(gotstat(ch, &d) < 0){ fprint(2, "%s: stat: %r\n", a); goto Done; } @@ -260,65 +382,77 @@ fprint(2, "create %s: %r\n", fn); goto Done; } - if(xropen(ch) < 0){ + if(ixropen(ch) < 0){ fprint(2, "%s: open: %r\n", a); goto Done; } offset = 0ULL; do{ - m = xrread(ch); + m = ixrread(ch); if(m == nil){ fprint(2, "%s: read: %r\n", a); goto Done; } nr = IOLEN(m->io); if(nr > 0) - if(d.qid.type&QTDIR) - nr = wdent(fd, m->io->rp, nr, offset); - else + if(d.qid.type&QTDIR){ + dirbuf = realloc(dirbuf, offset+nr); + memmove(dirbuf+offset, m->io->rp, nr); + }else nr = wdata(fd, m->io->rp, nr, offset); offset += nr; freemsg(m); }while(nr > 0); close(fd); fd = -1; + if(dirbuf != nil){ + printdir(dirbuf, offset); + free(dirbuf); + dirbuf = nil; + } Done: if(fd >= 0){ close(fd); remove(fn); } + free(dirbuf); sendul(wc, 0); free(path); threadexits(nil); close(fd); } + static void settwritehdrsz(void) { - Fscall t; + IXcall t; - t.type = Twrite; - twritehdrsz = packedsize(&t); + t.type = IXTwrite; + twritehdrsz = ixpackedsize(&t); + t.type = IXTcond; + t.attr = "qid"; + tcondhdrsz = ixpackedsize(&t); } static void putproc(void *a) { char *path, *els[64], *fn; - int nels, fd, i, nw; + int nels, fd, nw; Ch *ch; Dir *d; long nr; Msg *m; uvlong offset; + uchar buf[BIT32SZ]; path = a; threadsetname("putproc %s", path); settwritehdrsz(); if(*path == '/') path++; - path = estrdup(path); + path = strdup(path); nels = getfields(path, els, nelem(els), 1, "/"); if(nels < 1) sysfatal("short path"); @@ -330,37 +464,52 @@ if(d == nil) sysfatal("%s: %r", fn); ch = newch(cm); - xtfid(ch, rootfid, 0); - xtclone(ch, OCEND|OCERR, 0); - for(i = 0; i < nels - 1; i++) - xtwalk(ch, els[i], 0); + ixtsid(ch, ssid, 0); + ixtfid(ch, rootfid, 0); + ixtclone(ch, OCEND|OCERR, 0); + if(nels > 1) + ixtwalk(ch, nels-1, els, 0); if(d->qid.type&QTDIR) - xtcreate(ch, els[nels-1], OREAD, d->mode, 1); + ixtcreate(ch, els[nels-1], OREAD, d->mode, 1); else - xtcreate(ch, els[nels-1], OWRITE, d->mode, 0); + ixtcreate(ch, els[nels-1], OWRITE, d->mode, 0); /* fid automatically clunked on errors and eof */ - - if(xrfid(ch) < 0){ + PBIT32(buf, 0777); + ixtwattr(ch, "mode", buf, BIT32SZ, 0); + ixtwattr(ch, "gid", "planb", 5, 0); + if(ixrsid(ch) < 0){ + fprint(2, "%s: sid: %r\n", a); + goto Done; + } + if(ixrfid(ch) < 0){ fprint(2, "%s: fid: %r\n", a); closech(ch); goto Done; } - if(xrclone(ch) < 0){ + if(ixrclone(ch, nil) < 0){ fprint(2, "%s: clone: %r\n", a); closech(ch); goto Done; } - for(i = 0; i < nels-1; i++) - if(xrwalk(ch, nil) < 0){ - fprint(2, "%s: walk[%s]: %r\n", a, els[i]); - closech(ch); - goto Done; - } - if(xrcreate(ch) < 0){ + if(nels > 1 && ixrwalk(ch) < 0){ + fprint(2, "%s: walk: %r\n", a); + goto Done; + } + if(ixrcreate(ch) < 0){ fprint(2, "%s: create: %r\n", a); closech(ch); goto Done; } + if(ixrwattr(ch) < 0){ + fprint(2, "%s: wattr: %r\n", a); + closech(ch); + goto Done; + } + if(ixrwattr(ch) < 0){ + fprint(2, "%s: wattr: %r\n", a); + closech(ch); + goto Done; + } if((d->qid.type&QTDIR) == 0){ nw = 0; offset = 0ULL; @@ -372,11 +521,11 @@ if(nr <= 0){ if(nr < 0) fprint(2, "%s: read: %r", fn); - xtclunk(ch, 1); + ixtclose(ch, 1); break; } m->io->wp += nr; - if(xtwrite(ch, m, nr, offset, 0) < 0){ + if(ixtwrite(ch, m, nr, offset, offset+nr, 0) < 0){ closech(ch); drainch(ch); goto Done; @@ -389,7 +538,7 @@ */ if(nw > 10){ nw--; - if(xrwrite(ch) < 0){ + if(ixrwrite(ch, nil) < 0){ fprint(2, "%s: write: %r\n", a); closech(ch); goto Done; @@ -397,12 +546,12 @@ } } while(nw-- > 0) - if(xrwrite(ch) < 0){ + if(ixrwrite(ch, nil) < 0){ fprint(2, "%s: write: %r\n", a); closech(ch); goto Done; } - xrclunk(ch); + ixrclose(ch); } Done: if(fd >= 0) @@ -414,16 +563,22 @@ } static void -ixattach(char *user) +ixattach(char *) { Ch *ch; + char *u; + int afid; ch = newch(cm); - xtversion(ch, 0); - xtattach(ch, user, "main", 1); - if(xrversion(ch, &msz) < 0) + ixtversion(ch, 0); + ixtsession(ch, Nossid, getuser(), 0, 0); + ixtattach(ch, "main", 1); + if(ixrversion(ch, &msz) < 0) sysfatal("wrong ix version: %r"); - if(xrattach(ch, &rootfid) < 0) + if(ixrsession(ch, &ssid, &afid, &u) < 0) + sysfatal("can't set session: %r"); + print("session is %d %s %s \n", ssid, getuser(), u); + if(ixrattach(ch, &rootfid) < 0) sysfatal("can't attach: %r"); } @@ -474,14 +629,15 @@ }ARGEND; if(argc == 0 || doput + docond + doflush> 1) usage(); - fmtinstall('G', fscallfmt); + outofmemoryexits(1); + fmtinstall('G', ixcallfmt); fmtinstall('M', dirmodefmt); fmtinstall('D', dirfmt); ses = dialsrv(addr); if(ses == nil) sysfatal("dialsrv: %r"); - pool = newpool(Msgsz, argc*Nmsgs); - spool = newpool(Smsgsz, argc*Nmsgs); + pool = newpool(Msgsz, Nmsgs); + spool = newpool(Smsgsz, Nmsgs); startses(ses, pool, spool); cm = muxses(ses->rc, ses->wc, ses->ec); ixattach(getuser()); diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/ixreqs.c --- a/sys/src/cmd/ix/ixreqs.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/ixreqs.c Thu Dec 01 11:19:13 2011 +0100 @@ -1,183 +1,177 @@ #include #include -#include #include #include - #include "conf.h" #include "msg.h" #include "mpool.h" #include "tses.h" #include "ch.h" #include "dbg.h" -#include "fs.h" +#include "ix.h" #include "ixreqs.h" static int -sendreq(Ch *ch, Fscall *t, Msg *m, int last) +sendreq(Ch *ch, IXcall *t, Msg *m, int last) { int n; /* - * Twrite reads data directly after the packed T call, - * and sets io's rp and wp by itself. + * Twrite and Twattr read data directly after the packed T call, + * and set io's rp and wp by themselves. * Requests using strings like Tattach, Twalk, may not * fit in a small Msg if strings are large, in which case * we try using a large buffer before failing. */ dfprint("%cch%d-> %G\n", last?'|':'-', ch->id, t); - if(t->type != Twrite){ - n = pack(t, m->io->wp, IOCAP(m->io)); + if(t->type != IXTwrite && t->type != IXTwattr && t->type != IXTcond){ + n = ixpack(t, m->io->wp, IOCAP(m->io)); if(n < 0 && IOCAP(m->io) < Msgsz){ /* try with a large buffer */ freemsg(m); m = newmsg(pool); - n = pack(t, m->io->wp, IOCAP(m->io)); + n = ixpack(t, m->io->wp, IOCAP(m->io)); } }else - n = pack(t, m->io->bp, packedsize(t)); + n = ixpack(t, m->io->bp, ixpackedsize(t)); if(n <= 0) sysfatal("sendreq: pack"); - if(t->type != Twrite) + if(t->type != IXTwrite && t->type != IXTwattr && t->type != IXTcond) m->io->wp += n; return chsend(ch, m, last); } int -xtversion(Ch *ch, int last) +ixtversion(Ch *ch, int last) { - Fscall t; + IXcall t; Msg *m; m = newmsg(spool); - t.type = Tversion; + t.type = IXTversion; t.msize = Msgsz; - t.version = "ix"; + t.version = "3.1415926P"; return sendreq(ch, &t, m, last); } int -xtattach(Ch *ch, char *uname, char *aname, int last) +ixtsession(Ch *ch, int ssid, char *u, int keep, int last) { - Fscall t; + IXcall t; Msg *m; m = newmsg(spool); - t.type = Tattach; - t.afid = -1; - t.uname = uname; + t.type = IXTsession; + t.ssid = ssid; + t.uname = u; + t.keep = keep; + return sendreq(ch, &t, m, last); +} + +int +ixtsid(Ch *ch, int ssid, int last) +{ + IXcall t; + Msg *m; + + m = newmsg(spool); + t.type = IXTsid; + t.ssid = ssid; + return sendreq(ch, &t, m, last); +} + +static int +ixtmsg(Ch *ch, int type, int last) +{ + IXcall t; + Msg *m; + + m = newmsg(spool); + t.type = type; + return sendreq(ch, &t, m, last); +} + +int +ixtendsession(Ch *ch, int last) +{ + return ixtmsg(ch, IXTendsession, last); +} + +int +ixtfid(Ch *ch, int fid, int last) +{ + IXcall t; + Msg *m; + + m = newmsg(spool); + t.type = IXTfid; + t.fid = fid; + return sendreq(ch, &t, m, last); +} + +int +ixtattach(Ch *ch, char *aname, int last) +{ + IXcall t; + Msg *m; + + m = newmsg(spool); + t.type = IXTattach; t.aname = aname; return sendreq(ch, &t, m, last); } int -xtfid(Ch *ch, int fid, int last) +ixtclone(Ch *ch, int cflags, int last) { - Fscall t; + IXcall t; Msg *m; m = newmsg(spool); - t.type = Tfid; - t.fid = fid; - t.cflags = 0; - return sendreq(ch, &t, m, last); -} - -int -xtclone(Ch *ch, int cflags, int last) -{ - Fscall t; - Msg *m; - - m = newmsg(spool); - t.type = Tclone; + t.type = IXTclone; t.cflags = cflags; return sendreq(ch, &t, m, last); } int -xtclunk(Ch *ch, int last) +ixtwalk(Ch *ch, int nel, char **elem, int last) { - Fscall t; + IXcall t; Msg *m; + int i; m = newmsg(spool); - t.type = Tclunk; + t.type = IXTwalk; + t.nwname = nel; + if(nel > Nwalks) + sysfatal("ixtwalk: bug: too many elems"); + + for(i = 0; i < nel; i++) + t.wname[i] = elem[i]; return sendreq(ch, &t, m, last); } int -xtremove(Ch *ch, int last) +ixtopen(Ch *ch, int mode, int last) { - Fscall t; + IXcall t; Msg *m; m = newmsg(spool); - t.type = Tremove; - return sendreq(ch, &t, m, last); -} - -int -xtwalk(Ch *ch, char *elem, int last) -{ - Fscall t; - Msg *m; - - m = newmsg(spool); - t.type = Twalk; - t.wname = elem; - return sendreq(ch, &t, m, last); -} - - -int -xtstat(Ch *ch, int last) -{ - Fscall t; - Msg *m; - - m = newmsg(spool); - t.type = Tstat; - return sendreq(ch, &t, m, last); -} - -int -xtopen(Ch *ch, int mode, int last) -{ - Fscall t; - Msg *m; - - m = newmsg(spool); - t.type = Topen; + t.type = IXTopen; t.mode = mode; return sendreq(ch, &t, m, last); } int -xtread(Ch *ch, long count, uvlong offset, long msz, int last) +ixtcreate(Ch *ch, char *name, int mode, int perm, int last) { - Fscall t; + IXcall t; Msg *m; m = newmsg(spool); - t.type = Tread; - t.offset = offset; - t.count = count; - if(msz != 0 && t.count > msz) - t.count = msz; - t.nmsg = -1; - return sendreq(ch, &t, m, last); -} - -int -xtcreate(Ch *ch, char *name, int mode, int perm, int last) -{ - Fscall t; - Msg *m; - - m = newmsg(spool); - t.type = Tcreate; + t.type = IXTcreate; t.name = name; t.perm = perm; t.mode = mode; @@ -185,51 +179,132 @@ } int -xtwrite(Ch *ch, Msg *m, long count, uvlong offset, int last) +ixtread(Ch *ch, int nmsg, long count, uvlong offset, int last) { - Fscall t; + IXcall t; + Msg *m; - t.type = Twrite; + m = newmsg(spool); + t.type = IXTread; + t.nmsg = nmsg; + t.count = count; t.offset = offset; - t.count = count; return sendreq(ch, &t, m, last); } int -xtcond(Ch *ch, int op, Dir *d, int last) +ixtwrite(Ch *ch, Msg *m, long count, uvlong offset, uvlong endoffset, int last) { - Fscall t; - Msg *m; - uchar buf[512]; + IXcall t; - m = newmsg(pool); - t.type = Tcond; - t.cond = op; - t.nstat = convD2M(d, buf, sizeof buf); - t.stat = buf; + t.type = IXTwrite; + t.offset = offset; + t.endoffset = endoffset; + t.count = count; + t.data = m->io->bp + ixpackedsize(&t); /* so fmt works */ return sendreq(ch, &t, m, last); } int -xtwstat(Ch *ch, Dir *d, int last) +ixtclunk(Ch *ch, int last) { - Fscall t; + return ixtmsg(ch, IXTclunk, last); +} + +int +ixtclose(Ch *ch, int last) +{ + return ixtmsg(ch, IXTclose, last); +} + +int +ixtremove(Ch *ch, int last) +{ + return ixtmsg(ch, IXTremove, last); +} + +int +ixtattr(Ch *ch, char *attr, int last) +{ + IXcall t; Msg *m; - uchar buf[512]; + m = newmsg(spool); + t.type = IXTattr; + t.attr = attr; + return sendreq(ch, &t, m, last); +} + +int +ixtwattr(Ch *ch, char *attr, void *data, long nvalue, int last) +{ + IXcall t; + Msg *m; + uchar *value; + + value = data; m = newmsg(pool); - t.type = Twstat; - t.nstat = convD2M(d, buf, sizeof buf); - t.stat = buf; + t.type = IXTwattr; + t.attr = attr; + t.nvalue = nvalue; + m->io->wp += ixpackedsize(&t); + t.value = m->io->wp; /* for fmt */ + memmove(m->io->wp, value, nvalue); + m->io->wp += nvalue; + return sendreq(ch, &t, m, last); +} + +int +ixtcond(Ch *ch, Msg *m, int op, char *attr, long nvalue, int last) +{ + IXcall t; + + t.type = IXTcond; + t.op = op; + t.attr = attr; + t.nvalue = nvalue; + return sendreq(ch, &t, m, last); +} + +int +ixtmove(Ch *ch, int dirfid, char *newname, int last) +{ + IXcall t; + Msg *m; + + m = newmsg(spool); + t.type = IXTmove; + t.dirfid = dirfid; + t.newname = newname; + return sendreq(ch, &t, m, last); +} + +int +ixtcopy(Ch *ch, int nmsg, long count, uvlong offset, long msz, + int dstfid, uvlong dstoffset, int last) +{ + IXcall t; + Msg *m; + + m = newmsg(spool); + t.type = IXTcopy; + t.offset = offset; + t.count = count; + if(msz != 0 && t.count > msz) + t.count = msz; + t.nmsg = nmsg; + t.dstfid = dstfid; + t.dstoffset = dstoffset; return sendreq(ch, &t, m, last); } static Msg* -getreply(Ch *ch, int type, Fscall *r) +getreply(Ch *ch, int type, IXcall *r) { Msg *m; int last, id, n; +Again: id = ch->id; /* ch is released if last */ m = chrecv(ch, &last); if(m == nil){ @@ -237,7 +312,7 @@ dfprint("getreply: %r\n"); return nil; } - n = unpack(m->io->rp, IOLEN(m->io), r); + n = ixunpack(m->io->rp, IOLEN(m->io), r); if(n <= 0){ werrstr("getreply: rp %#p wp %#p ep %#p %r", m->io->rp, m->io->wp, m->io->ep); dfprint("getreply: %r\n"); @@ -245,27 +320,52 @@ return nil; } m->io->rp += n; + + switch(r->type){ /* needed just for printing the reply */ + case IXRread: + case IXTwrite: + r->count = IOLEN(m->io); + break; + case IXRattr: + case IXTwattr: + case IXTcond: + r->nvalue = IOLEN(m->io); + break; + } + dfprint("<-ch%d%c %G\n", id, last?'|':'-', r); if(r->type == type) return m; - if(r->type == Rerror) + if(r->type == IXRerror) werrstr("%s", r->ename); - else + else{ werrstr("wrong reply type %d", r->type); + /* + * we could fail always here because we got an unexpected reply, + * but, this permits issuing requests, and then check the + * status on a later request without having to call the + * receive function for each request unless we are really + * interested in the reply. + */ + if(!last){ + freemsg(m); + goto Again; + } + } freemsg(m); return nil; } int -xrversion(Ch *ch, ulong *mszp) +ixrversion(Ch *ch, ulong *mszp) { Msg *m; - Fscall r; + IXcall r; - m = getreply(ch, Rversion, &r); + m = getreply(ch, IXRversion, &r); if(m == nil) return -1; - if(strcmp(r.version, "ix") != 0){ + if(strcmp(r.version, "3.1415926P") != 0){ werrstr("wrong version %s", r.version); freemsg(m); return -1; @@ -279,26 +379,31 @@ } int -xrattach(Ch *ch, int *fidp) +ixrsession(Ch *ch, int *ssid, int *afid, char **u) { Msg *m; - Fscall r; + IXcall r; - m = getreply(ch, Rattach, &r); + m = getreply(ch, IXRsession, &r); if(m == nil) return -1; - *fidp = r.fid; + if(ssid != nil) + *ssid = r.ssid; + if(afid != nil) + *afid = r.afid; + if(u != nil) + *u = strdup(r.uname); freemsg(m); return 0; } -int -xrfid(Ch *ch) +static int +ixrmsg(Ch *ch, int type) { Msg *m; - Fscall r; + IXcall r; - m = getreply(ch, Rfid, &r); + m = getreply(ch, type, &r); if(m == nil) return -1; freemsg(m); @@ -306,152 +411,162 @@ } int -xrclunk(Ch *ch) +ixrsid(Ch *ch) +{ + return ixrmsg(ch, IXRsid); +} + +int +ixrendsession(Ch *ch) +{ + return ixrmsg(ch, IXRendsession); +} + +int +ixrfid(Ch *ch) +{ + return ixrmsg(ch, IXRfid); +} + +int +ixrattach(Ch *ch, int *fidp) { Msg *m; - Fscall r; + IXcall r; - m = getreply(ch, Rclunk, &r); + m = getreply(ch, IXRattach, &r); if(m == nil) return -1; + if(fidp != nil) + *fidp = r.fid; freemsg(m); return 0; } int -xrremove(Ch *ch) +ixrclone(Ch *ch, int *fidp) { Msg *m; - Fscall r; + IXcall r; - m = getreply(ch, Rremove, &r); + m = getreply(ch, IXRclone, &r); if(m == nil) return -1; freemsg(m); + if(fidp != nil) + *fidp = r.fid; return 0; } int -xrclone(Ch *ch) +ixrwalk(Ch *ch) { - Msg *m; - Fscall r; - - m = getreply(ch, Rclone, &r); - if(m == nil) - return -1; - freemsg(m); - return r.fid; + return ixrmsg(ch, IXRwalk); } int -xrwalk(Ch *ch, Qid *qp) +ixropen(Ch *ch) { - Msg *m; - Fscall r; - - m = getreply(ch, Rwalk, &r); - if(m == nil) - return -1; - freemsg(m); - if(qp != nil) - *qp = r.wqid; - return 0; + return ixrmsg(ch, IXRopen); } int -xropen(Ch *ch) +ixrcreate(Ch *ch) +{ + return ixrmsg(ch, IXRcreate); +} + +Msg* +ixrread(Ch *ch) { Msg *m; - Fscall r; + IXcall r; - m = getreply(ch, Ropen, &r); + m = getreply(ch, IXRread, &r); + if(m == nil) + return nil; + r.count = IOLEN(m->io); /* unused */ + return m; +} + +long +ixrwrite(Ch *ch, uvlong *offsetp) +{ + Msg *m; + IXcall r; + + m = getreply(ch, IXRwrite, &r); if(m == nil) return -1; + if(offsetp) + *offsetp = r.offset; freemsg(m); - return 0; + return r.count; } int -xrstat(Ch *ch, Dir *d, char buf[]) +ixrclunk(Ch *ch) +{ + return ixrmsg(ch, IXRclunk); +} + +int +ixrclose(Ch *ch) +{ + return ixrmsg(ch, IXRclose); +} + +int +ixrremove(Ch *ch) +{ + return ixrmsg(ch, IXRremove); +} + +Msg* +ixrattr(Ch *ch) { Msg *m; - Fscall r; + IXcall r; - m = getreply(ch, Rstat, &r); - if(m == nil) - return -1; - if(convM2D(r.stat, r.nstat, d, buf) <= BIT32SZ) - return -1; - freemsg(m); - return 0; -} - - -Msg* -xrread(Ch *ch) -{ - Msg *m; - Fscall r; - - m = getreply(ch, Rread, &r); + m = getreply(ch, IXRattr, &r); if(m == nil) return nil; - m->io->rp -= r.count; + r.nvalue = IOLEN(m->io); /* unused */ return m; } int -xrcreate(Ch *ch) +ixrwattr(Ch *ch) { - Msg *m; - Fscall r; + return ixrmsg(ch, IXRwattr); +} - m = getreply(ch, Rcreate, &r); - if(m == nil) - return -1; - freemsg(m); - return 0; +int +ixrcond(Ch *ch) +{ + return ixrmsg(ch, IXRcond); +} + +int +ixrmove(Ch *ch) +{ + return ixrmsg(ch, IXRmove); } long -xrwrite(Ch *ch) +ixrcopy(Ch *ch) { Msg *m; - Fscall r; + IXcall r; - m = getreply(ch, Rwrite, &r); + m = getreply(ch, IXRcopy, &r); if(m == nil) return -1; freemsg(m); return r.count; } -int -xrcond(Ch *ch) -{ - Msg *m; - Fscall r; - - m = getreply(ch, Rcond, &r); - if(m == nil) - return -1; - freemsg(m); - return 0; -} - -int -xrwstat(Ch *ch) -{ - Msg *m; - Fscall r; - - m = getreply(ch, Rwstat, &r); - if(m == nil) - return -1; - freemsg(m); - return 0; -} - - - +/* + * NB: Tflush, Rflush are done by aborting the channel + * in this implementation. + */ diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/ixreqs.h --- a/sys/src/cmd/ix/ixreqs.h Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/ixreqs.h Thu Dec 01 11:19:13 2011 +0100 @@ -1,33 +1,45 @@ /* |c/f2p ixreqs.c */ -extern int xrattach(Ch *ch, int *fidp); -extern int xrclone(Ch *ch); -extern int xrclunk(Ch *ch); -extern int xrcond(Ch *ch); -extern int xrcreate(Ch *ch); -extern int xrfid(Ch *ch); -extern int xropen(Ch *ch); -extern Msg* xrread(Ch *ch); -extern int xrremove(Ch *ch); -extern int xrstat(Ch *ch, Dir *d, char buf[]); -extern int xrversion(Ch *ch, ulong *mszp); -extern int xrwalk(Ch *ch, Qid *qp); -extern long xrwrite(Ch *ch); -extern int xrwstat(Ch *ch); -extern int xtattach(Ch *ch, char *uname, char *aname, int last); -extern int xtclone(Ch *ch, int cflags, int last); -extern int xtclunk(Ch *ch, int last); -extern int xtcond(Ch *ch, int op, Dir *d, int last); -extern int xtcreate(Ch *ch, char *name, int mode, int perm, int last); -extern int xtfid(Ch *ch, int fid, int last); -extern int xtopen(Ch *ch, int mode, int last); -extern int xtread(Ch *ch, long count, uvlong offset, long msz, int last); -extern int xtremove(Ch *ch, int last); -extern int xtstat(Ch *ch, int last); -extern int xtversion(Ch *ch, int last); -extern int xtwalk(Ch *ch, char *elem, int last); -extern int xtwrite(Ch *ch, Msg *m, long count, uvlong offset, int last); -extern int xtwstat(Ch *ch, Dir *d, int last); +extern int ixrattach(Ch *ch, int *fidp); +extern Msg* ixrattr(Ch *ch); +extern int ixrclone(Ch *ch, int *fidp); +extern int ixrclose(Ch *ch); +extern int ixrclunk(Ch *ch); +extern int ixrcond(Ch *ch); +extern long ixrcopy(Ch *ch); +extern int ixrcreate(Ch *ch); +extern int ixrendsession(Ch *ch); +extern int ixrfid(Ch *ch); +extern int ixrmove(Ch *ch); +extern int ixropen(Ch *ch); +extern Msg* ixrread(Ch *ch); +extern int ixrremove(Ch *ch); +extern int ixrsession(Ch *ch, int *ssid, int *afid, char **u); +extern int ixrsid(Ch *ch); +extern int ixrversion(Ch *ch, ulong *mszp); +extern int ixrwalk(Ch *ch); +extern int ixrwattr(Ch *ch); +extern long ixrwrite(Ch *ch, uvlong *offsetp); +extern int ixtattach(Ch *ch, char *aname, int last); +extern int ixtattr(Ch *ch, char *attr, int last); +extern int ixtclone(Ch *ch, int cflags, int last); +extern int ixtclose(Ch *ch, int last); +extern int ixtclunk(Ch *ch, int last); +extern int ixtcond(Ch *ch, Msg *m, int op, char *attr, long nvalue, int last); +extern int ixtcopy(Ch *ch, int nmsg, long count, uvlong offset, long msz,int dstfid, uvlong dstoffset, int last); +extern int ixtcreate(Ch *ch, char *name, int mode, int perm, int last); +extern int ixtendsession(Ch *ch, int last); +extern int ixtfid(Ch *ch, int fid, int last); +extern int ixtmove(Ch *ch, int dirfid, char *newname, int last); +extern int ixtopen(Ch *ch, int mode, int last); +extern int ixtread(Ch *ch, int nmsg, long count, uvlong offset, int last); +extern int ixtremove(Ch *ch, int last); +extern int ixtsession(Ch *ch, int ssid, char *u, int keep, int last); +extern int ixtsid(Ch *ch, int ssid, int last); +extern int ixtversion(Ch *ch, int last); +extern int ixtwalk(Ch *ch, int nel, char **elem, int last); +extern int ixtwattr(Ch *ch, char *attr, void *value, long nvalue, int last); +extern int ixtwrite(Ch *ch, Msg *m, long count, uvlong offset, uvlong endoffset, int last); extern Mpool *pool, *spool; diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/mpool.c --- a/sys/src/cmd/ix/mpool.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/mpool.c Thu Dec 01 11:19:13 2011 +0100 @@ -2,7 +2,6 @@ #include #include #include /* chancreate */ -#include #include #include "conf.h" #include "msg.h" @@ -51,7 +50,9 @@ Mbuf *mb; int i; - mp = emalloc(sizeof *mp); + if(nmsg == 0) + sysfatal("newpool: called for 0 messages"); + mp = mallocz(sizeof *mp, 1); mp->msize = msize; mp->bc = echancreate(sizeof(Mbuf*), nmsg); for(i = 0; i < nmsg; i++){ diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/msg.c --- a/sys/src/cmd/ix/msg.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/msg.c Thu Dec 01 11:19:13 2011 +0100 @@ -4,7 +4,6 @@ #include #include #include /* chancreate */ -#include #include #include "conf.h" #include "msg.h" diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/msg.h --- a/sys/src/cmd/ix/msg.h Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/msg.h Thu Dec 01 11:19:13 2011 +0100 @@ -27,6 +27,7 @@ #define IOCAP(io) ((io)->ep - (io)->wp) /* |c/f2p msg.c */ +extern void dumpmsg(Msg *m); extern Channel* echancreate(int elsz, int n); extern void freemsg(Msg *m); extern void ioreset(Io *io); diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/pack.c --- a/sys/src/cmd/ix/pack.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/pack.c Thu Dec 01 11:19:13 2011 +0100 @@ -2,18 +2,27 @@ #include #include -#include "fs.h" +#include "ix.h" -/* - * This is convS2M, convM2S from libc, but: - * - without copying bytes in the case of packing a Rread or Twrite request. - * - Tattach as no fid, Rattach has a fid. - * - Twalk has an uchar (bool) to ask for a newfid, and has only wname - * - Rwalk has newfid and only a wqid. - */ +uchar* +pdata(uchar *p, uchar *s, int ns) +{ + if(s == nil){ + PBIT16(p, 0); + p += BIT16SZ; + return p; + } + /* + * We are moving the string before the length, + * so you can S2M a struct into an existing message + */ + memmove(p + BIT16SZ, s, ns); + PBIT16(p, ns); + p += ns + BIT16SZ; + return p; +} -static uchar* pstring(uchar *p, char *s) { @@ -36,20 +45,6 @@ return p; } -static -uchar* -pqid(uchar *p, Qid *q) -{ - PBIT8(p, q->type); - p += BIT8SZ; - PBIT32(p, q->vers); - p += BIT32SZ; - PBIT64(p, q->path); - p += BIT64SZ; - return p; -} - -static uint stringsz(char *s) { @@ -59,156 +54,173 @@ return BIT16SZ+strlen(s); } +/* + * Does NOT include the data bytes added past the packed + * message for IXRread, IXTwrite, IXTwattr, IXRattr + * This is so to save copying. + */ uint -packedsize(Fscall *f) +ixpackedsize(IXcall *f) { uint n; + int i; - n = 0; - n += BIT8SZ; /* type */ + n = BIT8SZ; /* type */ - switch(f->type) - { - case Tcond: - n += BIT8SZ; - n += BIT16SZ; - n += f->nstat; - break; - - case Tfid: - n += BIT32SZ; - n += BIT8SZ; - break; - - case Tclone: - n += BIT8SZ; - break; - - case Tversion: + switch(f->type){ + case IXTversion: + case IXRversion: n += BIT32SZ; n += stringsz(f->version); break; - case Tauth: + case IXTsession: + n += BIT16SZ; + n += stringsz(f->uname); + n += BIT8SZ; + break; + case IXRsession: + n += BIT16SZ; n += BIT32SZ; n += stringsz(f->uname); + break; + + case IXTsid: + n += BIT16SZ; + break; + case IXRsid: + break; + + case IXTendsession: + case IXRendsession: + break; + + case IXTfid: + n += BIT32SZ; + break; + case IXRfid: + break; + + case IXTattach: n += stringsz(f->aname); break; - - case Tattach: + case IXRattach: n += BIT32SZ; - n += stringsz(f->uname); - n += stringsz(f->aname); break; - case Twalk: - n += stringsz(f->wname); + case IXRerror: + n += stringsz(f->ename); break; - case Topen: + case IXTclone: n += BIT8SZ; break; + case IXRclone: + n += BIT32SZ; + break; - case Tcreate: + case IXTwalk: + n += BIT16SZ; + for(i=0; inwname; i++) + n += stringsz(f->wname[i]); + break; + case IXRwalk: + break; + + case IXTopen: + n += BIT8SZ; + break; + case IXRopen: + break; + + case IXTcreate: n += stringsz(f->name); n += BIT32SZ; n += BIT8SZ; break; + case IXRcreate: + break; - case Tread: + case IXTread: + n += BIT16SZ; + n += BIT64SZ; n += BIT32SZ; + break; + case IXRread: + /* data follows */ + break; + + case IXTwrite: + n += BIT64SZ; + n += BIT64SZ; + /* data follows */ + break; + case IXRwrite: n += BIT64SZ; n += BIT32SZ; break; - case Twrite: - n += BIT64SZ; - n += BIT32SZ; - /* n += f->count; */ + case IXTclunk: + case IXRclunk: + case IXTclose: + case IXRclose: + case IXTremove: + case IXRremove: break; - case Tclunk: - case Tremove: - case Tstat: + case IXTattr: + n += stringsz(f->attr); + break; + case IXRattr: + /* data follows */ break; - case Twstat: - n += BIT16SZ; - n += f->nstat; + case IXTwattr: + n += stringsz(f->attr); + /* value data follows */ break; -/* - */ - case Rcond: - case Rfid: + case IXRwattr: break; - case Rclone: + case IXTcond: + n += BIT8SZ; + n += stringsz(f->attr); + /* value data follows */ + break; + case IXRcond: + break; + + case IXTmove: + n += BIT32SZ; + n += stringsz(f->newname); + break; + case IXRmove: + break; + + case IXTcopy: n += BIT32SZ; break; - - case Rversion: - n += BIT32SZ; - n += stringsz(f->version); + case IXRcopy: break; - case Rerror: - n += stringsz(f->ename); + case IXTflush: + case IXRflush: break; - - case Rauth: - n += QIDSZ; - break; - - case Rattach: - n += BIT32SZ; - n += QIDSZ; - break; - - case Rwalk: - n += QIDSZ; - break; - - case Ropen: - case Rcreate: - n += QIDSZ; - n += BIT32SZ; - break; - - case Rread: - n += BIT32SZ; - /* n += f->count; */ - break; - - case Rwrite: - n += BIT32SZ; - break; - - case Rclunk: - case Rremove: - break; - - case Rstat: - n += BIT16SZ; - n += f->nstat; - break; - - case Rwstat: - break; - default: - sysfatal("packedsize: type %d", f->type); + sysfatal("packedsize: unknown type %d", f->type); } return n; } uint -pack(Fscall *f, uchar *ap, uint nap) +ixpack(IXcall *f, uchar *ap, uint nap) { uchar *p; uint size; + int i; - size = packedsize(f); + size = ixpackedsize(f); if(size == 0) return 0; if(size > nap) @@ -219,169 +231,178 @@ PBIT8(p, f->type); p += BIT8SZ; - switch(f->type) - { - case Tcond: - PBIT8(p, f->cond); - p += BIT8SZ; - PBIT16(p, f->nstat); - p += BIT16SZ; - memmove(p, f->stat, f->nstat); - p += f->nstat; + switch(f->type){ + case IXTversion: + case IXRversion: + PBIT32(p, f->msize); + p += BIT32SZ; + p = pstring(p, f->version); break; - case Tfid: + case IXTsession: + PBIT16(p, f->ssid); + p += BIT16SZ; + p = pstring(p, f->uname); + PBIT8(p, f->keep); + p += BIT8SZ; + break; + case IXRsession: + PBIT16(p, f->ssid); + p += BIT16SZ; + PBIT32(p, f->afid); + p += BIT32SZ; + p = pstring(p, f->uname); + break; + + case IXTsid: + PBIT16(p, f->ssid); + p += BIT16SZ; + break; + case IXRsid: + break; + + case IXTendsession: + case IXRendsession: + break; + + case IXTfid: PBIT32(p, f->fid); p += BIT32SZ; + break; + case IXRfid: + break; + + case IXTattach: + p = pstring(p, f->aname); + break; + case IXRattach: + PBIT32(p, f->fid); + p += BIT32SZ; + break; + + case IXRerror: + p = pstring(p, f->ename); + break; + + case IXTclone: PBIT8(p, f->cflags); p += BIT8SZ; break; - - case Tclone: - PBIT8(p, f->cflags); - p += BIT8SZ; + case IXRclone: + PBIT32(p, f->fid); + p += BIT32SZ; break; - case Tversion: - PBIT32(p, f->msize); - p += BIT32SZ; - p = pstring(p, f->version); + case IXTwalk: + PBIT16(p, f->nwname); + p += BIT16SZ; + for(i=0; inwname; i++) + p = pstring(p, f->wname[i]); + break; + case IXRwalk: break; - case Tauth: - PBIT32(p, f->afid); - p += BIT32SZ; - p = pstring(p, f->uname); - p = pstring(p, f->aname); - break; - - case Tattach: - PBIT32(p, f->afid); - p += BIT32SZ; - p = pstring(p, f->uname); - p = pstring(p, f->aname); - break; - - case Twalk: - p = pstring(p, f->wname); - break; - - case Topen: + case IXTopen: PBIT8(p, f->mode); p += BIT8SZ; break; + case IXRopen: + break; - case Tcreate: - p = pstring(p, f->name); + case IXTcreate: + p = pstring(p, f->name); PBIT32(p, f->perm); p += BIT32SZ; PBIT8(p, f->mode); p += BIT8SZ; break; + case IXRcreate: + break; - case Tread: - PBIT32(p, f->nmsg); + case IXTread: + PBIT16(p, f->nmsg); + p += BIT16SZ; + PBIT64(p, f->offset); + p += BIT64SZ; + PBIT32(p, f->count); p += BIT32SZ; + break; + case IXRread: + /* data follows */ + break; + + case IXTwrite: + PBIT64(p, f->offset); + p += BIT64SZ; + PBIT64(p, f->endoffset); + p += BIT64SZ; + /* data follows */ + break; + case IXRwrite: PBIT64(p, f->offset); p += BIT64SZ; PBIT32(p, f->count); p += BIT32SZ; break; - case Twrite: + case IXTclunk: + case IXRclunk: + case IXTclose: + case IXRclose: + case IXTremove: + case IXRremove: + break; + + case IXTattr: + p = pstring(p, f->attr); + break; + case IXRattr: + /* value data follows */ + break; + + case IXTwattr: + p = pstring(p, f->attr); + /* value data follows */ + break; + case IXRwattr: + break; + + case IXTcond: + PBIT8(p, f->op); + p += BIT8SZ; + p = pstring(p, f->attr); + /* value data follows */ + break; + case IXRcond: + break; + + case IXTmove: + PBIT32(p, f->dirfid); + p += BIT32SZ; + p = pstring(p, f->newname); + break; + case IXRmove: + break; + + case IXTcopy: + PBIT16(p, f->nmsg); + p += BIT16SZ; PBIT64(p, f->offset); p += BIT64SZ; PBIT32(p, f->count); p += BIT32SZ; - /* - * Data added by the caller. - * memmove(p, f->data, f->count); - * p += f->count; - */ + PBIT32(p, f->dstfid); + p += BIT32SZ; + PBIT64(p, f->dstoffset); + p += BIT64SZ; break; - - case Tclunk: - case Tremove: - case Tstat: - break; - - case Twstat: - PBIT16(p, f->nstat); - p += BIT16SZ; - memmove(p, f->stat, f->nstat); - p += f->nstat; - break; -/* - * replies - */ - - case Rcond: - case Rfid: - break; - - case Rclone: - PBIT32(p, f->newfid); - p += BIT32SZ; - break; - - case Rversion: - PBIT32(p, f->msize); - p += BIT32SZ; - p = pstring(p, f->version); - break; - - case Rerror: - p = pstring(p, f->ename); - break; - - case Rauth: - p = pqid(p, &f->aqid); - break; - - case Rattach: - PBIT32(p, f->fid); - p += BIT32SZ; - p = pqid(p, &f->qid); - break; - - case Rwalk: - p = pqid(p, &f->wqid); - break; - - case Ropen: - case Rcreate: - p = pqid(p, &f->qid); - PBIT32(p, f->iounit); - p += BIT32SZ; - break; - - case Rread: - PBIT32(p, f->count); - p += BIT32SZ; - /* - * data is added by the caller. - * memmove(p, f->data, f->count); - * p += f->count; - */ - break; - - case Rwrite: + case IXRcopy: PBIT32(p, f->count); p += BIT32SZ; break; - case Rclunk: - case Rremove: - break; - - case Rstat: - PBIT16(p, f->nstat); - p += BIT16SZ; - memmove(p, f->stat, f->nstat); - p += f->nstat; - break; - - case Rwstat: + case IXTflush: + case IXRflush: break; default: @@ -393,7 +414,6 @@ return size; } -static uchar* gstring(uchar *p, uchar *ep, char **s) { @@ -413,35 +433,28 @@ return p; } -static uchar* -gqid(uchar *p, uchar *ep, Qid *q) +gdata(uchar *p, uchar *ep, uchar **s, int *ns) { - if(p+QIDSZ > ep) + uint n; + + if(p+BIT16SZ > ep) return nil; - q->type = GBIT8(p); - p += BIT8SZ; - q->vers = GBIT32(p); - p += BIT32SZ; - q->path = GBIT64(p); - p += BIT64SZ; + n = GBIT16(p); + *ns = n; + p += BIT16SZ; + if(p+n > ep) + return nil; + *s = p; + p += n; return p; } -/* - * no syntactic checks. - * three causes for error: - * 1. message size field is incorrect - * 2. input buffer too short for its own data (counts too long, etc.) - * 3. too many names or qids - * gqid() and gstring() return nil if they would reach beyond buffer. - * main switch statement checks range and also can fall through - * to test at end of routine. - */ uint -unpack(uchar *ap, uint nap, Fscall *f) +ixunpack(uchar *ap, uint nap, IXcall *f) { uchar *p, *ep; + int i; p = ap; ep = p + nap; @@ -454,42 +467,9 @@ f->type = GBIT8(p); p += BIT8SZ; - switch(f->type) - { - default: - werrstr("unknown type %d", f->type); - return 0; - - case Tcond: - if(p+BIT8SZ+BIT16SZ > ep) - return 0; - f->cond = GBIT8(p); - p += BIT8SZ; - f->nstat = GBIT16(p); - p += BIT16SZ; - if(p+f->nstat > ep) - return 0; - f->stat = p; - p += f->nstat; - break; - - case Tfid: - if(p+BIT32SZ+BIT8SZ > ep) - return 0; - f->fid = GBIT32(p); - p += BIT32SZ; - f->cflags = GBIT8(p); - p += BIT8SZ; - break; - - case Tclone: - if(p+BIT8SZ > ep) - return 0; - f->cflags = GBIT8(p); - p += BIT8SZ; - break; - - case Tversion: + switch(f->type){ + case IXTversion: + case IXRversion: if(p+BIT32SZ > ep) return 0; f->msize = GBIT32(p); @@ -497,46 +477,101 @@ p = gstring(p, ep, &f->version); break; - case Tauth: - if(p+BIT32SZ > ep) + case IXTsession: + if(p+BIT16SZ > ep) return 0; + f->ssid = GBIT16(p); + p += BIT16SZ; + p = gstring(p, ep, &f->uname); + if(p == nil) + return 0; + if(p+BIT8SZ > ep) + return 0; + f->keep = GBIT8(p); + p += BIT8SZ; + break; + case IXRsession: + if(p+BIT16SZ+BIT32SZ > ep) + return 0; + f->ssid = GBIT16(p); + p += BIT16SZ; f->afid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->uname); - if(p == nil) - break; - p = gstring(p, ep, &f->aname); - if(p == nil) - break; break; - case Tattach: + case IXTsid: + if(p+BIT16SZ > ep) + return 0; + f->ssid = GBIT16(p); + p += BIT16SZ; + break; + case IXRsid: + break; + + case IXTendsession: + case IXRendsession: + break; + + case IXTfid: if(p+BIT32SZ > ep) return 0; - f->afid = GBIT32(p); + f->fid = GBIT32(p); p += BIT32SZ; - p = gstring(p, ep, &f->uname); - if(p == nil) - break; - p = gstring(p, ep, &f->aname); - if(p == nil) - break; + break; + case IXRfid: break; - case Twalk: - p = gstring(p, ep, &f->wname); - if(p == nil) - break; + case IXTattach: + p = gstring(p, ep, &f->aname); + break; + case IXRattach: + if(p+BIT32SZ > ep) + return 0; + f->fid = GBIT32(p); + p += BIT32SZ; break; - case Topen: + case IXRerror: + p = gstring(p, ep, &f->ename); + break; + + case IXTclone: + if(p+BIT8SZ > ep) + return 0; + f->cflags = GBIT8(p); + p += BIT8SZ; + break; + case IXRclone: + if(p+BIT32SZ > ep) + return 0; + f->fid = GBIT32(p); + p += BIT32SZ; + break; + + case IXTwalk: + if(p+BIT16SZ > ep) + return 0; + f->nwname = GBIT16(p); + p += BIT16SZ; + if(f->nwname > Nwalks) + sysfatal("unpack: bug: too many walk elems"); + for(i=0; inwname && p != nil; i++) + p = gstring(p, ep, &f->wname[i]); + break; + case IXRwalk: + break; + + case IXTopen: if(p+BIT8SZ > ep) return 0; f->mode = GBIT8(p); p += BIT8SZ; break; + case IXRopen: + break; - case Tcreate: + case IXTcreate: p = gstring(p, ep, &f->name); if(p == nil) break; @@ -547,140 +582,116 @@ f->mode = GBIT8(p); p += BIT8SZ; break; + case IXRcreate: + break; - case Tread: - if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) + case IXTread: + if(p+BIT16SZ+BIT64SZ+BIT32SZ > ep) return 0; - f->nmsg = GBIT32(p); + f->nmsg = GBIT16(p); + p += BIT16SZ; + f->offset = GBIT64(p); + p += BIT64SZ; + f->count = GBIT32(p); p += BIT32SZ; + break; + case IXRread: + f->data = p; + break; + + case IXTwrite: + if(p+BIT64SZ > ep) + return 0; + f->offset = GBIT64(p); + p += BIT64SZ; + f->endoffset = GBIT64(p); + p += BIT64SZ; + f->data = p; + break; + case IXRwrite: + if(p+BIT32SZ+BIT64SZ > ep) + return 0; f->offset = GBIT64(p); p += BIT64SZ; f->count = GBIT32(p); p += BIT32SZ; break; - case Twrite: - if(p+BIT64SZ+BIT32SZ > ep) + case IXTclunk: + case IXRclunk: + case IXTclose: + case IXRclose: + case IXTremove: + case IXRremove: + break; + + case IXTattr: + p = gstring(p, ep, &f->attr); + break; + case IXRattr: + f->value = p; + break; + + case IXTwattr: + p = gstring(p, ep, &f->attr); + if(p == nil) return 0; + f->value = p; + break; + case IXRwattr: + break; + + case IXTcond: + if(p+BIT8SZ > ep) + return 0; + f->op = GBIT8(p); + p += BIT8SZ; + p = gstring(p, ep, &f->attr); + if(p == nil) + return 0; + f->value = p; + break; + case IXRcond: + break; + + case IXTmove: + if(p+BIT32SZ > ep) + return 0; + f->dirfid = GBIT32(p); + p += BIT32SZ; + p = gstring(p, ep, &f->newname); + break; + case IXRmove: + break; + + case IXTcopy: + if(p+BIT16SZ+BIT64SZ+BIT32SZ + BIT32SZ+BIT64SZ > ep) + return 0; + f->nmsg = GBIT16(p); + p += BIT16SZ; f->offset = GBIT64(p); p += BIT64SZ; f->count = GBIT32(p); p += BIT32SZ; - if(p+f->count > ep) - return 0; - f->data = (char*)p; - p += f->count; + f->dstfid = GBIT32(p); + p += BIT32SZ; + f->dstoffset = GBIT64(p); + p += BIT64SZ; break; - - case Tclunk: - case Tremove: - case Tstat: - break; - - case Twstat: - if(p+BIT16SZ > ep) - return 0; - f->nstat = GBIT16(p); - p += BIT16SZ; - if(p+f->nstat > ep) - return 0; - f->stat = p; - p += f->nstat; - break; - -/* - */ - case Rfid: - case Rcond: - break; - - case Rclone: - if(p+BIT32SZ > ep) - return 0; - f->newfid = GBIT32(p); - p += BIT32SZ; - break; - - case Rversion: - if(p+BIT32SZ > ep) - return 0; - f->msize = GBIT32(p); - p += BIT32SZ; - p = gstring(p, ep, &f->version); - break; - - case Rerror: - p = gstring(p, ep, &f->ename); - break; - - case Rauth: - p = gqid(p, ep, &f->aqid); - if(p == nil) - break; - break; - - case Rattach: - if(p+BIT32SZ > ep) - return 0; - f->fid = GBIT32(p); - p += BIT32SZ; - p = gqid(p, ep, &f->qid); - if(p == nil) - break; - break; - - case Rwalk: - p = gqid(p, ep, &f->wqid); - if(p == nil) - break; - break; - - case Ropen: - case Rcreate: - p = gqid(p, ep, &f->qid); - if(p == nil) - break; - if(p+BIT32SZ > ep) - return 0; - f->iounit = GBIT32(p); - p += BIT32SZ; - break; - - case Rread: - if(p+BIT32SZ > ep) - return 0; - f->count = GBIT32(p); - p += BIT32SZ; - if(p+f->count > ep) - return 0; - f->data = (char*)p; - p += f->count; - break; - - case Rwrite: + case IXRcopy: if(p+BIT32SZ > ep) return 0; f->count = GBIT32(p); p += BIT32SZ; break; - case Rclunk: - case Rremove: + case IXTflush: + case IXRflush: break; - case Rstat: - if(p+BIT16SZ > ep) - return 0; - f->nstat = GBIT16(p); - p += BIT16SZ; - if(p+f->nstat > ep) - return 0; - f->stat = p; - p += f->nstat; - break; - - case Rwstat: - break; + default: + werrstr("unpack: unknown type %d", f->type); + return 0; } if(p==nil || p>ep || p == ap){ diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/tses.c --- a/sys/src/cmd/ix/tses.c Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/tses.c Thu Dec 01 11:19:13 2011 +0100 @@ -1,5 +1,5 @@ /* - * Tcp-like transports, wrapped in a Ses structure + * Tcp-like transports, wrapped in a Con structure * to send and receive messages. * * Termination: @@ -19,7 +19,6 @@ */ #include #include -#include #include #include "conf.h" @@ -29,7 +28,7 @@ #include "dbg.h" static void -abortconn(Ses *s) +abortconn(Con *s) { if(s->cfd < 0) return; @@ -41,7 +40,7 @@ } static void -freeses(Ses *s) +freeses(Con *s) { dsprint("free session %p\n", s); free(s->addr); @@ -59,14 +58,14 @@ } static void -putses(Ses *s) +putses(Con *s) { if(decref(s) == 0) freeses(s); } static void -syserr(Ses *s) +syserr(Con *s) { /* * BUG: could leak if concurrent errors. @@ -78,7 +77,7 @@ static void rproc(void *a) { - Ses *s; + Con *s; Msg *m, *sm; long nr; @@ -125,7 +124,7 @@ static void wproc(void *a) { - Ses *s; + Con *s; Msg *m; s = a; @@ -156,7 +155,7 @@ } void -startses(Ses *s, Mpool *mp, Mpool *smp) +startses(Con *s, Mpool *mp, Mpool *smp) { s->pool = mp; s->spool = smp; @@ -175,7 +174,7 @@ enum{New, End}; Ssrv *ss; - Ses *sl, **nl, *s; + Con *sl, **nl, *s; Alt alts[] = { [New] {nil, &s, CHANRCV}, [End] {nil, &s, CHANRCV}, @@ -219,15 +218,15 @@ listenproc(void *a) { Ssrv *ss; - Ses *s; + Con *s; char ldir[40]; ss = a; threadsetname("listenproc %p", a); dpprint("listenproc[%p]: started\n", a); for(;;){ - s = emalloc(sizeof *s); - s->addr = estrdup(ss->addr); /* not needed in srv */ + s = mallocz(sizeof *s, 1); + s->addr = strdup(ss->addr); /* not needed in srv */ s->cfd = s->dfd = -1; s->ref = 1; s->cfd = listen(ss->adir, ldir); @@ -259,28 +258,28 @@ { Ssrv *ss; - ss = emalloc(sizeof *ss); + ss = mallocz(sizeof *ss, 1); dprint("announce %s\n", addr); ss->afd = announce(addr, ss->adir); if(ss->afd < 0){ free(ss); return nil; } - ss->addr = estrdup(addr); - ss->listenc = echancreate(sizeof(Ses*), 0); - ss->newc = echancreate(sizeof(Ses*), 0); - ss->endc = echancreate(sizeof(Ses*), 0); + ss->addr = strdup(addr); + ss->listenc = echancreate(sizeof(Con*), 0); + ss->newc = echancreate(sizeof(Con*), 0); + ss->endc = echancreate(sizeof(Con*), 0); proccreate(listenproc, ss, Stack); threadcreate(ssrvproc, ss, Stack); return ss; } -Ses* +Con* dialsrv(char *addr) { - Ses *s; + Con *s; - s = emalloc(sizeof *s); + s = mallocz(sizeof *s, 1); dprint("dial %s\n", addr); s->dfd = dial(addr, nil, nil, &s->cfd); if(s->dfd < 0){ @@ -288,13 +287,13 @@ return nil; } s->ref = 1; - s->addr = estrdup(addr); + s->addr = strdup(addr); dsprint("session[%p]: new %s\n", s, s->addr); return s; } int -closeses(Ses *s) +closeses(Con *s) { Msg *m; char *e; diff -r 006370f4d855 -r f23a243e5c73 sys/src/cmd/ix/tses.h --- a/sys/src/cmd/ix/tses.h Fri Dec 02 09:39:29 2011 +0000 +++ b/sys/src/cmd/ix/tses.h Thu Dec 01 11:19:13 2011 +0100 @@ -1,7 +1,7 @@ -typedef struct Ses Ses; +typedef struct Con Con; typedef struct Ssrv Ssrv; -struct Ses +struct Con { Channel*rc; /* read channel (of Msg*) */ Channel*wc; /* write channel (of Msg*) */ @@ -13,28 +13,28 @@ Mpool*spool; /* small message pool */ char* err; Ref; /* used by reader, writer, client */ - Ses *next; /* in list of sessions */ + Con *next; /* in list of sessions */ char* addr; /* debug */ - int cfd; /* control fd */ - int dfd; /* data fd */ + int cfd; /* control fd */ + int dfd; /* data fd */ int rtid; /* reader thread id */ }; struct Ssrv { - Channel*newc; /* of Ses* */ + Channel*newc; /* of Con* */ /* implementation*/ char* addr; char adir[40]; int afd; int lfd; - Channel*endc; /* of Ses* */ + Channel*endc; /* of Con* */ Channel*listenc; /* of ses* */ }; /* |c/f2p tses.c */ -extern int closeses(Ses *s); -extern Ses* dialsrv(char *addr); +extern int closeses(Con *s); +extern Con* dialsrv(char *addr); extern Ssrv* newsrv(char *addr); -extern void startses(Ses *s, Mpool *p, Mpool *sp); +extern void startses(Con *s, Mpool *p, Mpool *sp);