Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_tlsv12/sys/src/cmd/iostats/statsrv.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <auth.h>
4
#include <fcall.h>
5
#define Extern	extern
6
#include "statfs.h"
7
 
8
char Ebadfid[]	= "Bad fid";
9
char Enotdir[]	="Not a directory";
10
char Edupfid[]	= "Fid already in use";
11
char Eopen[]	= "Fid already opened";
12
char Exmnt[]	= "Cannot .. past mount point";
13
char Enoauth[]	= "iostats: Authentication failed";
14
char Ebadver[]	= "Unrecognized 9P version";
15
 
16
int
17
okfile(char *s, int mode)
18
{
19
	if(strncmp(s, "/fd/", 3) == 0){
20
		/* 0, 1, and 2 we handle ourselves */
21
		if(s[4]=='/' || atoi(s+4) > 2)
22
			return 0;
23
		return 1;
24
	}
25
	if(strncmp(s, "/net/ssl", 8) == 0)
26
		return 0;
27
	if(strncmp(s, "/net/tls", 8) == 0)
28
		return 0;
29
	if(strncmp(s, "/srv/", 5) == 0 && ((mode&3) == OWRITE || (mode&3) == ORDWR))
30
		return 0;
31
	return 1;
32
}
33
 
34
void
35
update(Rpc *rpc, vlong t)
36
{
37
	vlong t2;
38
 
39
	t2 = nsec();
40
	t = t2 - t;
41
	if(t < 0)
42
		t = 0;
43
 
44
	rpc->time += t;
45
	if(t < rpc->lo)
46
		rpc->lo = t;
47
	if(t > rpc->hi)
48
		rpc->hi = t;
49
}
50
 
51
void
52
Xversion(Fsrpc *r)
53
{
54
	Fcall thdr;
55
	vlong t;
56
 
57
	t = nsec();
58
 
59
	if(r->work.msize > IOHDRSZ+Maxfdata)
60
		thdr.msize = IOHDRSZ+Maxfdata;
61
	else
62
		thdr.msize = r->work.msize;
63
	myiounit = thdr.msize - IOHDRSZ;
64
	if(strncmp(r->work.version, "9P2000", 6) != 0){
65
		reply(&r->work, &thdr, Ebadver);
66
		r->busy = 0;
67
		return;
68
	}
69
	thdr.version = "9P2000";
70
	/* BUG: should clunk all fids */
71
	reply(&r->work, &thdr, 0);
72
	r->busy = 0;
73
 
74
	update(&stats->rpc[Tversion], t);
75
}
76
 
77
void
78
Xauth(Fsrpc *r)
79
{
80
	Fcall thdr;
81
	vlong t;
82
 
83
	t = nsec();
84
 
85
	reply(&r->work, &thdr, Enoauth);
86
	r->busy = 0;
87
 
88
	update(&stats->rpc[Tauth], t);
89
}
90
 
91
void
92
Xflush(Fsrpc *r)
93
{
94
	Fsrpc *t, *e;
95
	Fcall thdr;
96
 
97
	e = &Workq[Nr_workbufs];
98
 
99
	for(t = Workq; t < e; t++) {
100
		if(t->work.tag == r->work.oldtag) {
101
			DEBUG(2, "\tQ busy %d pid %p can %d\n", t->busy, t->pid, t->canint);
102
			if(t->busy && t->pid) {
103
				t->flushtag = r->work.tag;
104
				DEBUG(2, "\tset flushtag %d\n", r->work.tag);
105
				if(t->canint)
106
					postnote(PNPROC, t->pid, "flush");
107
				r->busy = 0;
108
				return;
109
			}
110
		}
111
	}
112
 
113
	reply(&r->work, &thdr, 0);
114
	DEBUG(2, "\tflush reply\n");
115
	r->busy = 0;
116
}
117
 
