GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/nfsstat/nfsstat.c Lines: 0 126 0.0 %
Date: 2016-12-06 Branches: 0 52 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: nfsstat.c,v 1.35 2015/10/23 08:18:30 tedu Exp $	*/
2
/*	$NetBSD: nfsstat.c,v 1.7 1996/03/03 17:21:30 thorpej Exp $	*/
3
4
/*
5
 * Copyright (c) 1983, 1989, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * This code is derived from software contributed to Berkeley by
9
 * Rick Macklem at The University of Guelph.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
#include <sys/types.h>
37
#include <sys/mount.h>
38
#include <sys/sysctl.h>
39
#include <nfs/rpcv2.h>
40
#include <nfs/nfsproto.h>
41
#include <nfs/nfs.h>
42
#include <signal.h>
43
#include <fcntl.h>
44
#include <ctype.h>
45
#include <errno.h>
46
#include <kvm.h>
47
#include <nlist.h>
48
#include <unistd.h>
49
#include <stdio.h>
50
#include <stdlib.h>
51
#include <string.h>
52
#include <limits.h>
53
#include <paths.h>
54
#include <err.h>
55
56
#define SHOW_SERVER 0x01
57
#define SHOW_CLIENT 0x02
58
#define SHOW_ALL (SHOW_SERVER | SHOW_CLIENT)
59
60
struct nlist nl[] = {
61
#define	N_NFSSTAT	0
62
	{ "_nfsstats" },
63
	{ "" },
64
};
65
kvm_t *kd;
66
volatile sig_atomic_t signalled;	/* set if alarm goes off "early" */
67
int nfs_id;
68
69
void getnfsstats(struct nfsstats *);
70
void printhdr(void);
71
void intpr(u_int);
72
void sidewaysintpr(u_int, u_int);
73
void usage(void);
74
void catchalarm(int);
75
76
int
77
main(int argc, char *argv[])
78
{
79
	u_int interval, display = SHOW_ALL;
80
	extern int optind;
81
	extern char *optarg;
82
	char *memf, *nlistf;
83
	const char *errstr;
84
	int ch;
85
86
	interval = 0;
87
	memf = nlistf = NULL;
88
	while ((ch = getopt(argc, argv, "cM:N:sw:")) != -1)
89
		switch(ch) {
90
		case 'M':
91
			memf = optarg;
92
			break;
93
		case 'N':
94
			nlistf = optarg;
95
			break;
96
		case 'w':
97
			interval = (u_int)strtonum(optarg, 0, 1000, &errstr);
98
			if (errstr)
99
				errx(1, "invalid interval %s: %s",
100
				    optarg, errstr);
101
			break;
102
		case 's':
103
			display = SHOW_SERVER;
104
			break;
105
		case 'c':
106
			display = SHOW_CLIENT;
107
			break;
108
		case '?':
109
		default:
110
			usage();
111
		}
112
	argc -= optind;
113
	argv += optind;
114
115
	if (argc) {
116
		interval = (u_int)strtonum(*argv, 0, 1000, &errstr);
117
		if (errstr)
118
			errx(1, "invalid interval %s: %s", *argv, errstr);
119
		++argv;
120
		--argc;
121
	}
122
	if (nlistf || memf) {
123
		char errbuf[_POSIX2_LINE_MAX];
124
125
		if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == 0)
126
			errx(1, "nfsstat: %s", errbuf);
127
		if (kvm_nlist(kd, nl) != 0)
128
			errx(1, "kvm_nlist: can't get names");
129
	} else {
130
		int mib[4];
131
		size_t len;
132
133
		mib[0] = CTL_VFS;
134
		mib[1] = VFS_GENERIC;
135
		mib[2] = VFS_MAXTYPENUM;
136
		len = sizeof(nfs_id);
137
		if (sysctl(mib, 3, &nfs_id, &len, NULL, 0))
138
			err(1, "sysctl: VFS_MAXTYPENUM");
139
140
		for (; nfs_id; nfs_id--) {
141
			struct vfsconf vfsc;
142
143
			mib[0] = CTL_VFS;
144
			mib[1] = VFS_GENERIC;
145
			mib[2] = VFS_CONF;
146
			mib[3] = nfs_id;
147
148
			len = sizeof(vfsc);
149
			if (sysctl(mib, 4, &vfsc, &len, NULL, 0))
150
				continue;
151
152
			if (!strcmp(vfsc.vfc_name, MOUNT_NFS))
153
				break;
154
		}
155
		if (nfs_id == 0)
156
			errx(1, "cannot find nfs filesystem id");
157
	}
158
159
	if (interval)
