GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/nfsstat/nfsstat.c Lines: 0 212 0.0 %
Date: 2017-11-07 Branches: 0 54 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: nfsstat.c,v 1.36 2016/08/27 04:07:42 guenther 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 <sys/time.h>
40
#include <nfs/rpcv2.h>
41
#include <nfs/nfsproto.h>
42
#include <nfs/nfs.h>
43
#include <signal.h>
44
#include <fcntl.h>
45
#include <ctype.h>
46
#include <errno.h>
47
#include <kvm.h>
48
#include <nlist.h>
49
#include <unistd.h>
50
#include <stdio.h>
51
#include <stdlib.h>
52
#include <string.h>
53
#include <limits.h>
54
#include <paths.h>
55
#include <err.h>
56
57
#define SHOW_SERVER 0x01
58
#define SHOW_CLIENT 0x02
59
#define SHOW_ALL (SHOW_SERVER | SHOW_CLIENT)
60
61
struct nlist nl[] = {
62
#define	N_NFSSTAT	0
63
	{ "_nfsstats" },
64
	{ "" },
65
};
66
kvm_t *kd;
67
volatile sig_atomic_t signalled;	/* set if alarm goes off "early" */
68
int nfs_id;
69
70
void getnfsstats(struct nfsstats *);
71
void printhdr(void);
72
void intpr(u_int);
73
void sidewaysintpr(u_int, u_int);
74
void usage(void);
75
void catchalarm(int);
76
77
int
78
main(int argc, char *argv[])
79
{
80
	u_int interval, display = SHOW_ALL;
81
	extern int optind;
82
	extern char *optarg;
83
	char *memf, *nlistf;
84
	const char *errstr;
85
	int ch;
86
87
	interval = 0;
88
	memf = nlistf = NULL;
89
	while ((ch = getopt(argc, argv, "cM:N:sw:")) != -1)
90
		switch(ch) {
91
		case 'M':
92
			memf = optarg;
93
			break;
94
		case 'N':
95
			nlistf = optarg;
96
			break;
97
		case 'w':
98
			interval = (u_int)strtonum(optarg, 0, 1000, &errstr);
99
			if (errstr)
100
				errx(1, "invalid interval %s: %s",
101
				    optarg, errstr);
102
			break;
103
		case 's':
104
			display = SHOW_SERVER;
105
			break;
106
		case 'c':
107
			display = SHOW_CLIENT;
108
			break;
109
		case '?':
110
		default:
111
			usage();
112
		}
113
	argc -= optind;
114
	argv += optind;
115
116
	if (argc) {
117
		interval = (u_int)strtonum(*argv, 0, 1000, &errstr);
118
		if (errstr)
119
			errx(1, "invalid interval %s: %s", *argv, errstr);
120
		++argv;
121
		--argc;
122
	}
123
	if (nlistf || memf) {
124
		char errbuf[_POSIX2_LINE_MAX];
125
126
		if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == 0)
127
			errx(1, "nfsstat: %s", errbuf);
128
		if (kvm_nlist(kd, nl) != 0)
129
			errx(1, "kvm_nlist: can't get names");
130
	} else {
131
		int mib[4];
132
		size_t len;
133
134
		mib[0] = CTL_VFS;
135
		mib[1] = VFS_GENERIC;
136
		mib[2] = VFS_MAXTYPENUM;
137
		len = sizeof(nfs_id);
138
		if (sysctl(mib, 3, &nfs_id, &len, NULL, 0))
139
			err(1, "sysctl: VFS_MAXTYPENUM");
140
141
		for (; nfs_id; nfs_id--) {
142
			struct vfsconf vfsc;
143
144
			mib[0] = CTL_VFS;
145
			mib[1] = VFS_GENERIC;
146
			mib[2] = VFS_CONF;
147
			mib[3] = nfs_id;
148
149
			len = sizeof(vfsc);
150
			if (sysctl(mib, 4, &vfsc, &len, NULL, 0))
151
				continue;
152
153
			if (!strcmp(vfsc.vfc_name, MOUNT_NFS))
154
				break;
155
		}
156
		if (nfs_id == 0)
157
			errx(1, "cannot find nfs filesystem id");
158
	}
159
160
	if (interval)
161
		sidewaysintpr(interval, display);
162
	else
163
		intpr(display);
164
165
	return 0;
