#include "all.h" static char *tnames[] = { [Tversion] "version", [Tauth] "auth", [Tattach] "attach", [Tflush] "flush", [Twalk] "walk", [Topen] "open", [Tcreate] "create", [Tread] "read", [Twrite] "write", [Tclunk] "clunk", [Tremove] "remove", [Tstat] "stat", [Twstat] "wstat", }; int messagesize = IOHDRSZ+Maxfdata; int xmesg(Session *s, int t) { int n; if(chatty){ if(0 <= t && t < nelem(tnames) && tnames[t]) chat("T%s...", tnames[t]); else chat("T%d...", t); } s->f.type = t; s->f.tag = ++s->tag; if(p9debug) fprint(2, "xmseg\tsend %F\n", &s->f); n = convS2M(&s->f, s->data, messagesize); if(niwrite(s->fd, s->data, n) != n){ clog("xmesg write error on %d: %r\n", s->fd); return -1; } again: n = read9pmsg(s->fd, s->data, messagesize); if(n < 0){ clog("xmesg read error: %r\n"); return -1; } if(convM2S(s->data, n, &s->f) <= 0){ clog("xmesg bad convM2S %d %.2x %.2x %.2x %.2x\n", n, ((uchar*)s->data)[0], ((uchar*)s->data)[1], ((uchar*)s->data)[2], ((uchar*)s->data)[3]); return -1; } if(p9debug) fprint(2, "\trecv %F\n", &s->f); if(s->f.tag != s->tag){ clog("xmesg tag %d for %d\n", s->f.tag, s->tag); goto again; } if(s->f.type == Rerror){ if(t == Tclunk) clog("xmesg clunk: %s", s->f.ename); chat("xmesg %d error %s...", t, s->f.ename); return -1; } if(s->f.type != t+1){ clog("xmesg type mismatch: %d, expected %d\n", s->f.type, t+1); return -1; } return 0; } int clunkfid(Session *s, Fid *f) { putfid(s, f); if(s == 0 || f == 0) return 0; s->f.fid = f - s->fids; return xmesg(s, Tclunk); } #define UNLINK(p) ((p)->prev->next = (p)->next, (p)->next->prev = (p)->prev) #define LINK(h, p) ((p)->next = (h)->next, (p)->prev = (h), \ (h)->next->prev = (p), (h)->next = (p)) #define TOFRONT(h, p) ((h)->next != (p) ? (UNLINK(p), LINK(h,p)) : 0) Fid * newfid(Session *s) { Fid *f, *fN; chat("newfid.."); if(s->list.prev == 0){ chat("init.."); s->list.prev = &s->list; s->list.next = &s->list; s->free = s->fids; if(0 && chatty) fN = &s->fids[25]; else fN = &s->fids[nelem(s->fids)]; for(f=s->fids; fowner = 0; f->prev = 0; f->next = f+1; } (f-1)->next = 0; } if(s->free){ f = s->free; s->free = f->next; LINK(&s->list, f); }else{ for(f=s->list.prev; f!=&s->list; f=f->prev) if(f->owner) break; if(f == &s->list){ clog("fid leak"); return 0; } setfid(s, f); if(xmesg(s, Tclunk) < 0){ clog("clunk failed, no fids?"); /*return 0;*/ } *(f->owner) = 0; f->owner = 0; } chat("%ld...", f - s->fids); f->tstale = nfstime + staletime; return f; } void setfid(Session *s, Fid *f) { /* * TOFRONT(&s->list, f); */ if(s->list.next != f){ UNLINK(f); LINK(&s->list, f); } f->tstale = nfstime + staletime; s->f.fid = f - s->fids; } void putfid(Session *s, Fid *f) { chat("putfid %ld...", f-s->fids); if(s == 0 || f == 0){ clog("putfid(0x%p, 0x%p) %s", s, f, (s ? s->service : "?")); return; } UNLINK(f); if(f->owner) *(f->owner) = 0; f->owner = 0; f->prev = 0; f->next = s->free; s->free = f; } void fidtimer(Session *s, long now) { Fid *f, *t; int n; f = s->list.next; n = 0; while(f != &s->list){ t = f; f = f->next; if(t->owner && now >= t->tstale) ++n, clunkfid(s, t); } if(n > 0) chat("fidtimer %s\n", s->service); }