xref: /titanic_44/usr/src/cmd/fs.d/cachefs/cachefsstat/cachefsstat.c (revision 9a5557fdd04be37785607871e8d4189e39490129)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdarg.h>
33 #include <libintl.h>
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
36 #include <sys/stat.h>
37 #include <kstat.h>
38 #include <locale.h>
39 #include <sys/fs/cachefs_log.h>
40 #include "stats.h"
41 
42 void usage(char *);
43 void pr_err(char *, ...);
44 
45 static int zflag;
46 char *prog;
47 
48 static void print_stats(stats_cookie_t *, cachefs_kstat_key_t *, int);
49 
50 int
51 main(int argc, char **argv)
52 {
53 	int rc = 0;
54 	int i, c, errflg = 0;
55 	stats_cookie_t *sc = NULL;
56 	cachefs_kstat_key_t *key;
57 
58 	(void) setlocale(LC_ALL, "");
59 #if !defined(TEXT_DOMAIN)
60 #define	TEXT_DOMAIN "SYS_TEST"
61 #endif /* TEXT_DOMAIN */
62 	(void) textdomain(TEXT_DOMAIN);
63 
64 	if (prog = strrchr(argv[0], '/'))
65 		++prog;
66 	else
67 		prog = argv[0];
68 
69 	while ((c = getopt(argc, argv, "z")) != EOF)
70 		switch (c) {
71 		case 'z':
72 			++zflag;
73 			break;
74 
75 		case '?':
76 		default:
77 			++errflg;
78 			break;
79 		}
80 
81 	if (errflg) {
82 		usage(NULL);
83 		rc = -1;
84 		goto out;
85 	}
86 
87 	/*
88 	 * handle multiple mountpoints specified on command line
89 	 */
90 
91 	for (i = optind; i < argc; i++) {
92 		if ((sc = stats_create_mountpath(argv[i], prog)) == NULL) {
93 			pr_err(gettext("Cannot use %s"), argv[i]);
94 			rc = 1;
95 			continue;
96 		}
97 
98 		if (stats_inerror(sc)) {
99 			pr_err(stats_errorstr(sc));
100 			rc = stats_errno(sc);
101 			continue;
102 		}
103 		print_stats(sc, key = stats_getkey(sc), zflag);
104 		if (stats_inerror(sc)) {
105 			pr_err(stats_errorstr(sc));
106 			rc = stats_errno(sc);
107 		}
108 
109 		stats_destroy(sc);
110 		free(key);
111 	}
112 
113 	/*
114 	 * handle the case where no mountpoints were specified,
115 	 * i.e. show stats for all.
116 	 */
117 
118 	if (optind >= argc) {
119 		sc = stats_create_unbound(prog);
120 
121 		while ((key = stats_next(sc)) != NULL) {
122 			if (! key->ks_mounted) {
123 				free(key);
124 				continue;
125 			}
126 
127 			print_stats(sc, key, zflag);
128 			if (stats_inerror(sc)) {
129 				pr_err(stats_errorstr(sc));
130 				rc = stats_errno(sc);
131 			}
132 			free(key);
133 		}
134 		stats_destroy(sc);
135 	}
136 
137 out:
138 	return (rc);
139 }
140 
141 static void
142 print_stats(stats_cookie_t *sc, cachefs_kstat_key_t *key, int zero)
143 {
144 	uint_t misses, passes, fails, modifies;
145 	uint_t hitp, passtotal;
146 	uint_t gccount;
147 	u_longlong_t hits;
148 
149 	hits = (u_longlong_t)stats_hits(sc);
150 	misses = stats_misses(sc);
151 	if (hits + misses != 0)
152 		hitp = (uint_t)((100 * hits) / (hits + misses));
153 	else
154 		hitp = 100;
155 
156 	passes = stats_passes(sc);
157 	fails = stats_fails(sc);
158 	passtotal = passes + fails;
159 
160 	modifies = stats_modifies(sc);
161 
162 	gccount = stats_gc_count(sc);
163 
164 	printf("\n    %s\n", (char *)(uintptr_t)key->ks_mountpoint);
165 	printf(gettext(
166 		"\t         cache hit rate: %5u%% (%llu hits, %u misses)\n"),
167 		hitp, hits, misses);
168 	printf(gettext("\t     consistency checks: %6d (%d pass, %d fail)\n"),
169 	    passtotal, passes, fails);
170 	printf(gettext("\t               modifies: %6d\n"), modifies);
171 	printf(gettext("\t     garbage collection: %6d\n"), gccount);
172 	if (gccount != 0) {
173 		time_t gctime = stats_gc_time(sc);
174 		time_t before = stats_gc_before(sc);
175 		time_t after = stats_gc_after(sc);
176 
177 		if (gctime != (time_t)0)
178 			printf(gettext("\tlast garbage collection: %s"),
179 			    ctime(&gctime));
180 	}
181 
182 	if (zero)
183 		(void) stats_zero_stats(sc);
184 }
185 
186 
187 /*
188  *
189  *			usage
190  *
191  * Description:
192  *	Prints a short usage message.
193  * Arguments:
194  *	msgp	message to include with the usage message
195  * Returns:
196  * Preconditions:
197  */
198 
199 void
200 usage(char *msgp)
201 {
202 	if (msgp) {
203 		pr_err("%s", msgp);
204 	}
205 
206 	fprintf(stderr,
207 	    gettext("Usage: cachefsstat [ -z ] [ path ... ]\n"));
208 }
209 
210 /*
211  *
212  *			pr_err
213  *
214  * Description:
215  *	Prints an error message to stderr.
216  * Arguments:
217  *	fmt	printf style format
218  *	...	arguments for fmt
219  * Returns:
220  * Preconditions:
221  *	precond(fmt)
222  */
223 
224 void
225 pr_err(char *fmt, ...)
226 {
227 	va_list ap;
228 
229 	va_start(ap, fmt);
230 	(void) fprintf(stderr, gettext("cachefsstat: "));
231 	(void) vfprintf(stderr, fmt, ap);
232 	(void) fprintf(stderr, "\n");
233 	va_end(ap);
234 }
235