166
}
167
168
void
169
getnfsstats(struct nfsstats *p)
170
{
171
	if (kd) {
172
		if (kvm_read(kd, nl[N_NFSSTAT].n_value, p, sizeof(*p)) != sizeof(*p))
173
			errx(1, "kvm_read failed");
174
	} else {
175
		int mib[3];
176
		size_t len = sizeof(*p);
177
178
		mib[0] = CTL_VFS;
179
		mib[1] = nfs_id; /* 2 */
180
		mib[2] = NFS_NFSSTATS;
181
182
		if (sysctl(mib, 3, p, &len, NULL, 0))
183
			err(1, "sysctl");
184
	}
185
}
186
187
/*
188
 * Print a description of the nfs stats.
189
 */
190
void
191
intpr(u_int display)
192
{
193
	struct nfsstats nfsstats;
194
195
	getnfsstats(&nfsstats);
196
197
	if (display & SHOW_CLIENT) {
198
		printf("Client Info:\n");
199
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
200
		    "Getattr", "Setattr", "Lookup", "Readlink", "Read",
201
		    "Write", "Create", "Remove");
202
		printf("%9llu %9llu %9llu %9llu %9llu %9llu %9llu %9llu\n",
203
		    nfsstats.rpccnt[NFSPROC_GETATTR],
204
		    nfsstats.rpccnt[NFSPROC_SETATTR],
205
		    nfsstats.rpccnt[NFSPROC_LOOKUP],
206
		    nfsstats.rpccnt[NFSPROC_READLINK],
207
		    nfsstats.rpccnt[NFSPROC_READ],
208
		    nfsstats.rpccnt[NFSPROC_WRITE],
209
		    nfsstats.rpccnt[NFSPROC_CREATE],
210
		    nfsstats.rpccnt[NFSPROC_REMOVE]);
211
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
212
		    "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
213
		    "Readdir", "RdirPlus", "Access");
214
		printf("%9llu %9llu %9llu %9llu %9llu %9llu %9llu %9llu\n",
215
		    nfsstats.rpccnt[NFSPROC_RENAME],
216
		    nfsstats.rpccnt[NFSPROC_LINK],
217
		    nfsstats.rpccnt[NFSPROC_SYMLINK],
218
		    nfsstats.rpccnt[NFSPROC_MKDIR],
219
		    nfsstats.rpccnt[NFSPROC_RMDIR],
220
		    nfsstats.rpccnt[NFSPROC_READDIR],
221
		    nfsstats.rpccnt[NFSPROC_READDIRPLUS],
222
		    nfsstats.rpccnt[NFSPROC_ACCESS]);
223
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
224
		    "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
225
		printf("%9llu %9llu %9llu %9llu %9llu\n",
226
		    nfsstats.rpccnt[NFSPROC_MKNOD],
227
		    nfsstats.rpccnt[NFSPROC_FSSTAT],
228
		    nfsstats.rpccnt[NFSPROC_FSINFO],
229
		    nfsstats.rpccnt[NFSPROC_PATHCONF],
230
		    nfsstats.rpccnt[NFSPROC_COMMIT]);
231
		printf("Rpc Info:\n");
232
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
233
		    "TimedOut", "Invalid", "X Replies", "Retries", "Requests",
234
		    "FrcSync");
235
		printf("%9llu %9llu %9llu %9llu %9llu %9llu\n",
236
		    nfsstats.rpctimeouts,
237
		    nfsstats.rpcinvalid,
238
		    nfsstats.rpcunexpected,
239
		    nfsstats.rpcretries,
240
		    nfsstats.rpcrequests,
241
		    nfsstats.forcedsync);
242
		printf("Cache Info:\n");
243
		printf("%9.9s %9.9s %9.9s %9.9s",
244
		    "Attr Hits", "Misses", "Lkup Hits", "Misses");
245
		printf(" %9.9s %9.9s %9.9s %9.9s\n",
246
		    "BioR Hits", "Misses", "BioW Hits", "Misses");
247
		printf("%9llu %9llu %9llu %9llu",
248
		    nfsstats.attrcache_hits, nfsstats.attrcache_misses,
249
		    nfsstats.lookupcache_hits, nfsstats.lookupcache_misses);
250
		printf(" %9llu %9llu %9llu %9llu\n",
251
		    nfsstats.biocache_reads-nfsstats.read_bios,
252
		    nfsstats.read_bios,
253
		    nfsstats.biocache_writes-nfsstats.write_bios,
254
		    nfsstats.write_bios);
255
		printf("%9.9s %9.9s %9.9s %9.9s",
256
		    "BioRLHits", "Misses", "BioD Hits", "Misses");
257
		printf(" %9.9s %9.9s\n", "DirE Hits", "Misses");