118
void
119
Xattach(Fsrpc *r)
120
{
121
	Fcall thdr;
122
	Fid *f;
123
	vlong t;
124
 
125
	t = nsec();
126
 
127
	f = newfid(r->work.fid);
128
	if(f == 0) {
129
		reply(&r->work, &thdr, Ebadfid);
130
		r->busy = 0;
131
		return;
132
	}
133
 
134
	f->f = root;
135
	thdr.qid = f->f->qid;
136
	reply(&r->work, &thdr, 0);
137
	r->busy = 0;
138
 
139
	update(&stats->rpc[Tattach], t);
140
}
141
 
142
void
143
Xwalk(Fsrpc *r)
144
{
145
	char errbuf[ERRMAX], *err;
146
	Fcall thdr;
147
	Fid *f, *n;
148
	File *nf;
149
	vlong t;
150
	int i;
151
 
152
	t = nsec();
153
 
154
	f = getfid(r->work.fid);
155
	if(f == 0) {
156
		reply(&r->work, &thdr, Ebadfid);
157
		r->busy = 0;
158
		return;
159
	}
160
	n = nil;
161
	if(r->work.newfid != r->work.fid){
162
		n = newfid(r->work.newfid);
163
		if(n == 0) {
164
			reply(&r->work, &thdr, Edupfid);
165
			r->busy = 0;
166
			return;
167
		}
168
		n->f = f->f;
169
		f = n;	/* walk new guy */
170
	}
171
 
172
	thdr.nwqid = 0;
173
	err = nil;
174
	for(i=0; i<r->work.nwname; i++){
175
		if(i >= MAXWELEM)
176
			break;
177
		if(strcmp(r->work.wname[i], "..") == 0) {
178
			if(f->f->parent == 0) {
179
				err = Exmnt;
180
				break;
181
			}
182
			f->f = f->f->parent;
183
			thdr.wqid[thdr.nwqid++] = f->f->qid;
184
			continue;
185
		}
186
 
187
		nf = file(f->f, r->work.wname[i]);
188
		if(nf == 0) {
189
			errstr(errbuf, sizeof errbuf);
190
			err = errbuf;
191
			break;
192
		}
193
 
194
		f->f = nf;
195
		thdr.wqid[thdr.nwqid++] = nf->qid;
196
		continue;
197
	}
198
 
199
	if(err == nil && thdr.nwqid == 0 && r->work.nwname > 0)
200
		err = "file does not exist";
201
 
202
	if(n != nil && (err != 0 || thdr.nwqid < r->work.nwname)){
203
		/* clunk the new fid, which is the one we walked */
204
		freefid(n->nr);
205
	}
206
 
207
	if(thdr.nwqid > 0)
208
		err = nil;
209
	reply(&r->work, &thdr, err);
210
	r->busy = 0;
211
 
212
	update(&stats->rpc[Twalk], t);
213
}
214
 
215
void
216
Xclunk(Fsrpc *r)
217
{
218
	Fcall thdr;
219
	Fid *f;
220
	vlong t;
221
	int fid;
222
 
223
	t = nsec();
224
 
225
	f = getfid(r->work.fid);
226
	if(f == 0) {
227
		reply(&r->work, &thdr, Ebadfid);
228
		r->busy = 0;
229
		return;
230
	}
231
 
232
	if(f->fid >= 0)
233
		close(f->fid);
234
 
235
	fid = r->work.fid;
236
	reply(&r->work, &thdr, 0);
237
	r->busy = 0;
238
 
239
	update(&stats->rpc[Tclunk], t);
240
 
241
	if(f->nread || f->nwrite)
242
		fidreport(f);
243
 
244
	freefid(fid);
245
}
246
 
