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
xmesg(Session * s,int t)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
clunkfid(Session * s,Fid * f)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 *
newfid(Session * s)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
setfid(Session * s,Fid * f)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
putfid(Session * s,Fid * f)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
fidtimer(Session * s,long now)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