160
		sidewaysintpr(interval, display);
161
	else
162
		intpr(display);
163
164
	return 0;
165
}
166
167
void
168
getnfsstats(struct nfsstats *p)
169
{
170
	if (kd) {
171
		if (kvm_read(kd, nl[N_NFSSTAT].n_value, p, sizeof(*p)) != sizeof(*p))
172
			errx(1, "kvm_read failed");
173
	} else {
174
		int mib[3];
175
		size_t len = sizeof(*p);
176
177
		mib[0] = CTL_VFS;
178
		mib[1] = nfs_id; /* 2 */
179
		mib[2] = NFS_NFSSTATS;
180
181
		if (sysctl(mib, 3, p, &len, NULL, 0))
182
			err(1, "sysctl");
183
	}
184
}
185
186
/*
187
 * Print a description of the nfs stats.
188
 */
189
void
190
intpr(u_int display)
191
{
192
	struct nfsstats nfsstats;
193
194
	getnfsstats(&nfsstats);
195
196
	if (display & SHOW_CLIENT) {
197
		printf("Client Info:\n");
198
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
199
		    "Getattr", "Setattr", "Lookup", "Readlink", "Read",
200
		    "Write", "Create", "Remove");
201
		printf("%9llu %9llu %9llu %9llu %9llu %9llu %9llu %9llu\n",
202
		    nfsstats.rpccnt[NFSPROC_GETATTR],
203
		    nfsstats.rpccnt[NFSPROC_SETATTR],
204
		    nfsstats.rpccnt[NFSPROC_LOOKUP],
205
		    nfsstats.rpccnt[NFSPROC_READLINK],
206
		    nfsstats.rpccnt[NFSPROC_READ],
207
		    nfsstats.rpccnt[NFSPROC_WRITE],
208
		    nfsstats.rpccnt[NFSPROC_CREATE],
209
		    nfsstats.rpccnt[NFSPROC_REMOVE]);
210
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
211
		    "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
212
		    "Readdir", "RdirPlus", "Access");
213
		printf("%9llu %9llu %9llu %9llu %9llu %9llu %9llu %9llu\n",
214
		    nfsstats.rpccnt[NFSPROC_RENAME],
215
		    nfsstats.rpccnt[NFSPROC_LINK],
216
		    nfsstats.rpccnt[NFSPROC_SYMLINK],
217
		    nfsstats.rpccnt[NFSPROC_MKDIR],
218
		    nfsstats.rpccnt[NFSPROC_RMDIR],
219
		    nfsstats.rpccnt[NFSPROC_READDIR],
220
		    nfsstats.rpccnt[NFSPROC_READDIRPLUS],
221
		    nfsstats.rpccnt[NFSPROC_ACCESS]);
222
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
223
		    "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
224
		printf("%9llu %9llu %9llu %9llu %9llu\n",
225
		    nfsstats.rpccnt[NFSPROC_MKNOD],
226
		    nfsstats.rpccnt[NFSPROC_FSSTAT],
227
		    nfsstats.rpccnt[NFSPROC_FSINFO],
228
		    nfsstats.rpccnt[NFSPROC_PATHCONF],
229
		    nfsstats.rpccnt[NFSPROC_COMMIT]);
230
		printf("Rpc Info:\n");
231
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
232
		    "TimedOut", "Invalid", "X Replies", "Retries", "Requests",
233
		    "FrcSync");
234
		printf("%9llu %9llu %9llu %9llu %9llu %9llu\n",
235
		    nfsstats.rpctimeouts,
236
		    nfsstats.rpcinvalid,
237
		    nfsstats.rpcunexpected,
238
		    nfsstats.rpcretries,
239
		    nfsstats.rpcrequests,
240
		    nfsstats.forcedsync);
241
		printf("Cache Info:\n");
242
		printf("%9.9s %9.9s %9.9s %9.9s",
243
		    "Attr Hits", "Misses", "Lkup Hits", "Misses");
244
		printf(" %9.9s %9.9s %9.9s %9.9s\n",
245
		    "BioR Hits", "Misses", "BioW Hits", "Misses");
246
		printf("%9llu %9llu %9llu %9llu",
247
		    nfsstats.attrcache_hits, nfsstats.attrcache_misses,
248
		    nfsstats.lookupcache_hits, nfsstats.lookupcache_misses);
249
		printf(" %9llu %9llu %9llu %9llu\n",
250
		    nfsstats.biocache_reads-nfsstats.read_bios,
251
		    nfsstats.read_bios,
252
		    nfsstats.biocache_writes-nfsstats.write_bios,
253
		    nfsstats.write_bios);