258
		printf("%9llu %9llu %9llu %9llu",
259
		    nfsstats.biocache_readlinks-nfsstats.readlink_bios,
260
		    nfsstats.readlink_bios,
261
		    nfsstats.biocache_readdirs-nfsstats.readdir_bios,
262
		    nfsstats.readdir_bios);
263
		printf(" %9llu %9llu\n",
264
		    nfsstats.direofcache_hits, nfsstats.direofcache_misses);
265
	}
266
267
	if (display == SHOW_ALL)
268
		printf("\n");
269
270
	if (display & SHOW_SERVER) {
271
		printf("Server Info:\n");
272
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
273
		    "Getattr", "Setattr", "Lookup", "Readlink", "Read",
274
		    "Write", "Create", "Remove");
275
		printf("%9llu %9llu %9llu %9llu %9llu %9llu %9llu %9llu\n",
276
		    nfsstats.srvrpccnt[NFSPROC_GETATTR],
277
		    nfsstats.srvrpccnt[NFSPROC_SETATTR],
278
		    nfsstats.srvrpccnt[NFSPROC_LOOKUP],
279
		    nfsstats.srvrpccnt[NFSPROC_READLINK],
280
		    nfsstats.srvrpccnt[NFSPROC_READ],
281
		    nfsstats.srvrpccnt[NFSPROC_WRITE],
282
		    nfsstats.srvrpccnt[NFSPROC_CREATE],
283
		    nfsstats.srvrpccnt[NFSPROC_REMOVE]);
284
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
285
		    "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
286
		    "Readdir", "RdirPlus", "Access");
287
		printf("%9llu %9llu %9llu %9llu %9llu %9llu %9llu %9llu\n",
288
		    nfsstats.srvrpccnt[NFSPROC_RENAME],
289
		    nfsstats.srvrpccnt[NFSPROC_LINK],
290
		    nfsstats.srvrpccnt[NFSPROC_SYMLINK],
291
		    nfsstats.srvrpccnt[NFSPROC_MKDIR],
292
		    nfsstats.srvrpccnt[NFSPROC_RMDIR],
293
		    nfsstats.srvrpccnt[NFSPROC_READDIR],
294
		    nfsstats.srvrpccnt[NFSPROC_READDIRPLUS],
295
		    nfsstats.srvrpccnt[NFSPROC_ACCESS]);
296
		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
297
		    "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
298
		printf("%9llu %9llu %9llu %9llu %9llu\n",
299
		    nfsstats.srvrpccnt[NFSPROC_MKNOD],
300
		    nfsstats.srvrpccnt[NFSPROC_FSSTAT],
301
		    nfsstats.srvrpccnt[NFSPROC_FSINFO],
302
		    nfsstats.srvrpccnt[NFSPROC_PATHCONF],
303
		    nfsstats.srvrpccnt[NFSPROC_COMMIT]);
304
		printf("Server Ret-Failed\n");
305
		printf("%17llu\n", nfsstats.srvrpc_errs);
306
		printf("Server Faults\n");
307
		printf("%13llu\n", nfsstats.srv_errs);
308
		printf("Server Cache Stats:\n");
309
		printf("%9.9s %9.9s %9.9s %9.9s\n",
310
		    "Inprog", "Idem", "Non-idem", "Misses");
311
		printf("%9llu %9llu %9llu %9llu\n",
312
		    nfsstats.srvcache_inproghits,
313
		    nfsstats.srvcache_idemdonehits,
314
		    nfsstats.srvcache_nonidemdonehits,
315
		    nfsstats.srvcache_misses);
316
		printf("Server Write Gathering:\n");
317
		printf("%9.9s %9.9s %9.9s\n",
318
		    "WriteOps", "WriteRPC", "Opsaved");
319
		printf("%9llu %9llu %9llu\n",
320
		    nfsstats.srvvop_writes,
321
		    nfsstats.srvrpccnt[NFSPROC_WRITE],
322
		    nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes);
323
	}
324
}
325
326
/*
327
 * Print a running summary of nfs statistics.
328
 * Repeat display every interval seconds, showing statistics
329
 * collected over that interval.  Assumes that interval is non-zero.
330
 * First line printed at top of screen is always cumulative.
331
 */