247
void
248
Xstat(Fsrpc *r)
249
{
250
	char err[ERRMAX], path[128];
251
	uchar statbuf[STATMAX];
252
	Fcall thdr;
253
	Fid *f;
254
	int s;
255
	vlong t;
256
 
257
	t = nsec();
258
 
259
	f = getfid(r->work.fid);
260
	if(f == 0) {
261
		reply(&r->work, &thdr, Ebadfid);
262
		r->busy = 0;
263
		return;
264
	}
265
	makepath(path, f->f, "");
266
	if(!okfile(path, -1)){
267
		snprint(err, sizeof err, "iostats: can't simulate %s", path);
268
		reply(&r->work, &thdr, err);
269
		r->busy = 0;
270
		return;
271
	}
272
 
273
	if(f->fid >= 0)
274
		s = fstat(f->fid, statbuf, sizeof statbuf);
275
	else
276
		s = stat(path, statbuf, sizeof statbuf);
277
 
278
	if(s < 0) {
279
		errstr(err, sizeof err);
280
		reply(&r->work, &thdr, err);
281
		r->busy = 0;
282
		return;
283
	}
284
	thdr.stat = statbuf;
285
	thdr.nstat = s;
286
	reply(&r->work, &thdr, 0);
287
	r->busy = 0;
288
 
289
	update(&stats->rpc[Tstat], t);
290
}
291
 
292
void
293
Xcreate(Fsrpc *r)
294
{
295
	char err[ERRMAX], path[128];
296
	Fcall thdr;
297
	Fid *f;
298
	File *nf;
299
	vlong t;
300
 
301
	t = nsec();
302
 
303
	f = getfid(r->work.fid);
304
	if(f == 0) {
305
		reply(&r->work, &thdr, Ebadfid);
306
		r->busy = 0;
307
		return;
308
	}
309
 
310
 
311
	makepath(path, f->f, r->work.name);
312
	f->fid = create(path, r->work.mode, r->work.perm);
313
	if(f->fid < 0) {
314
		errstr(err, sizeof err);
315
		reply(&r->work, &thdr, err);
316
		r->busy = 0;
317
		return;
318
	}
319
 
320
	nf = file(f->f, r->work.name);
321
	if(nf == 0) {
322
		errstr(err, sizeof err);
323
		reply(&r->work, &thdr, err);
324
		r->busy = 0;
325
		return;
326
	}
327
 
328
	f->mode = r->work.mode;
329
	f->f = nf;
330
	thdr.iounit = myiounit;
331
	thdr.qid = f->f->qid;
332
	reply(&r->work, &thdr, 0);
333
	r->busy = 0;
334
 
335
	update(&stats->rpc[Tcreate], t);
336
}
337
 
338
 
339
void
340
Xremove(Fsrpc *r)
341
{
342
	char err[ERRMAX], path[128];
343
	Fcall thdr;
344
	Fid *f;
345
	vlong t;
346
 
347
	t = nsec();
348
 
349
	f = getfid(r->work.fid);
350
	if(f == 0) {
351
		reply(&r->work, &thdr, Ebadfid);
352
		r->busy = 0;
353
		return;
354
	}
355
 
356
	makepath(path, f->f, "");
357
	DEBUG(2, "\tremove: %s\n", path);
358
	if(remove(path) < 0) {
359
		errstr(err, sizeof err);
360
		reply(&r->work, &thdr, err);
361
		freefid(r->work.fid);
362
		r->busy = 0;
363
		return;
364
	}
365
 
366
	f->f->inval = 1;
367
	if(f->fid >= 0)
368
		close(f->fid);
369
	freefid(r->work.fid);
370
 
371
	reply(&r->work, &thdr, 0);
372
	r->busy = 0;
373
 
374
	update(&stats->rpc[Tremove], t);
375
}
376
 
377
void
378
Xwstat(Fsrpc *r)
379
{
380
	char err[ERRMAX], path[128];
381
	Fcall thdr;
382
	Fid *f;
383
	int s;
384
	vlong t;
385
 
386
	t = nsec();
387
 
388
	f = getfid(r->work.fid);
389
	if(f == 0) {
390
		reply(&r->work, &thdr, Ebadfid);
391
		r->busy = 0;
392
		return;
393
	}
394
	if(f->fid >= 0)
395
		s = fwstat(f->fid, r->work.stat, r->work.nstat);
396
	else {
397
		makepath(path, f->f, "");
398
		s = wstat(path, r->work.stat, r->work.nstat);
399
	}
400
	if(s < 0) {
401
		errstr(err, sizeof err);
402
		reply(&r->work, &thdr, err);
403
	}
404
	else
405
		reply(&r->work, &thdr, 0);
406
 
407
	r->busy = 0;
408
	update(&stats->rpc[Twstat], t);
409
}
410
 