254
		printf("%9.9s %9.9s %9.9s %9.9s",
255
		    "BioRLHits", "Misses", "BioD Hits", "Misses");
256
		printf(" %9.9s %9.9s\n", "DirE Hits", "Misses");
257
		printf("%9llu %9llu %9llu %9llu",
258
		    nfsstats.biocache_readlinks-nfsstats.readlink_bios,
259
		    nfsstats.readlink_bios,
260
		    nfsstats.biocache_readdirs-nfsstats.readdir_bios,
261
		    nfsstats.readdir_bios);
262
		printf(" %9llu %9llu\n",
263
		    nfsstats.direofcache_hits, nfsstats.direofcache_misses);
264
	}
265
266
	if (display == SHOW_ALL)
267
		printf("\n");
268
269
	if (display & SHOW_SERVER) {
270
		printf("Server Info:\n");
271
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
272
		    "Getattr", "Setattr", "Lookup", "Readlink", "Read",
273
		    "Write", "Create", "Remove");
274
		printf("%9llu %9llu %9llu %9llu %9llu %9llu %9llu %9llu\n",
275
		    nfsstats.srvrpccnt[NFSPROC_GETATTR],
276
		    nfsstats.srvrpccnt[NFSPROC_SETATTR],
277
		    nfsstats.srvrpccnt[NFSPROC_LOOKUP],
278
		    nfsstats.srvrpccnt[NFSPROC_READLINK],
279
		    nfsstats.srvrpccnt[NFSPROC_READ],
280
		    nfsstats.srvrpccnt[NFSPROC_WRITE],
281
		    nfsstats.srvrpccnt[NFSPROC_CREATE],
282
		    nfsstats.srvrpccnt[NFSPROC_REMOVE]);
283
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
284
		    "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
285
		    "Readdir", "RdirPlus", "Access");
286
		printf("%9llu %9llu %9llu %9llu %9llu %9llu %9llu %9llu\n",
287
		    nfsstats.srvrpccnt[NFSPROC_RENAME],
288
		    nfsstats.srvrpccnt[NFSPROC_LINK],
289
		    nfsstats.srvrpccnt[NFSPROC_SYMLINK],
290
		    nfsstats.srvrpccnt[NFSPROC_MKDIR],
291
		    nfsstats.srvrpccnt[NFSPROC_RMDIR],
292
		    nfsstats.srvrpccnt[NFSPROC_READDIR],
293
		    nfsstats.srvrpccnt[NFSPROC_READDIRPLUS],
294
		    nfsstats.srvrpccnt[NFSPROC_ACCESS]);
295
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
296
		    "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
297
		printf("%9llu %9llu %9llu %9llu %9llu\n",
298
		    nfsstats.srvrpccnt[NFSPROC_MKNOD],
299
		    nfsstats.srvrpccnt[NFSPROC_FSSTAT],
300
		    nfsstats.srvrpccnt[NFSPROC_FSINFO],
301
		    nfsstats.srvrpccnt[NFSPROC_PATHCONF],
302
		    nfsstats.srvrpccnt[NFSPROC_COMMIT]);
303
		printf("Server Ret-Failed\n");
304
		printf("%17llu\n", nfsstats.srvrpc_errs);
305
		printf("Server Faults\n");
306
		printf("%13llu\n", nfsstats.srv_errs);
307
		printf("Server Cache Stats:\n");
308
		printf("%9.9s %9.9s %9.9s %9.9s\n",
309
		    "Inprog", "Idem", "Non-idem", "Misses");
310
		printf("%9llu %9llu %9llu %9llu\n",
311
		    nfsstats.srvcache_inproghits,
312
		    nfsstats.srvcache_idemdonehits,
313
		    nfsstats.srvcache_nonidemdonehits,
314
		    nfsstats.srvcache_misses);
315
		printf("Server Write Gathering:\n");
316
		printf("%9.9s %9.9s %9.9s\n",
317
		    "WriteOps", "WriteRPC", "Opsaved");
318
		printf("%9llu %9llu %9llu\n",
319
		    nfsstats.srvvop_writes,
320
		    nfsstats.srvrpccnt[NFSPROC_WRITE],
321
		    nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes);
322
	}
323
}
324
325
/*
326
 * Print a running summary of nfs statistics.
327
 * Repeat display every interval seconds, showing statistics
328
 * collected over that interval.  Assumes that interval is non-zero.
329
 * First line printed at top of screen is always cumulative.
330
 */