332
void
333
sidewaysintpr(u_int interval, u_int display)
334
{
335
	struct nfsstats nfsstats, lastst;
336
	int hdrcnt;
337
	sigset_t emptyset;
338
339
	(void)signal(SIGALRM, catchalarm);
340
	signalled = 0;
341
	(void)alarm(interval);
342
	bzero(&lastst, sizeof(lastst));
343
344
	for (hdrcnt = 1;;) {
345
		if (!--hdrcnt) {
346
			printhdr();
347
			hdrcnt = 20;
348
		}
349
350
		getnfsstats(&nfsstats);
351
352
		if (display & SHOW_CLIENT)
353
			printf("Client: "
354
			    "%8llu %8llu %8llu %8llu %8llu %8llu %8llu %8llu\n",
355
			    nfsstats.rpccnt[NFSPROC_GETATTR] -
356
			    lastst.rpccnt[NFSPROC_GETATTR],
357
			    nfsstats.rpccnt[NFSPROC_LOOKUP] -
358
			    lastst.rpccnt[NFSPROC_LOOKUP],
359
			    nfsstats.rpccnt[NFSPROC_READLINK] -
360
			    lastst.rpccnt[NFSPROC_READLINK],
361
			    nfsstats.rpccnt[NFSPROC_READ] -
362
			    lastst.rpccnt[NFSPROC_READ],
363
			    nfsstats.rpccnt[NFSPROC_WRITE] -
364
			    lastst.rpccnt[NFSPROC_WRITE],
365
			    nfsstats.rpccnt[NFSPROC_RENAME] -
366
			    lastst.rpccnt[NFSPROC_RENAME],
367
			    nfsstats.rpccnt[NFSPROC_ACCESS] -
368
			    lastst.rpccnt[NFSPROC_ACCESS],
369
			    (nfsstats.rpccnt[NFSPROC_READDIR] -
370
			    lastst.rpccnt[NFSPROC_READDIR]) +
371
			    (nfsstats.rpccnt[NFSPROC_READDIRPLUS] -
372
			    lastst.rpccnt[NFSPROC_READDIRPLUS]));
373
		if (display & SHOW_SERVER)
374
			printf("Server: "
375
			    "%8llu %8llu %8llu %8llu %8llu %8llu %8llu %8llu\n",
376
			    nfsstats.srvrpccnt[NFSPROC_GETATTR] -
377
			    lastst.srvrpccnt[NFSPROC_GETATTR],
378
			    nfsstats.srvrpccnt[NFSPROC_LOOKUP] -
379
			    lastst.srvrpccnt[NFSPROC_LOOKUP],
380
			    nfsstats.srvrpccnt[NFSPROC_READLINK] -
381
			    lastst.srvrpccnt[NFSPROC_READLINK],
382
			    nfsstats.srvrpccnt[NFSPROC_READ] -
383
			    lastst.srvrpccnt[NFSPROC_READ],
384
			    nfsstats.srvrpccnt[NFSPROC_WRITE] -
385
			    lastst.srvrpccnt[NFSPROC_WRITE],
386
			    nfsstats.srvrpccnt[NFSPROC_RENAME] -
387
			    lastst.srvrpccnt[NFSPROC_RENAME],
388
			    nfsstats.srvrpccnt[NFSPROC_ACCESS] -
389
			    lastst.srvrpccnt[NFSPROC_ACCESS],
390
			    (nfsstats.srvrpccnt[NFSPROC_READDIR] -
391
			    lastst.srvrpccnt[NFSPROC_READDIR]) +
392
			    (nfsstats.srvrpccnt[NFSPROC_READDIRPLUS] -
393
			    lastst.srvrpccnt[NFSPROC_READDIRPLUS]));
394
		lastst = nfsstats;
395
		fflush(stdout);
396
		sigemptyset(&emptyset);
397
		if (!signalled)
398
			sigsuspend(&emptyset);
399
		signalled = 0;
400
		(void)alarm(interval);
401
	}
402
	/*NOTREACHED*/
403
}
404
405
void
406
printhdr(void)
407
{
408
	printf("        %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n",
409
	    "Getattr", "Lookup", "Readlink", "Read", "Write", "Rename",
410
	    "Access", "Readdir");
411
	fflush(stdout);
412
}
413
414
/*
415
 * Called if an interval expires before sidewaysintpr has completed a loop.
416
 * Sets a flag to not wait for the alarm.
417
 */
418
/* ARGSUSED */
419
void
420
catchalarm(int signo)
421
{
422
	signalled = 1;
423
}
424
425
void
426
usage(void)
427
{
428
	extern char *__progname;
429
430
	fprintf(stderr, "usage: %s [-cs] [-M core] [-N system] [-w wait]\n",
431
	    __progname);
432
	exit(1);
433
}