411
void
412
slave(Fsrpc *f)
413
{
414
	int r;
415
	Proc *p;
416
	uintptr pid;
417
	static int nproc;
418
 
419
	for(;;) {
420
		for(p = Proclist; p; p = p->next) {
421
			if(p->busy == 0) {
422
				f->pid = p->pid;
423
				p->busy = 1;
424
				pid = (uintptr)rendezvous((void*)p->pid, f);
425
				if(pid != p->pid)
426
					fatal("rendezvous sync fail");
427
				return;
428
			}	
429
		}
430
 
431
		if(++nproc > MAXPROC)
432
			fatal("too many procs");
433
 
434
		r = rfork(RFPROC|RFMEM);
435
		if(r < 0)
436
			fatal("rfork");
437
 
438
		if(r == 0)
439
			blockingslave();
440
 
441
		p = malloc(sizeof(Proc));
442
		if(p == 0)
443
			fatal("out of memory");
444
 
445
		p->busy = 0;
446
		p->pid = r;
447
		p->next = Proclist;
448
		Proclist = p;
449
 
450
		rendezvous((void*)p->pid, p);
451
	}
452
}
453
 
454
void
455
blockingslave(void)
456
{
457
	Proc *m;
458
	uintptr pid;
459
	Fsrpc *p;
460
	Fcall thdr;
461
 
462
	notify(flushaction);
463
 
464
	pid = getpid();
465
 
466
	m = rendezvous((void*)pid, 0);
467
 
468
	for(;;) {
469
		p = rendezvous((void*)pid, (void*)pid);
470
		if(p == (void*)~0)			/* Interrupted */
471
			continue;
472
 
473
		DEBUG(2, "\tslave: %p %F b %d p %p\n", pid, &p->work, p->busy, p->pid);
474
		if(p->flushtag != NOTAG)
475
			return;
476
 
477
		switch(p->work.type) {
478
		case Tread:
479
			slaveread(p);
480
			break;
481
		case Twrite:
482
			slavewrite(p);
483
			break;
484
		case Topen:
485
			slaveopen(p);
486
			break;
487
		default:
488
			reply(&p->work, &thdr, "exportfs: slave type error");
489
		}
490
		if(p->flushtag != NOTAG) {
491
			p->work.type = Tflush;
492
			p->work.tag = p->flushtag;
493
			reply(&p->work, &thdr, 0);
494
		}
495
		p->busy = 0;	
496
		m->busy = 0;
497
	}
498
}
499
 
500
void
501
slaveopen(Fsrpc *p)
502
{
503
	char err[ERRMAX], path[128];
504
	Fcall *work, thdr;
505
	Fid *f;
506
	vlong t;
507
 
508
	work = &p->work;
509
 
510
	t = nsec();
511
 
512
	f = getfid(work->fid);
513
	if(f == 0) {
514
		reply(work, &thdr, Ebadfid);
515
		return;
516
	}
517
	if(f->fid >= 0) {
518
		close(f->fid);
519
		f->fid = -1;
520
	}
521
 
522
	makepath(path, f->f, "");
523
	DEBUG(2, "\topen: %s %d\n", path, work->mode);
524
 
525
	p->canint = 1;
526
	if(p->flushtag != NOTAG)
527
		return;
528
 
529
	if(!okfile(path, work->mode)){
530
		snprint(err, sizeof err, "iostats can't simulate %s", path);
531
		reply(work, &thdr, err);
532
		return;
533
	}
534
 
535
	/* There is a race here I ignore because there are no locks */
536
	f->fid = open(path, work->mode);
537
	p->canint = 0;
538
	if(f->fid < 0) {
539
		errstr(err, sizeof err);
540
		reply(work, &thdr, err);
541
		return;
542
	}
543
 
544
	DEBUG(2, "\topen: fd %d\n", f->fid);
545
	f->mode = work->mode;
546
	thdr.iounit = myiounit;
547
	thdr.qid = f->f->qid;
548
	reply(work, &thdr, 0);
549
 
550
	update(&stats->rpc[Topen], t);
551
}
552
 