331
void
332
sidewaysintpr(u_int interval, u_int display)
333
{
334
	struct nfsstats nfsstats, lastst;
335
	int hdrcnt;
336
	sigset_t emptyset;
337
338
	(void)signal(SIGALRM, catchalarm);
339
	signalled = 0;
340
	(void)alarm(interval);
341
	bzero(&lastst, sizeof(lastst));
342
343
	for (hdrcnt = 1;;) {
344
		if (!--hdrcnt) {
345
			printhdr();
346
			hdrcnt = 20;
347
		}
348
349
		getnfsstats(&nfsstats);
350
351
		if (display & SHOW_CLIENT)
352
			printf("Client: "
353
			    "%8llu %8llu %8llu %8llu %8llu %8llu %8llu %8llu\n",
354
			    nfsstats.rpccnt[NFSPROC_GETATTR] -
355
			    lastst.rpccnt[NFSPROC_GETATTR],
356
			    nfsstats.rpccnt[NFSPROC_LOOKUP] -
357
			    lastst.rpccnt[NFSPROC_LOOKUP],
358
			    nfsstats.rpccnt[NFSPROC_READLINK] -
359
			    lastst.rpccnt[NFSPROC_READLINK],
360
			    nfsstats.rpccnt[NFSPROC_READ] -
361
			    lastst.rpccnt[NFSPROC_READ],
362
			    nfsstats.rpccnt[NFSPROC_WRITE] -
363
			    lastst.rpccnt[NFSPROC_WRITE],
364
			    nfsstats.rpccnt[NFSPROC_RENAME] -
365
			    lastst.rpccnt[NFSPROC_RENAME],
366
			    nfsstats.rpccnt[NFSPROC_ACCESS] -
367
			    lastst.rpccnt[NFSPROC_ACCESS],
368
			    (nfsstats.rpccnt[NFSPROC_READDIR] -
369
			    lastst.rpccnt[NFSPROC_READDIR]) +
370
			    (nfsstats.rpccnt[NFSPROC_READDIRPLUS] -
371
			    lastst.rpccnt[NFSPROC_READDIRPLUS]));
372
		if (display & SHOW_SERVER)
373
			printf("Server: "
374
			    "%8llu %8llu %8llu %8llu %8llu %8llu %8llu %8llu\n",
375
			    nfsstats.srvrpccnt[NFSPROC_GETATTR] -
376
			    lastst.srvrpccnt[NFSPROC_GETATTR],
377
			    nfsstats.srvrpccnt[NFSPROC_LOOKUP] -
378
			    lastst.srvrpccnt[NFSPROC_LOOKUP],
379
			    nfsstats.srvrpccnt[NFSPROC_READLINK] -
380
			    lastst.srvrpccnt[NFSPROC_READLINK],
381
			    nfsstats.srvrpccnt[NFSPROC_READ] -
382
			    lastst.srvrpccnt[NFSPROC_READ],
383
			    nfsstats.srvrpccnt[NFSPROC_WRITE] -
384
			    lastst.srvrpccnt[NFSPROC_WRITE],
385
			    nfsstats.srvrpccnt[NFSPROC_RENAME] -
386
			    lastst.srvrpccnt[NFSPROC_RENAME],
387
			    nfsstats.srvrpccnt[NFSPROC_ACCESS] -
388
			    lastst.srvrpccnt[NFSPROC_ACCESS],
389
			    (nfsstats.srvrpccnt[NFSPROC_READDIR] -
390
			    lastst.srvrpccnt[NFSPROC_READDIR]) +
391
			    (nfsstats.srvrpccnt[NFSPROC_READDIRPLUS] -
392
			    lastst.srvrpccnt[NFSPROC_READDIRPLUS]));
393
		lastst = nfsstats;
394
		fflush(stdout);
395
		sigemptyset(&emptyset);
396
		if (!signalled)
397
			sigsuspend(&emptyset);
398
		signalled = 0;
399
		(void)alarm(interval);
400
	}
401
	/*NOTREACHED*/
402
}
403
404
void
405
printhdr(void)
406
{
407
	printf("        %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n",
408
	    "Getattr", "Lookup", "Readlink", "Read", "Write", "Rename",
409
	    "Access", "Readdir");
410
	fflush(stdout);
411
}
412
413
/*
414
 * Called if an interval expires before sidewaysintpr has completed a loop.
415
 * Sets a flag to not wait for the alarm.
416
 */
417
/* ARGSUSED */
418
void
419
catchalarm(int signo)
420
{
421
	signalled = 1;
422
}
423
424
void
425
usage(void)
426
{
427
	extern char *__progname;
428
429
	fprintf(stderr, "usage: %s [-cs] [-M core] [-N system] [-w wait]\n",
430
	    __progname);
431
	exit(1);
432
}