1 #include "all.h" 2 3 static char *tnames[] = { 4 [Tversion] "version", 5 [Tauth] "auth", 6 [Tattach] "attach", 7 [Tflush] "flush", 8 [Twalk] "walk", 9 [Topen] "open", 10 [Tcreate] "create", 11 [Tread] "read", 12 [Twrite] "write", 13 [Tclunk] "clunk", 14 [Tremove] "remove", 15 [Tstat] "stat", 16 [Twstat] "wstat", 17 }; 18 19 int messagesize = IOHDRSZ+Maxfdata; 20 21 int 22 xmesg(Session *s, int t) 23 { 24 int n; 25 26 if(chatty){ 27 if(0 <= t && t < nelem(tnames) && tnames[t]) 28 chat("T%s...", tnames[t]); 29 else 30 chat("T%d...", t); 31 } 32 s->f.type = t; 33 s->f.tag = ++s->tag; 34 if(p9debug) 35 fprint(2, "xmseg\tsend %F\n", &s->f); 36 n = convS2M(&s->f, s->data, messagesize); 37 if(niwrite(s->fd, s->data, n) != n){ 38 clog("xmesg write error on %d: %r\n", s->fd); 39 return -1; 40 } 41 again: 42 n = read9pmsg(s->fd, s->data, messagesize); 43 if(n < 0){ 44 clog("xmesg read error: %r\n"); 45 return -1; 46 } 47 if(convM2S(s->data, n, &s->f) <= 0){ 48 clog("xmesg bad convM2S %d %.2x %.2x %.2x %.2x\n", 49 n, ((uchar*)s->data)[0], ((uchar*)s->data)[1], 50 ((uchar*)s->data)[2], ((uchar*)s->data)[3]); 51 return -1; 52 } 53 if(p9debug) 54 fprint(2, "\trecv %F\n", &s->f); 55 if(s->f.tag != s->tag){ 56 clog("xmesg tag %d for %d\n", s->f.tag, s->tag); 57 goto again; 58 } 59 if(s->f.type == Rerror){ 60 if(t == Tclunk) 61 clog("xmesg clunk: %s", s->f.ename); 62 chat("xmesg %d error %s...", t, s->f.ename); 63 return -1; 64 } 65 if(s->f.type != t+1){ 66 clog("xmesg type mismatch: %d, expected %d\n", s->f.type, t+1); 67 return -1; 68 } 69 return 0; 70 } 71 72 int 73 clunkfid(Session *s, Fid *f) 74 { 75 putfid(s, f); 76 if(s == 0 || f == 0) 77 return 0; 78 s->f.fid = f - s->fids; 79 return xmesg(s, Tclunk); 80 } 81 82 #define UNLINK(p) ((p)->prev->next = (p)->next, (p)->next->prev = (p)->prev) 83 84 #define LINK(h, p) ((p)->next = (h)->next, (p)->prev = (h), \ 85 (h)->next->prev = (p), (h)->next = (p)) 86 87 #define TOFRONT(h, p) ((h)->next != (p) ? (UNLINK(p), LINK(h,p)) : 0) 88 89 Fid * 90 newfid(Session *s) 91 { 92 Fid *f, *fN; 93 94 chat("newfid.."); 95 if(s->list.prev == 0){ 96 chat("init.."); 97 s->list.prev = &s->list; 98 s->list.next = &s->list; 99 s->free = s->fids; 100 if(0 && chatty) 101 fN = &s->fids[25]; 102 else 103 fN = &s->fids[nelem(s->fids)]; 104 for(f=s->fids; f<fN; f++){ 105 f->owner = 0; 106 f->prev = 0; 107 f->next = f+1; 108 } 109 (f-1)->next = 0; 110 } 111 if(s->free){ 112 f = s->free; 113 s->free = f->next; 114 LINK(&s->list, f); 115 }else{ 116 for(f=s->list.prev; f!=&s->list; f=f->prev) 117 if(f->owner) 118 break; 119 if(f == &s->list){ 120 clog("fid leak"); 121 return 0; 122 } 123 setfid(s, f); 124 if(xmesg(s, Tclunk) < 0){ 125 clog("clunk failed, no fids?"); 126 /*return 0;*/ 127 } 128 *(f->owner) = 0; 129 f->owner = 0; 130 } 131 chat("%ld...", f - s->fids); 132 f->tstale = nfstime + staletime; 133 return f; 134 } 135 136 void 137 setfid(Session *s, Fid *f) 138 { 139 /* 140 * TOFRONT(&s->list, f); 141 */ 142 if(s->list.next != f){ 143 UNLINK(f); 144 LINK(&s->list, f); 145 } 146 147 f->tstale = nfstime + staletime; 148 s->f.fid = f - s->fids; 149 } 150 151 void 152 putfid(Session *s, Fid *f) 153 { 154 chat("putfid %ld...", f-s->fids); 155 if(s == 0 || f == 0){ 156 clog("putfid(0x%p, 0x%p) %s", s, f, (s ? s->service : "?")); 157 return; 158 } 159 UNLINK(f); 160 if(f->owner) 161 *(f->owner) = 0; 162 f->owner = 0; 163 f->prev = 0; 164 f->next = s->free; 165 s->free = f; 166 } 167 168 void 169 fidtimer(Session *s, long now) 170 { 171 Fid *f, *t; 172 int n; 173 174 f = s->list.next; 175 n = 0; 176 while(f != &s->list){ 177 t = f; 178 f = f->next; 179 if(t->owner && now >= t->tstale) 180 ++n, clunkfid(s, t); 181 } 182 if(n > 0) 183 chat("fidtimer %s\n", s->service); 184 } 185