553
void
554
slaveread(Fsrpc *p)
555
{
556
	char data[Maxfdata], err[ERRMAX];
557
	Fcall *work, thdr;
558
	Fid *f;
559
	int n, r;
560
	vlong t;
561
 
562
	work = &p->work;
563
 
564
	t = nsec();
565
 
566
	f = getfid(work->fid);
567
	if(f == 0) {
568
		reply(work, &thdr, Ebadfid);
569
		return;
570
	}
571
 
572
	n = (work->count > Maxfdata) ? Maxfdata : work->count;
573
	p->canint = 1;
574
	if(p->flushtag != NOTAG)
575
		return;
576
	/* can't just call pread, since directories must update the offset */
577
	if(f->f->qid.type&QTDIR){
578
		if(work->offset != f->offset){
579
			if(work->offset != 0){
580
				snprint(err, sizeof err, "can't seek in directory from %lld to %lld", f->offset, work->offset);
581
				reply(work, &thdr, err);
582
				return;
583
			}
584
			if(seek(f->fid, 0, 0) != 0){
585
				errstr(err, sizeof err);
586
				reply(work, &thdr, err);
587
				return;	
588
			}
589
			f->offset = 0;
590
		}
591
		r = read(f->fid, data, n);
592
		if(r > 0)
593
			f->offset += r;
594
	}else
595
		r = pread(f->fid, data, n, work->offset);
596
	p->canint = 0;
597
	if(r < 0) {
598
		errstr(err, sizeof err);
599
		reply(work, &thdr, err);
600
		return;
601
	}
602
 
603
	DEBUG(2, "\tread: fd=%d %d bytes\n", f->fid, r);
604
 
605
	thdr.data = data;
606
	thdr.count = r;
607
	stats->totread += r;
608
	f->nread++;
609
	f->bread += r;
610
	reply(work, &thdr, 0);
611
 
612
	update(&stats->rpc[Tread], t);
613
}
614
 
615
void
616
slavewrite(Fsrpc *p)
617
{
618
	char err[ERRMAX];
619
	Fcall *work, thdr;
620
	Fid *f;
621
	int n;
622
	vlong t;
623
 
624
	work = &p->work;
625
 
626
	t = nsec();
627
 
628
	f = getfid(work->fid);
629
	if(f == 0) {
630
		reply(work, &thdr, Ebadfid);
631
		return;
632
	}
633
 
634
	n = (work->count > Maxfdata) ? Maxfdata : work->count;
635
	p->canint = 1;
636
	if(p->flushtag != NOTAG)
637
		return;
638
	n = pwrite(f->fid, work->data, n, work->offset);
639
	p->canint = 0;
640
	if(n < 0) {
641
		errstr(err, sizeof err);
642
		reply(work, &thdr, err);
643
		return;
644
	}
645
 
646
	DEBUG(2, "\twrite: %d bytes fd=%d\n", n, f->fid);
647
 
648
	thdr.count = n;
649
	f->nwrite++;
650
	f->bwrite += n;
651
	stats->totwrite += n;
652
	reply(work, &thdr, 0);
653
 
654
	update(&stats->rpc[Twrite], t);
655
}
656
 
657
void
658
reopen(Fid *f)
659
{
660
	USED(f);
661
	fatal("reopen");
662
}
663
 
664
void
665
flushaction(void *a, char *cause)
666
{
667
	USED(a);
668
	if(strncmp(cause, "kill", 4) == 0)
669
		noted(NDFLT);
670
 
671
	noted(NCONT);
672
}