1*206fef1cSDavid du Colombier #include <u.h>
2*206fef1cSDavid du Colombier #include <libc.h>
3*206fef1cSDavid du Colombier #include <auth.h>
4*206fef1cSDavid du Colombier #include <fcall.h>
5*206fef1cSDavid du Colombier
6*206fef1cSDavid du Colombier #include "cformat.h"
7*206fef1cSDavid du Colombier #include "lru.h"
8*206fef1cSDavid du Colombier #include "bcache.h"
9*206fef1cSDavid du Colombier #include "disk.h"
10*206fef1cSDavid du Colombier #include "inode.h"
11*206fef1cSDavid du Colombier #include "file.h"
12*206fef1cSDavid du Colombier #include "stats.h"
13*206fef1cSDavid du Colombier
14*206fef1cSDavid du Colombier enum
15*206fef1cSDavid du Colombier {
16*206fef1cSDavid du Colombier Nfid= 10240,
17*206fef1cSDavid du Colombier };
18*206fef1cSDavid du Colombier
19*206fef1cSDavid du Colombier /* maximum length of a file */
20*206fef1cSDavid du Colombier enum { MAXLEN = ~0ULL >> 1 };
21*206fef1cSDavid du Colombier
22*206fef1cSDavid du Colombier typedef struct Mfile Mfile;
23*206fef1cSDavid du Colombier typedef struct Ram Ram;
24*206fef1cSDavid du Colombier typedef struct P9fs P9fs;
25*206fef1cSDavid du Colombier
26*206fef1cSDavid du Colombier struct Mfile
27*206fef1cSDavid du Colombier {
28*206fef1cSDavid du Colombier Qid qid;
29*206fef1cSDavid du Colombier char busy;
30*206fef1cSDavid du Colombier };
31*206fef1cSDavid du Colombier
32*206fef1cSDavid du Colombier Mfile mfile[Nfid];
33*206fef1cSDavid du Colombier Icache ic;
34*206fef1cSDavid du Colombier int debug, statson, noauth, openserver;
35*206fef1cSDavid du Colombier int readonly; /* flag: tree being cached is expected to not change */
36*206fef1cSDavid du Colombier
37*206fef1cSDavid du Colombier struct P9fs
38*206fef1cSDavid du Colombier {
39*206fef1cSDavid du Colombier int fd[2];
40*206fef1cSDavid du Colombier Fcall rhdr;
41*206fef1cSDavid du Colombier Fcall thdr;
42*206fef1cSDavid du Colombier long len;
43*206fef1cSDavid du Colombier char *name;
44*206fef1cSDavid du Colombier };
45*206fef1cSDavid du Colombier
46*206fef1cSDavid du Colombier P9fs c; /* client conversation */
47*206fef1cSDavid du Colombier P9fs s; /* server conversation */
48*206fef1cSDavid du Colombier
49*206fef1cSDavid du Colombier struct Cfsstat cfsstat, cfsprev;
50*206fef1cSDavid du Colombier char statbuf[2048];
51*206fef1cSDavid du Colombier int statlen;
52*206fef1cSDavid du Colombier
53*206fef1cSDavid du Colombier #define MAXFDATA 8192 /* i/o size for read/write */
54*206fef1cSDavid du Colombier
55*206fef1cSDavid du Colombier int messagesize = MAXFDATA+IOHDRSZ;
56*206fef1cSDavid du Colombier
57*206fef1cSDavid du Colombier uchar datasnd[MAXFDATA + IOHDRSZ];
58*206fef1cSDavid du Colombier uchar datarcv[MAXFDATA + IOHDRSZ];
59*206fef1cSDavid du Colombier
60*206fef1cSDavid du Colombier Qid rootqid;
61*206fef1cSDavid du Colombier Qid ctlqid = {0x5555555555555555LL, 0, 0};
62*206fef1cSDavid du Colombier
63*206fef1cSDavid du Colombier ulong cachesize = 512 * 1024 * 1024;
64*206fef1cSDavid du Colombier
65*206fef1cSDavid du Colombier void rversion(void);
66*206fef1cSDavid du Colombier void rauth(Mfile*);
67*206fef1cSDavid du Colombier void rflush(void);
68*206fef1cSDavid du Colombier void rattach(Mfile*);
69*206fef1cSDavid du Colombier void rwalk(Mfile*);
70*206fef1cSDavid du Colombier void ropen(Mfile*);
71*206fef1cSDavid du Colombier void rcreate(Mfile*);
72*206fef1cSDavid du Colombier void rread(Mfile*);
73*206fef1cSDavid du Colombier void rwrite(Mfile*);
74*206fef1cSDavid du Colombier void rclunk(Mfile*);
75*206fef1cSDavid du Colombier void rremove(Mfile*);
76*206fef1cSDavid du Colombier void rstat(Mfile*);
77*206fef1cSDavid du Colombier void rwstat(Mfile*);
78*206fef1cSDavid du Colombier void error(char*, ...);
79*206fef1cSDavid du Colombier void warning(char*);
80*206fef1cSDavid du Colombier void mountinit(char*, char*);
81*206fef1cSDavid du Colombier void io(void);
82*206fef1cSDavid du Colombier void sendreply(char*);
83*206fef1cSDavid du Colombier void sendmsg(P9fs*, Fcall*);
84*206fef1cSDavid du Colombier void rcvmsg(P9fs*, Fcall*);
85*206fef1cSDavid du Colombier int delegate(void);
86*206fef1cSDavid du Colombier int askserver(void);
87*206fef1cSDavid du Colombier void cachesetup(int, char*, char*);
88*206fef1cSDavid du Colombier int ctltest(Mfile*);
89*206fef1cSDavid du Colombier void genstats(void);
90*206fef1cSDavid du Colombier
91*206fef1cSDavid du Colombier char *mname[]={
92*206fef1cSDavid du Colombier [Tversion] "Tversion",
93*206fef1cSDavid du Colombier [Tauth] "Tauth",
94*206fef1cSDavid du Colombier [Tflush] "Tflush",
95*206fef1cSDavid du Colombier [Tattach] "Tattach",
96*206fef1cSDavid du Colombier [Twalk] "Twalk",
97*206fef1cSDavid du Colombier [Topen] "Topen",
98*206fef1cSDavid du Colombier [Tcreate] "Tcreate",
99*206fef1cSDavid du Colombier [Tclunk] "Tclunk",
100*206fef1cSDavid du Colombier [Tread] "Tread",
101*206fef1cSDavid du Colombier [Twrite] "Twrite",
102*206fef1cSDavid du Colombier [Tremove] "Tremove",
103*206fef1cSDavid du Colombier [Tstat] "Tstat",
104*206fef1cSDavid du Colombier [Twstat] "Twstat",
105*206fef1cSDavid du Colombier [Rversion] "Rversion",
106*206fef1cSDavid du Colombier [Rauth] "Rauth",
107*206fef1cSDavid du Colombier [Rerror] "Rerror",
108*206fef1cSDavid du Colombier [Rflush] "Rflush",
109*206fef1cSDavid du Colombier [Rattach] "Rattach",
110*206fef1cSDavid du Colombier [Rwalk] "Rwalk",
111*206fef1cSDavid du Colombier [Ropen] "Ropen",
112*206fef1cSDavid du Colombier [Rcreate] "Rcreate",
113*206fef1cSDavid du Colombier [Rclunk] "Rclunk",
114*206fef1cSDavid du Colombier [Rread] "Rread",
115*206fef1cSDavid du Colombier [Rwrite] "Rwrite",
116*206fef1cSDavid du Colombier [Rremove] "Rremove",
117*206fef1cSDavid du Colombier [Rstat] "Rstat",
118*206fef1cSDavid du Colombier [Rwstat] "Rwstat",
119*206fef1cSDavid du Colombier 0,
120*206fef1cSDavid du Colombier };
121*206fef1cSDavid du Colombier
122*206fef1cSDavid du Colombier void
usage(void)123*206fef1cSDavid du Colombier usage(void)
124*206fef1cSDavid du Colombier {
125*206fef1cSDavid du Colombier fprint(2, "usage:\t%s -s [-dnrS] [-m size]\n", argv0);
126*206fef1cSDavid du Colombier fprint(2, "\t%s [-a netaddr | -F srv] [-dnrS] [-m size] [mntpt]\n",
127*206fef1cSDavid du Colombier argv0);
128*206fef1cSDavid du Colombier exits("usage");
129*206fef1cSDavid du Colombier }
130*206fef1cSDavid du Colombier
131*206fef1cSDavid du Colombier void
main(int argc,char * argv[])132*206fef1cSDavid du Colombier main(int argc, char *argv[])
133*206fef1cSDavid du Colombier {
134*206fef1cSDavid du Colombier int std;
135*206fef1cSDavid du Colombier char *server, *mtpt;
136*206fef1cSDavid du Colombier
137*206fef1cSDavid du Colombier std = 0;
138*206fef1cSDavid du Colombier server = "tcp!pie";
139*206fef1cSDavid du Colombier mtpt = "/n/ramcfs";
140*206fef1cSDavid du Colombier
141*206fef1cSDavid du Colombier ARGBEGIN{
142*206fef1cSDavid du Colombier case 'a':
143*206fef1cSDavid du Colombier server = EARGF(usage());
144*206fef1cSDavid du Colombier break;
145*206fef1cSDavid du Colombier case 'd':
146*206fef1cSDavid du Colombier debug = 1;
147*206fef1cSDavid du Colombier break;
148*206fef1cSDavid du Colombier case 'F':
149*206fef1cSDavid du Colombier server = EARGF(usage());
150*206fef1cSDavid du Colombier openserver = 1;
151*206fef1cSDavid du Colombier break;
152*206fef1cSDavid du Colombier case 'm':
153*206fef1cSDavid du Colombier cachesize = atoi(EARGF(usage())) * 1024 * 1024;
154*206fef1cSDavid du Colombier if (cachesize < 8 * 1024 * 1024 ||
155*206fef1cSDavid du Colombier cachesize > 3750UL * 1024 * 1024)
156*206fef1cSDavid du Colombier sysfatal("implausible cache size %lud", cachesize);
157*206fef1cSDavid du Colombier break;
158*206fef1cSDavid du Colombier case 'n':
159*206fef1cSDavid du Colombier noauth = 1;
160*206fef1cSDavid du Colombier break;
161*206fef1cSDavid du Colombier case 'r':
162*206fef1cSDavid du Colombier readonly = 1;
163*206fef1cSDavid du Colombier break;
164*206fef1cSDavid du Colombier case 'S':
165*206fef1cSDavid du Colombier statson = 1;
166*206fef1cSDavid du Colombier break;
167*206fef1cSDavid du Colombier case 's':
168*206fef1cSDavid du Colombier std = 1;
169*206fef1cSDavid du Colombier break;
170*206fef1cSDavid du Colombier default:
171*206fef1cSDavid du Colombier usage();
172*206fef1cSDavid du Colombier }ARGEND
173*206fef1cSDavid du Colombier if(argc && *argv)
174*206fef1cSDavid du Colombier mtpt = *argv;
175*206fef1cSDavid du Colombier
176*206fef1cSDavid du Colombier if(debug)
177*206fef1cSDavid du Colombier fmtinstall('F', fcallfmt);
178*206fef1cSDavid du Colombier
179*206fef1cSDavid du Colombier c.name = "client";
180*206fef1cSDavid du Colombier s.name = "server";
181*206fef1cSDavid du Colombier if(std){
182*206fef1cSDavid du Colombier c.fd[0] = c.fd[1] = 1;
183*206fef1cSDavid du Colombier s.fd[0] = s.fd[1] = 0;
184*206fef1cSDavid du Colombier }else
185*206fef1cSDavid du Colombier mountinit(server, mtpt);
186*206fef1cSDavid du Colombier
187*206fef1cSDavid du Colombier cachesetup(1, nil, nil);
188*206fef1cSDavid du Colombier
189*206fef1cSDavid du Colombier switch(fork()){
190*206fef1cSDavid du Colombier case 0:
191*206fef1cSDavid du Colombier io();
192*206fef1cSDavid du Colombier exits("");
193*206fef1cSDavid du Colombier case -1:
194*206fef1cSDavid du Colombier error("fork");
195*206fef1cSDavid du Colombier default:
196*206fef1cSDavid du Colombier exits("");
197*206fef1cSDavid du Colombier }
198*206fef1cSDavid du Colombier }
199*206fef1cSDavid du Colombier
200*206fef1cSDavid du Colombier void
cachesetup(int format,char * name,char *)201*206fef1cSDavid du Colombier cachesetup(int format, char *name, char *)
202*206fef1cSDavid du Colombier {
203*206fef1cSDavid du Colombier int secsize;
204*206fef1cSDavid du Colombier int inodes;
205*206fef1cSDavid du Colombier int blocksize;
206*206fef1cSDavid du Colombier char *memcache;
207*206fef1cSDavid du Colombier
208*206fef1cSDavid du Colombier secsize = 512; /* only really matters for disks */
209*206fef1cSDavid du Colombier blocksize = 4*1024;
210*206fef1cSDavid du Colombier inodes = 2*1024;
211*206fef1cSDavid du Colombier
212*206fef1cSDavid du Colombier memcache = malloc(cachesize);
213*206fef1cSDavid du Colombier if(memcache == nil)
214*206fef1cSDavid du Colombier error("can't allocate memory for cache: %r");
215*206fef1cSDavid du Colombier
216*206fef1cSDavid du Colombier /*
217*206fef1cSDavid du Colombier * Always format. If we don't have a name, fall
218*206fef1cSDavid du Colombier * back to our old behavior of using "bootes"
219*206fef1cSDavid du Colombier */
220*206fef1cSDavid du Colombier USED(format);
221*206fef1cSDavid du Colombier name = (name == nil? "bootes": name);
222*206fef1cSDavid du Colombier if(iformat(&ic, memcache, inodes, name, blocksize, secsize) < 0)
223*206fef1cSDavid du Colombier error("formatting failed");
224*206fef1cSDavid du Colombier }
225*206fef1cSDavid du Colombier
226*206fef1cSDavid du Colombier void
mountinit(char * server,char * mountpoint)227*206fef1cSDavid du Colombier mountinit(char *server, char *mountpoint)
228*206fef1cSDavid du Colombier {
229*206fef1cSDavid du Colombier int err;
230*206fef1cSDavid du Colombier int p[2];
231*206fef1cSDavid du Colombier
232*206fef1cSDavid du Colombier /*
233*206fef1cSDavid du Colombier * grab a channel and call up the file server
234*206fef1cSDavid du Colombier */
235*206fef1cSDavid du Colombier if (openserver) {
236*206fef1cSDavid du Colombier s.fd[0] = open(server, ORDWR);
237*206fef1cSDavid du Colombier if(s.fd[0] < 0)
238*206fef1cSDavid du Colombier error("opening srv file %s: %r", server);
239*206fef1cSDavid du Colombier } else {
240*206fef1cSDavid du Colombier s.fd[0] = dial(netmkaddr(server, 0, "9fs"), 0, 0, 0);
241*206fef1cSDavid du Colombier if(s.fd[0] < 0)
242*206fef1cSDavid du Colombier error("dialing %s: %r", server);
243*206fef1cSDavid du Colombier }
244*206fef1cSDavid du Colombier s.fd[1] = s.fd[0];
245*206fef1cSDavid du Colombier
246*206fef1cSDavid du Colombier /*
247*206fef1cSDavid du Colombier * mount onto name space
248*206fef1cSDavid du Colombier */
249*206fef1cSDavid du Colombier if(pipe(p) < 0)
250*206fef1cSDavid du Colombier error("pipe failed");
251*206fef1cSDavid du Colombier switch(fork()){
252*206fef1cSDavid du Colombier case 0:
253*206fef1cSDavid du Colombier break;
254*206fef1cSDavid du Colombier default:
255*206fef1cSDavid du Colombier if (noauth)
256*206fef1cSDavid du Colombier err = mount(p[1], -1, mountpoint, MREPL|MCREATE|MCACHE, "");
257*206fef1cSDavid du Colombier else
258*206fef1cSDavid du Colombier err = amount(p[1], mountpoint, MREPL|MCREATE|MCACHE, "");
259*206fef1cSDavid du Colombier if (err < 0)
260*206fef1cSDavid du Colombier error("mount failed: %r");
261*206fef1cSDavid du Colombier exits(0);
262*206fef1cSDavid du Colombier case -1:
263*206fef1cSDavid du Colombier error("fork failed\n");
264*206fef1cSDavid du Colombier /*BUG: no wait!*/
265*206fef1cSDavid du Colombier }
266*206fef1cSDavid du Colombier c.fd[0] = c.fd[1] = p[0];
267*206fef1cSDavid du Colombier }
268*206fef1cSDavid du Colombier
269*206fef1cSDavid du Colombier void
io(void)270*206fef1cSDavid du Colombier io(void)
271*206fef1cSDavid du Colombier {
272*206fef1cSDavid du Colombier int type;
273*206fef1cSDavid du Colombier Mfile *mf;
274*206fef1cSDavid du Colombier loop:
275*206fef1cSDavid du Colombier rcvmsg(&c, &c.thdr);
276*206fef1cSDavid du Colombier
277*206fef1cSDavid du Colombier type = c.thdr.type;
278*206fef1cSDavid du Colombier
279*206fef1cSDavid du Colombier if(statson){
280*206fef1cSDavid du Colombier cfsstat.cm[type].n++;
281*206fef1cSDavid du Colombier cfsstat.cm[type].s = nsec();
282*206fef1cSDavid du Colombier }
283*206fef1cSDavid du Colombier mf = &mfile[c.thdr.fid];
284*206fef1cSDavid du Colombier switch(type){
285*206fef1cSDavid du Colombier default:
286*206fef1cSDavid du Colombier error("type");
287*206fef1cSDavid du Colombier break;
288*206fef1cSDavid du Colombier case Tversion:
289*206fef1cSDavid du Colombier rversion();
290*206fef1cSDavid du Colombier break;
291*206fef1cSDavid du Colombier case Tauth:
292*206fef1cSDavid du Colombier mf = &mfile[c.thdr.afid];
293*206fef1cSDavid du Colombier rauth(mf);
294*206fef1cSDavid du Colombier break;
295*206fef1cSDavid du Colombier case Tflush:
296*206fef1cSDavid du Colombier rflush();
297*206fef1cSDavid du Colombier break;
298*206fef1cSDavid du Colombier case Tattach:
299*206fef1cSDavid du Colombier rattach(mf);
300*206fef1cSDavid du Colombier break;
301*206fef1cSDavid du Colombier case Twalk:
302*206fef1cSDavid du Colombier rwalk(mf);
303*206fef1cSDavid du Colombier break;
304*206fef1cSDavid du Colombier case Topen:
305*206fef1cSDavid du Colombier ropen(mf);
306*206fef1cSDavid du Colombier break;
307*206fef1cSDavid du Colombier case Tcreate:
308*206fef1cSDavid du Colombier rcreate(mf);
309*206fef1cSDavid du Colombier break;
310*206fef1cSDavid du Colombier case Tread:
311*206fef1cSDavid du Colombier rread(mf);
312*206fef1cSDavid du Colombier break;
313*206fef1cSDavid du Colombier case Twrite:
314*206fef1cSDavid du Colombier rwrite(mf);
315*206fef1cSDavid du Colombier break;
316*206fef1cSDavid du Colombier case Tclunk:
317*206fef1cSDavid du Colombier rclunk(mf);
318*206fef1cSDavid du Colombier break;
319*206fef1cSDavid du Colombier case Tremove:
320*206fef1cSDavid du Colombier rremove(mf);
321*206fef1cSDavid du Colombier break;
322*206fef1cSDavid du Colombier case Tstat:
323*206fef1cSDavid du Colombier rstat(mf);
324*206fef1cSDavid du Colombier break;
325*206fef1cSDavid du Colombier case Twstat:
326*206fef1cSDavid du Colombier rwstat(mf);
327*206fef1cSDavid du Colombier break;
328*206fef1cSDavid du Colombier }
329*206fef1cSDavid du Colombier if(statson){
330*206fef1cSDavid du Colombier cfsstat.cm[type].t += nsec() -cfsstat.cm[type].s;
331*206fef1cSDavid du Colombier }
332*206fef1cSDavid du Colombier goto loop;
333*206fef1cSDavid du Colombier }
334*206fef1cSDavid du Colombier
335*206fef1cSDavid du Colombier void
rversion(void)336*206fef1cSDavid du Colombier rversion(void)
337*206fef1cSDavid du Colombier {
338*206fef1cSDavid du Colombier if(messagesize > c.thdr.msize)
339*206fef1cSDavid du Colombier messagesize = c.thdr.msize;
340*206fef1cSDavid du Colombier c.thdr.msize = messagesize; /* set downstream size */
341*206fef1cSDavid du Colombier delegate();
342*206fef1cSDavid du Colombier }
343*206fef1cSDavid du Colombier
344*206fef1cSDavid du Colombier void
rauth(Mfile * mf)345*206fef1cSDavid du Colombier rauth(Mfile *mf)
346*206fef1cSDavid du Colombier {
347*206fef1cSDavid du Colombier if(mf->busy)
348*206fef1cSDavid du Colombier error("auth to used channel");
349*206fef1cSDavid du Colombier
350*206fef1cSDavid du Colombier if(delegate() == 0){
351*206fef1cSDavid du Colombier mf->qid = s.rhdr.aqid;
352*206fef1cSDavid du Colombier mf->busy = 1;
353*206fef1cSDavid du Colombier }
354*206fef1cSDavid du Colombier }
355*206fef1cSDavid du Colombier
356*206fef1cSDavid du Colombier void
rflush(void)357*206fef1cSDavid du Colombier rflush(void) /* synchronous so easy */
358*206fef1cSDavid du Colombier {
359*206fef1cSDavid du Colombier sendreply(0);
360*206fef1cSDavid du Colombier }
361*206fef1cSDavid du Colombier
362*206fef1cSDavid du Colombier void
rattach(Mfile * mf)363*206fef1cSDavid du Colombier rattach(Mfile *mf)
364*206fef1cSDavid du Colombier {
365*206fef1cSDavid du Colombier if(delegate() == 0){
366*206fef1cSDavid du Colombier mf->qid = s.rhdr.qid;
367*206fef1cSDavid du Colombier mf->busy = 1;
368*206fef1cSDavid du Colombier if (statson == 1){
369*206fef1cSDavid du Colombier statson++;
370*206fef1cSDavid du Colombier rootqid = mf->qid;
371*206fef1cSDavid du Colombier }
372*206fef1cSDavid du Colombier }
373*206fef1cSDavid du Colombier }
374*206fef1cSDavid du Colombier
375*206fef1cSDavid du Colombier void
rwalk(Mfile * mf)376*206fef1cSDavid du Colombier rwalk(Mfile *mf)
377*206fef1cSDavid du Colombier {
378*206fef1cSDavid du Colombier Mfile *nmf;
379*206fef1cSDavid du Colombier
380*206fef1cSDavid du Colombier nmf = nil;
381*206fef1cSDavid du Colombier if(statson
382*206fef1cSDavid du Colombier && mf->qid.type == rootqid.type && mf->qid.path == rootqid.path
383*206fef1cSDavid du Colombier && c.thdr.nwname == 1 && strcmp(c.thdr.wname[0], "cfsctl") == 0){
384*206fef1cSDavid du Colombier /* This is the ctl file */
385*206fef1cSDavid du Colombier nmf = &mfile[c.thdr.newfid];
386*206fef1cSDavid du Colombier if(c.thdr.newfid != c.thdr.fid && nmf->busy)
387*206fef1cSDavid du Colombier error("clone to used channel");
388*206fef1cSDavid du Colombier nmf = &mfile[c.thdr.newfid];
389*206fef1cSDavid du Colombier nmf->qid = ctlqid;
390*206fef1cSDavid du Colombier nmf->busy = 1;
391*206fef1cSDavid du Colombier c.rhdr.nwqid = 1;
392*206fef1cSDavid du Colombier c.rhdr.wqid[0] = ctlqid;
393*206fef1cSDavid du Colombier sendreply(0);
394*206fef1cSDavid du Colombier return;
395*206fef1cSDavid du Colombier }
396*206fef1cSDavid du Colombier if(c.thdr.newfid != c.thdr.fid){
397*206fef1cSDavid du Colombier if(c.thdr.newfid >= Nfid)
398*206fef1cSDavid du Colombier error("clone nfid out of range");
399*206fef1cSDavid du Colombier nmf = &mfile[c.thdr.newfid];
400*206fef1cSDavid du Colombier if(nmf->busy)
401*206fef1cSDavid du Colombier error("clone to used channel");
402*206fef1cSDavid du Colombier nmf = &mfile[c.thdr.newfid];
403*206fef1cSDavid du Colombier nmf->qid = mf->qid;
404*206fef1cSDavid du Colombier nmf->busy = 1;
405*206fef1cSDavid du Colombier mf = nmf; /* Walk mf */
406*206fef1cSDavid du Colombier }
407*206fef1cSDavid du Colombier
408*206fef1cSDavid du Colombier if(delegate() < 0){ /* complete failure */
409*206fef1cSDavid du Colombier if(nmf)
410*206fef1cSDavid du Colombier nmf->busy = 0;
411*206fef1cSDavid du Colombier return;
412*206fef1cSDavid du Colombier }
413*206fef1cSDavid du Colombier
414*206fef1cSDavid du Colombier if(s.rhdr.nwqid == c.thdr.nwname){ /* complete success */
415*206fef1cSDavid du Colombier if(s.rhdr.nwqid > 0)
416*206fef1cSDavid du Colombier mf->qid = s.rhdr.wqid[s.rhdr.nwqid-1];
417*206fef1cSDavid du Colombier return;
418*206fef1cSDavid du Colombier }
419*206fef1cSDavid du Colombier
420*206fef1cSDavid du Colombier /* partial success; release fid */
421*206fef1cSDavid du Colombier if(nmf)
422*206fef1cSDavid du Colombier nmf->busy = 0;
423*206fef1cSDavid du Colombier }
424*206fef1cSDavid du Colombier
425*206fef1cSDavid du Colombier void
ropen(Mfile * mf)426*206fef1cSDavid du Colombier ropen(Mfile *mf)
427*206fef1cSDavid du Colombier {
428*206fef1cSDavid du Colombier if(statson && ctltest(mf)){
429*206fef1cSDavid du Colombier /* Opening ctl file */
430*206fef1cSDavid du Colombier if(c.thdr.mode != OREAD){
431*206fef1cSDavid du Colombier sendreply("does not exist");
432*206fef1cSDavid du Colombier return;
433*206fef1cSDavid du Colombier }
434*206fef1cSDavid du Colombier c.rhdr.qid = ctlqid;
435*206fef1cSDavid du Colombier c.rhdr.iounit = 0;
436*206fef1cSDavid du Colombier sendreply(0);
437*206fef1cSDavid du Colombier genstats();
438*206fef1cSDavid du Colombier return;
439*206fef1cSDavid du Colombier }
440*206fef1cSDavid du Colombier if(delegate() == 0){
441*206fef1cSDavid du Colombier mf->qid = s.rhdr.qid;
442*206fef1cSDavid du Colombier if(c.thdr.mode & OTRUNC)
443*206fef1cSDavid du Colombier iget(&ic, mf->qid);
444*206fef1cSDavid du Colombier }
445*206fef1cSDavid du Colombier }
446*206fef1cSDavid du Colombier
447*206fef1cSDavid du Colombier void
rcreate(Mfile * mf)448*206fef1cSDavid du Colombier rcreate(Mfile *mf)
449*206fef1cSDavid du Colombier {
450*206fef1cSDavid du Colombier if(statson && ctltest(mf)){
451*206fef1cSDavid du Colombier sendreply("exists");
452*206fef1cSDavid du Colombier return;
453*206fef1cSDavid du Colombier }
454*206fef1cSDavid du Colombier if(delegate() == 0){
455*206fef1cSDavid du Colombier mf->qid = s.rhdr.qid;
456*206fef1cSDavid du Colombier mf->qid.vers++;
457*206fef1cSDavid du Colombier }
458*206fef1cSDavid du Colombier }
459*206fef1cSDavid du Colombier
460*206fef1cSDavid du Colombier void
rclunk(Mfile * mf)461*206fef1cSDavid du Colombier rclunk(Mfile *mf)
462*206fef1cSDavid du Colombier {
463*206fef1cSDavid du Colombier if(!mf->busy){
464*206fef1cSDavid du Colombier sendreply(0);
465*206fef1cSDavid du Colombier return;
466*206fef1cSDavid du Colombier }
467*206fef1cSDavid du Colombier mf->busy = 0;
468*206fef1cSDavid du Colombier delegate();
469*206fef1cSDavid du Colombier }
470*206fef1cSDavid du Colombier
471*206fef1cSDavid du Colombier void
rremove(Mfile * mf)472*206fef1cSDavid du Colombier rremove(Mfile *mf)
473*206fef1cSDavid du Colombier {
474*206fef1cSDavid du Colombier if(statson && ctltest(mf)){
475*206fef1cSDavid du Colombier sendreply("not removed");
476*206fef1cSDavid du Colombier return;
477*206fef1cSDavid du Colombier }
478*206fef1cSDavid du Colombier mf->busy = 0;
479*206fef1cSDavid du Colombier delegate();
480*206fef1cSDavid du Colombier }
481*206fef1cSDavid du Colombier
482*206fef1cSDavid du Colombier void
rread(Mfile * mf)483*206fef1cSDavid du Colombier rread(Mfile *mf)
484*206fef1cSDavid du Colombier {
485*206fef1cSDavid du Colombier int cnt, done;
486*206fef1cSDavid du Colombier long n;
487*206fef1cSDavid du Colombier vlong off, first;
488*206fef1cSDavid du Colombier char *cp;
489*206fef1cSDavid du Colombier char data[MAXFDATA];
490*206fef1cSDavid du Colombier Ibuf *b;
491*206fef1cSDavid du Colombier
492*206fef1cSDavid du Colombier off = c.thdr.offset;
493*206fef1cSDavid du Colombier first = off;
494*206fef1cSDavid du Colombier cnt = c.thdr.count;
495*206fef1cSDavid du Colombier
496*206fef1cSDavid du Colombier if(statson && ctltest(mf)){
497*206fef1cSDavid du Colombier if(cnt > statlen-off)
498*206fef1cSDavid du Colombier c.rhdr.count = statlen-off;
499*206fef1cSDavid du Colombier else
500*206fef1cSDavid du Colombier c.rhdr.count = cnt;
501*206fef1cSDavid du Colombier if((int)c.rhdr.count < 0){
502*206fef1cSDavid du Colombier sendreply("eof");
503*206fef1cSDavid du Colombier return;
504*206fef1cSDavid du Colombier }
505*206fef1cSDavid du Colombier c.rhdr.data = statbuf + off;
506*206fef1cSDavid du Colombier sendreply(0);
507*206fef1cSDavid du Colombier return;
508*206fef1cSDavid du Colombier }
509*206fef1cSDavid du Colombier if(mf->qid.type & (QTDIR|QTAUTH)){
510*206fef1cSDavid du Colombier delegate();
511*206fef1cSDavid du Colombier if (statson) {
512*206fef1cSDavid du Colombier cfsstat.ndirread++;
513*206fef1cSDavid du Colombier if(c.rhdr.count > 0){
514*206fef1cSDavid du Colombier cfsstat.bytesread += c.rhdr.count;
515*206fef1cSDavid du Colombier cfsstat.bytesfromdirs += c.rhdr.count;
516*206fef1cSDavid du Colombier }
517*206fef1cSDavid du Colombier }
518*206fef1cSDavid du Colombier return;
519*206fef1cSDavid du Colombier }
520*206fef1cSDavid du Colombier
521*206fef1cSDavid du Colombier b = iget(&ic, mf->qid);
522*206fef1cSDavid du Colombier if(b == 0){
523*206fef1cSDavid du Colombier DPRINT(2, "delegating read\n");
524*206fef1cSDavid du Colombier delegate();
525*206fef1cSDavid du Colombier if (statson){
526*206fef1cSDavid du Colombier cfsstat.ndelegateread++;
527*206fef1cSDavid du Colombier if(c.rhdr.count > 0){
528*206fef1cSDavid du Colombier cfsstat.bytesread += c.rhdr.count;
529*206fef1cSDavid du Colombier cfsstat.bytesfromserver += c.rhdr.count;
530*206fef1cSDavid du Colombier }
531*206fef1cSDavid du Colombier }
532*206fef1cSDavid du Colombier return;
533*206fef1cSDavid du Colombier }
534*206fef1cSDavid du Colombier
535*206fef1cSDavid du Colombier cp = data;
536*206fef1cSDavid du Colombier done = 0;
537*206fef1cSDavid du Colombier while(cnt>0 && !done){
538*206fef1cSDavid du Colombier if(off >= b->inode.length){
539*206fef1cSDavid du Colombier DPRINT(2, "offset %lld greater than length %lld\n",
540*206fef1cSDavid du Colombier off, b->inode.length);
541*206fef1cSDavid du Colombier break;
542*206fef1cSDavid du Colombier }
543*206fef1cSDavid du Colombier n = fread(&ic, b, cp, off, cnt);
544*206fef1cSDavid du Colombier if(n <= 0){
545*206fef1cSDavid du Colombier n = -n;
546*206fef1cSDavid du Colombier if(n==0 || n>cnt)
547*206fef1cSDavid du Colombier n = cnt;
548*206fef1cSDavid du Colombier DPRINT(2,
549*206fef1cSDavid du Colombier "fetch %ld bytes of data from server at offset %lld\n",
550*206fef1cSDavid du Colombier n, off);
551*206fef1cSDavid du Colombier s.thdr.type = c.thdr.type;
552*206fef1cSDavid du Colombier s.thdr.fid = c.thdr.fid;
553*206fef1cSDavid du Colombier s.thdr.tag = c.thdr.tag;
554*206fef1cSDavid du Colombier s.thdr.offset = off;
555*206fef1cSDavid du Colombier s.thdr.count = n;
556*206fef1cSDavid du Colombier if(statson)
557*206fef1cSDavid du Colombier cfsstat.ndelegateread++;
558*206fef1cSDavid du Colombier if(askserver() < 0){
559*206fef1cSDavid du Colombier sendreply(s.rhdr.ename);
560*206fef1cSDavid du Colombier return;
561*206fef1cSDavid du Colombier }
562*206fef1cSDavid du Colombier if(s.rhdr.count != n)
563*206fef1cSDavid du Colombier done = 1;
564*206fef1cSDavid du Colombier n = s.rhdr.count;
565*206fef1cSDavid du Colombier if(n == 0){
566*206fef1cSDavid du Colombier /* end of file */
567*206fef1cSDavid du Colombier if(b->inode.length > off){
568*206fef1cSDavid du Colombier DPRINT(2, "file %llud.%ld, length %lld\n",
569*206fef1cSDavid du Colombier b->inode.qid.path,
570*206fef1cSDavid du Colombier b->inode.qid.vers, off);
571*206fef1cSDavid du Colombier b->inode.length = off;
572*206fef1cSDavid du Colombier }
573*206fef1cSDavid du Colombier break;
574*206fef1cSDavid du Colombier }
575*206fef1cSDavid du Colombier memmove(cp, s.rhdr.data, n);
576*206fef1cSDavid du Colombier fwrite(&ic, b, cp, off, n);
577*206fef1cSDavid du Colombier if (statson){
578*206fef1cSDavid du Colombier cfsstat.bytestocache += n;
579*206fef1cSDavid du Colombier cfsstat.bytesfromserver += n;
580*206fef1cSDavid du Colombier }
581*206fef1cSDavid du Colombier }else{
582*206fef1cSDavid du Colombier DPRINT(2, "fetched %ld bytes from cache\n", n);
583*206fef1cSDavid du Colombier if(statson)
584*206fef1cSDavid du Colombier cfsstat.bytesfromcache += n;
585*206fef1cSDavid du Colombier }
586*206fef1cSDavid du Colombier cnt -= n;
587*206fef1cSDavid du Colombier off += n;
588*206fef1cSDavid du Colombier cp += n;
589*206fef1cSDavid du Colombier }
590*206fef1cSDavid du Colombier c.rhdr.data = data;
591*206fef1cSDavid du Colombier c.rhdr.count = off - first;
592*206fef1cSDavid du Colombier if(statson)
593*206fef1cSDavid du Colombier cfsstat.bytesread += c.rhdr.count;
594*206fef1cSDavid du Colombier sendreply(0);
595*206fef1cSDavid du Colombier }
596*206fef1cSDavid du Colombier
597*206fef1cSDavid du Colombier void
rwrite(Mfile * mf)598*206fef1cSDavid du Colombier rwrite(Mfile *mf)
599*206fef1cSDavid du Colombier {
600*206fef1cSDavid du Colombier Ibuf *b;
601*206fef1cSDavid du Colombier char buf[MAXFDATA];
602*206fef1cSDavid du Colombier
603*206fef1cSDavid du Colombier if(statson && ctltest(mf)){
604*206fef1cSDavid du Colombier sendreply("read only");
605*206fef1cSDavid du Colombier return;
606*206fef1cSDavid du Colombier }
607*206fef1cSDavid du Colombier if(mf->qid.type & (QTDIR|QTAUTH)){
608*206fef1cSDavid du Colombier delegate();
609*206fef1cSDavid du Colombier if(statson && c.rhdr.count > 0)
610*206fef1cSDavid du Colombier cfsstat.byteswritten += c.rhdr.count;
611*206fef1cSDavid du Colombier return;
612*206fef1cSDavid du Colombier }
613*206fef1cSDavid du Colombier
614*206fef1cSDavid du Colombier memmove(buf, c.thdr.data, c.thdr.count);
615*206fef1cSDavid du Colombier if(delegate() < 0)
616*206fef1cSDavid du Colombier return;
617*206fef1cSDavid du Colombier
618*206fef1cSDavid du Colombier if(s.rhdr.count > 0)
619*206fef1cSDavid du Colombier cfsstat.byteswritten += s.rhdr.count;
620*206fef1cSDavid du Colombier /* don't modify our cache for append-only data; always read from server*/
621*206fef1cSDavid du Colombier if(mf->qid.type & QTAPPEND)
622*206fef1cSDavid du Colombier return;
623*206fef1cSDavid du Colombier b = iget(&ic, mf->qid);
624*206fef1cSDavid du Colombier if(b == 0)
625*206fef1cSDavid du Colombier return;
626*206fef1cSDavid du Colombier if (b->inode.length < c.thdr.offset + s.rhdr.count)
627*206fef1cSDavid du Colombier b->inode.length = c.thdr.offset + s.rhdr.count;
628*206fef1cSDavid du Colombier mf->qid.vers++;
629*206fef1cSDavid du Colombier if (s.rhdr.count != c.thdr.count)
630*206fef1cSDavid du Colombier syslog(0, "cfslog", "rhdr.count %ud, thdr.count %ud\n",
631*206fef1cSDavid du Colombier s.rhdr.count, c.thdr.count);
632*206fef1cSDavid du Colombier if(fwrite(&ic, b, buf, c.thdr.offset, s.rhdr.count) == s.rhdr.count){
633*206fef1cSDavid du Colombier iinc(&ic, b);
634*206fef1cSDavid du Colombier if(statson)
635*206fef1cSDavid du Colombier cfsstat.bytestocache += s.rhdr.count;
636*206fef1cSDavid du Colombier }
637*206fef1cSDavid du Colombier }
638*206fef1cSDavid du Colombier
639*206fef1cSDavid du Colombier void
rstat(Mfile * mf)640*206fef1cSDavid du Colombier rstat(Mfile *mf)
641*206fef1cSDavid du Colombier {
642*206fef1cSDavid du Colombier Dir d;
643*206fef1cSDavid du Colombier
644*206fef1cSDavid du Colombier if(statson && ctltest(mf)){
645*206fef1cSDavid du Colombier genstats();
646*206fef1cSDavid du Colombier d.qid = ctlqid;
647*206fef1cSDavid du Colombier d.mode = 0444;
648*206fef1cSDavid du Colombier d.length = statlen; /* would be nice to do better */
649*206fef1cSDavid du Colombier d.name = "cfsctl";
650*206fef1cSDavid du Colombier d.uid = "none";
651*206fef1cSDavid du Colombier d.gid = "none";
652*206fef1cSDavid du Colombier d.muid = "none";
653*206fef1cSDavid du Colombier d.atime = time(nil);
654*206fef1cSDavid du Colombier d.mtime = d.atime;
655*206fef1cSDavid du Colombier c.rhdr.nstat = convD2M(&d, c.rhdr.stat,
656*206fef1cSDavid du Colombier sizeof c.rhdr - (c.rhdr.stat - (uchar*)&c.rhdr));
657*206fef1cSDavid du Colombier sendreply(0);
658*206fef1cSDavid du Colombier return;
659*206fef1cSDavid du Colombier }
660*206fef1cSDavid du Colombier if(delegate() == 0){
661*206fef1cSDavid du Colombier Ibuf *b;
662*206fef1cSDavid du Colombier
663*206fef1cSDavid du Colombier convM2D(s.rhdr.stat, s.rhdr.nstat , &d, nil);
664*206fef1cSDavid du Colombier mf->qid = d.qid;
665*206fef1cSDavid du Colombier b = iget(&ic, mf->qid);
666*206fef1cSDavid du Colombier if(b)
667*206fef1cSDavid du Colombier b->inode.length = d.length;
668*206fef1cSDavid du Colombier }
669*206fef1cSDavid du Colombier }
670*206fef1cSDavid du Colombier
671*206fef1cSDavid du Colombier void
rwstat(Mfile * mf)672*206fef1cSDavid du Colombier rwstat(Mfile *mf)
673*206fef1cSDavid du Colombier {
674*206fef1cSDavid du Colombier Ibuf *b;
675*206fef1cSDavid du Colombier
676*206fef1cSDavid du Colombier if(statson && ctltest(mf)){
677*206fef1cSDavid du Colombier sendreply("read only");
678*206fef1cSDavid du Colombier return;
679*206fef1cSDavid du Colombier }
680*206fef1cSDavid du Colombier delegate();
681*206fef1cSDavid du Colombier if(b = iget(&ic, mf->qid))
682*206fef1cSDavid du Colombier b->inode.length = MAXLEN;
683*206fef1cSDavid du Colombier }
684*206fef1cSDavid du Colombier
685*206fef1cSDavid du Colombier void
error(char * fmt,...)686*206fef1cSDavid du Colombier error(char *fmt, ...)
687*206fef1cSDavid du Colombier {
688*206fef1cSDavid du Colombier va_list arg;
689*206fef1cSDavid du Colombier static char buf[2048];
690*206fef1cSDavid du Colombier
691*206fef1cSDavid du Colombier va_start(arg, fmt);
692*206fef1cSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, arg);
693*206fef1cSDavid du Colombier va_end(arg);
694*206fef1cSDavid du Colombier fprint(2, "%s: %s\n", argv0, buf);
695*206fef1cSDavid du Colombier exits("error");
696*206fef1cSDavid du Colombier }
697*206fef1cSDavid du Colombier
698*206fef1cSDavid du Colombier void
warning(char * s)699*206fef1cSDavid du Colombier warning(char *s)
700*206fef1cSDavid du Colombier {
701*206fef1cSDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, s);
702*206fef1cSDavid du Colombier }
703*206fef1cSDavid du Colombier
704*206fef1cSDavid du Colombier /*
705*206fef1cSDavid du Colombier * send a reply to the client
706*206fef1cSDavid du Colombier */
707*206fef1cSDavid du Colombier void
sendreply(char * err)708*206fef1cSDavid du Colombier sendreply(char *err)
709*206fef1cSDavid du Colombier {
710*206fef1cSDavid du Colombier
711*206fef1cSDavid du Colombier if(err){
712*206fef1cSDavid du Colombier c.rhdr.type = Rerror;
713*206fef1cSDavid du Colombier c.rhdr.ename = err;
714*206fef1cSDavid du Colombier }else{
715*206fef1cSDavid du Colombier c.rhdr.type = c.thdr.type+1;
716*206fef1cSDavid du Colombier c.rhdr.fid = c.thdr.fid;
717*206fef1cSDavid du Colombier }
718*206fef1cSDavid du Colombier c.rhdr.tag = c.thdr.tag;
719*206fef1cSDavid du Colombier sendmsg(&c, &c.rhdr);
720*206fef1cSDavid du Colombier }
721*206fef1cSDavid du Colombier
722*206fef1cSDavid du Colombier /*
723*206fef1cSDavid du Colombier * send a request to the server, get the reply, and send that to
724*206fef1cSDavid du Colombier * the client
725*206fef1cSDavid du Colombier */
726*206fef1cSDavid du Colombier int
delegate(void)727*206fef1cSDavid du Colombier delegate(void)
728*206fef1cSDavid du Colombier {
729*206fef1cSDavid du Colombier int type;
730*206fef1cSDavid du Colombier
731*206fef1cSDavid du Colombier type = c.thdr.type;
732*206fef1cSDavid du Colombier if(statson){
733*206fef1cSDavid du Colombier cfsstat.sm[type].n++;
734*206fef1cSDavid du Colombier cfsstat.sm[type].s = nsec();
735*206fef1cSDavid du Colombier }
736*206fef1cSDavid du Colombier
737*206fef1cSDavid du Colombier sendmsg(&s, &c.thdr);
738*206fef1cSDavid du Colombier rcvmsg(&s, &s.rhdr);
739*206fef1cSDavid du Colombier
740*206fef1cSDavid du Colombier if(statson)
741*206fef1cSDavid du Colombier cfsstat.sm[type].t += nsec() - cfsstat.sm[type].s;
742*206fef1cSDavid du Colombier
743*206fef1cSDavid du Colombier sendmsg(&c, &s.rhdr);
744*206fef1cSDavid du Colombier return c.thdr.type+1 == s.rhdr.type ? 0 : -1;
745*206fef1cSDavid du Colombier }
746*206fef1cSDavid du Colombier
747*206fef1cSDavid du Colombier /*
748*206fef1cSDavid du Colombier * send a request to the server and get a reply
749*206fef1cSDavid du Colombier */
750*206fef1cSDavid du Colombier int
askserver(void)751*206fef1cSDavid du Colombier askserver(void)
752*206fef1cSDavid du Colombier {
753*206fef1cSDavid du Colombier int type;
754*206fef1cSDavid du Colombier
755*206fef1cSDavid du Colombier s.thdr.tag = c.thdr.tag;
756*206fef1cSDavid du Colombier
757*206fef1cSDavid du Colombier type = s.thdr.type;
758*206fef1cSDavid du Colombier if(statson){
759*206fef1cSDavid du Colombier cfsstat.sm[type].n++;
760*206fef1cSDavid du Colombier cfsstat.sm[type].s = nsec();
761*206fef1cSDavid du Colombier }
762*206fef1cSDavid du Colombier
763*206fef1cSDavid du Colombier sendmsg(&s, &s.thdr);
764*206fef1cSDavid du Colombier rcvmsg(&s, &s.rhdr);
765*206fef1cSDavid du Colombier
766*206fef1cSDavid du Colombier if(statson)
767*206fef1cSDavid du Colombier cfsstat.sm[type].t += nsec() - cfsstat.sm[type].s;
768*206fef1cSDavid du Colombier
769*206fef1cSDavid du Colombier return s.thdr.type+1 == s.rhdr.type ? 0 : -1;
770*206fef1cSDavid du Colombier }
771*206fef1cSDavid du Colombier
772*206fef1cSDavid du Colombier /*
773*206fef1cSDavid du Colombier * send/receive messages with logging
774*206fef1cSDavid du Colombier */
775*206fef1cSDavid du Colombier void
sendmsg(P9fs * p,Fcall * f)776*206fef1cSDavid du Colombier sendmsg(P9fs *p, Fcall *f)
777*206fef1cSDavid du Colombier {
778*206fef1cSDavid du Colombier DPRINT(2, "->%s: %F\n", p->name, f);
779*206fef1cSDavid du Colombier
780*206fef1cSDavid du Colombier p->len = convS2M(f, datasnd, messagesize);
781*206fef1cSDavid du Colombier if(p->len <= 0)
782*206fef1cSDavid du Colombier error("convS2M");
783*206fef1cSDavid du Colombier if(write(p->fd[1], datasnd, p->len)!=p->len)
784*206fef1cSDavid du Colombier error("sendmsg");
785*206fef1cSDavid du Colombier }
786*206fef1cSDavid du Colombier
787*206fef1cSDavid du Colombier void
dump(uchar * p,int len)788*206fef1cSDavid du Colombier dump(uchar *p, int len)
789*206fef1cSDavid du Colombier {
790*206fef1cSDavid du Colombier fprint(2, "%d bytes", len);
791*206fef1cSDavid du Colombier while(len-- > 0)
792*206fef1cSDavid du Colombier fprint(2, " %.2ux", *p++);
793*206fef1cSDavid du Colombier fprint(2, "\n");
794*206fef1cSDavid du Colombier }
795*206fef1cSDavid du Colombier
796*206fef1cSDavid du Colombier void
rcvmsg(P9fs * p,Fcall * f)797*206fef1cSDavid du Colombier rcvmsg(P9fs *p, Fcall *f)
798*206fef1cSDavid du Colombier {
799*206fef1cSDavid du Colombier int olen, rlen;
800*206fef1cSDavid du Colombier char buf[128];
801*206fef1cSDavid du Colombier
802*206fef1cSDavid du Colombier olen = p->len;
803*206fef1cSDavid du Colombier p->len = read9pmsg(p->fd[0], datarcv, sizeof(datarcv));
804*206fef1cSDavid du Colombier if(p->len <= 0){
805*206fef1cSDavid du Colombier snprint(buf, sizeof buf, "read9pmsg(%d)->%ld: %r",
806*206fef1cSDavid du Colombier p->fd[0], p->len);
807*206fef1cSDavid du Colombier error(buf);
808*206fef1cSDavid du Colombier }
809*206fef1cSDavid du Colombier
810*206fef1cSDavid du Colombier if((rlen = convM2S(datarcv, p->len, f)) != p->len)
811*206fef1cSDavid du Colombier error("rcvmsg format error, expected length %d, got %d",
812*206fef1cSDavid du Colombier rlen, p->len);
813*206fef1cSDavid du Colombier if(f->fid >= Nfid){
814*206fef1cSDavid du Colombier fprint(2, "<-%s: %d %s on %d\n", p->name, f->type,
815*206fef1cSDavid du Colombier mname[f->type]? mname[f->type]: "mystery", f->fid);
816*206fef1cSDavid du Colombier dump((uchar*)datasnd, olen);
817*206fef1cSDavid du Colombier dump((uchar*)datarcv, p->len);
818*206fef1cSDavid du Colombier error("rcvmsg fid out of range");
819*206fef1cSDavid du Colombier }
820*206fef1cSDavid du Colombier DPRINT(2, "<-%s: %F\n", p->name, f);
821*206fef1cSDavid du Colombier }
822*206fef1cSDavid du Colombier
823*206fef1cSDavid du Colombier int
ctltest(Mfile * mf)824*206fef1cSDavid du Colombier ctltest(Mfile *mf)
825*206fef1cSDavid du Colombier {
826*206fef1cSDavid du Colombier return mf->busy && mf->qid.type == ctlqid.type &&
827*206fef1cSDavid du Colombier mf->qid.path == ctlqid.path;
828*206fef1cSDavid du Colombier }
829*206fef1cSDavid du Colombier
830*206fef1cSDavid du Colombier void
genstats(void)831*206fef1cSDavid du Colombier genstats(void)
832*206fef1cSDavid du Colombier {
833*206fef1cSDavid du Colombier int i;
834*206fef1cSDavid du Colombier char *p;
835*206fef1cSDavid du Colombier
836*206fef1cSDavid du Colombier p = statbuf;
837*206fef1cSDavid du Colombier
838*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
839*206fef1cSDavid du Colombier " Client Server\n");
840*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
841*206fef1cSDavid du Colombier " #calls Δ ms/call Δ #calls Δ ms/call Δ\n");
842*206fef1cSDavid du Colombier for (i = 0; i < nelem(cfsstat.cm); i++)
843*206fef1cSDavid du Colombier if(cfsstat.cm[i].n || cfsstat.sm[i].n) {
844*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
845*206fef1cSDavid du Colombier "%7lud %7lud ", cfsstat.cm[i].n,
846*206fef1cSDavid du Colombier cfsstat.cm[i].n - cfsprev.cm[i].n);
847*206fef1cSDavid du Colombier if (cfsstat.cm[i].n)
848*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
849*206fef1cSDavid du Colombier "%7.3f ", 0.000001*cfsstat.cm[i].t/
850*206fef1cSDavid du Colombier cfsstat.cm[i].n);
851*206fef1cSDavid du Colombier else
852*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
853*206fef1cSDavid du Colombier " ");
854*206fef1cSDavid du Colombier if(cfsstat.cm[i].n - cfsprev.cm[i].n)
855*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
856*206fef1cSDavid du Colombier "%7.3f ", 0.000001*
857*206fef1cSDavid du Colombier (cfsstat.cm[i].t - cfsprev.cm[i].t)/
858*206fef1cSDavid du Colombier (cfsstat.cm[i].n - cfsprev.cm[i].n));
859*206fef1cSDavid du Colombier else
860*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
861*206fef1cSDavid du Colombier " ");
862*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
863*206fef1cSDavid du Colombier "%7lud %7lud ", cfsstat.sm[i].n,
864*206fef1cSDavid du Colombier cfsstat.sm[i].n - cfsprev.sm[i].n);
865*206fef1cSDavid du Colombier if (cfsstat.sm[i].n)
866*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
867*206fef1cSDavid du Colombier "%7.3f ", 0.000001*cfsstat.sm[i].t/
868*206fef1cSDavid du Colombier cfsstat.sm[i].n);
869*206fef1cSDavid du Colombier else
870*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
871*206fef1cSDavid du Colombier " ");
872*206fef1cSDavid du Colombier if(cfsstat.sm[i].n - cfsprev.sm[i].n)
873*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
874*206fef1cSDavid du Colombier "%7.3f ", 0.000001*
875*206fef1cSDavid du Colombier (cfsstat.sm[i].t - cfsprev.sm[i].t)/
876*206fef1cSDavid du Colombier (cfsstat.sm[i].n - cfsprev.sm[i].n));
877*206fef1cSDavid du Colombier else
878*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p,
879*206fef1cSDavid du Colombier " ");
880*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%s\n",
881*206fef1cSDavid du Colombier mname[i]);
882*206fef1cSDavid du Colombier }
883*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndirread\n",
884*206fef1cSDavid du Colombier cfsstat.ndirread, cfsstat.ndirread - cfsprev.ndirread);
885*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndelegateread\n",
886*206fef1cSDavid du Colombier cfsstat.ndelegateread, cfsstat.ndelegateread -
887*206fef1cSDavid du Colombier cfsprev.ndelegateread);
888*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ninsert\n",
889*206fef1cSDavid du Colombier cfsstat.ninsert, cfsstat.ninsert - cfsprev.ninsert);
890*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndelete\n",
891*206fef1cSDavid du Colombier cfsstat.ndelete, cfsstat.ndelete - cfsprev.ndelete);
892*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud nupdate\n",
893*206fef1cSDavid du Colombier cfsstat.nupdate, cfsstat.nupdate - cfsprev.nupdate);
894*206fef1cSDavid du Colombier
895*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesread\n",
896*206fef1cSDavid du Colombier cfsstat.bytesread, cfsstat.bytesread - cfsprev.bytesread);
897*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud byteswritten\n",
898*206fef1cSDavid du Colombier cfsstat.byteswritten, cfsstat.byteswritten -
899*206fef1cSDavid du Colombier cfsprev.byteswritten);
900*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromserver\n",
901*206fef1cSDavid du Colombier cfsstat.bytesfromserver, cfsstat.bytesfromserver -
902*206fef1cSDavid du Colombier cfsprev.bytesfromserver);
903*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromdirs\n",
904*206fef1cSDavid du Colombier cfsstat.bytesfromdirs, cfsstat.bytesfromdirs -
905*206fef1cSDavid du Colombier cfsprev.bytesfromdirs);
906*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromcache\n",
907*206fef1cSDavid du Colombier cfsstat.bytesfromcache, cfsstat.bytesfromcache -
908*206fef1cSDavid du Colombier cfsprev.bytesfromcache);
909*206fef1cSDavid du Colombier p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytestocache\n",
910*206fef1cSDavid du Colombier cfsstat.bytestocache, cfsstat.bytestocache -
911*206fef1cSDavid du Colombier cfsprev.bytestocache);
912*206fef1cSDavid du Colombier statlen = p - statbuf;
913*206fef1cSDavid du Colombier cfsprev = cfsstat;
914*206fef1cSDavid du Colombier }
915