xref: /illumos-gate/usr/src/cmd/smbsrv/smbstat/smbstat.c (revision 3d393ee6c37fa10ac512ed6d36109ad616dc7c1a)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 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 /*
30  * smbstat: Server Message Block File System statistics
31  */
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <kstat.h>
35 #include <stdarg.h>
36 #include <errno.h>
37 #include <inttypes.h>
38 #include <strings.h>
39 #include <utility.h>
40 #include <libintl.h>
41 #include <zone.h>
42 #include <smbsrv/smb_kstat.h>
43 
44 static kstat_ctl_t	*kc;		/* libkstat cookie */
45 static kstat_t		*smb_server;
46 static kstat_t		*smb_cmds;
47 
48 static int get_smbinfo_stat(void);
49 static int get_smbdispatch_stat(void);
50 static void smbstat_init(void);
51 static void smbstat_fini(void);
52 static void smbstat_smb_server_print();
53 static void smbstat_smb_cmds_print();
54 static void smbstat_print(const char *, kstat_t *, int);
55 static int smbstat_width(kstat_t *, int);
56 static void smbstat_fail(int, char *, ...);
57 static kid_t smbstat_kstat_read(kstat_ctl_t *, kstat_t *, void *);
58 static void smbstat_usage(void);
59 
60 #define	MAX_COLUMNS	80
61 
62 int
63 main(int argc, char *argv[])
64 {
65 	int c;
66 	int iflag = 0;		/* smb_server stats */
67 	int dflag = 0;		/* smb_cmds_all stats */
68 
69 	if (getzoneid() != GLOBAL_ZONEID) {
70 		(void) fprintf(stderr,
71 		    gettext("%s: Cannot execute in non-global zone.\n"),
72 		    argv[0]);
73 		return (0);
74 	}
75 
76 	if (is_system_labeled()) {
77 		(void) fprintf(stderr,
78 		    gettext("%s: Trusted Extensions not supported.\n"),
79 		    argv[0]);
80 		return (0);
81 	}
82 
83 	while ((c = getopt(argc, argv, "id")) != EOF) {
84 		switch (c) {
85 		case 'i':
86 			iflag++;
87 			break;
88 		case 'd':
89 			dflag++;
90 			break;
91 		case '?':
92 		default:
93 			smbstat_usage();
94 		}
95 	}
96 
97 	if ((argc - optind) > 0) {
98 		smbstat_usage();
99 	}
100 
101 	smbstat_init();
102 
103 	if (iflag) {
104 		smbstat_smb_server_print();
105 	} else if (dflag) {
106 		smbstat_smb_cmds_print();
107 	} else {
108 		smbstat_smb_server_print();
109 		smbstat_smb_cmds_print();
110 	}
111 
112 	smbstat_fini();
113 	return (0);
114 }
115 
116 
117 static int
118 get_smbinfo_stat(void)
119 {
120 	(void) smbstat_kstat_read(kc, smb_server, NULL);
121 	return (smbstat_width(smb_server, 0));
122 }
123 
124 static int
125 get_smbdispatch_stat(void)
126 {
127 	(void) smbstat_kstat_read(kc, smb_cmds, NULL);
128 	return (smbstat_width(smb_cmds, 0));
129 }
130 
131 static void
132 smbstat_smb_server_print()
133 {
134 	int	field_width;
135 	int	i, j, nreq, ncolumns;
136 	char	fixlen[128];
137 	kstat_named_t *knp;
138 
139 	field_width = get_smbinfo_stat();
140 	if (field_width == 0)
141 		return;
142 
143 	(void) printf("%s\n", "\nSMB Info:\n");
144 	ncolumns = (MAX_COLUMNS -1)/field_width;
145 
146 	knp = KSTAT_NAMED_PTR(smb_server);
147 	nreq = smb_server->ks_ndata;
148 
149 	for (i = 0; i < nreq; i += ncolumns) {
150 		/* prints out the titles of the columns */
151 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
152 			(void) printf("%-*s", field_width, knp[j].name);
153 		}
154 		(void) printf("\n");
155 		/* prints out the stat numbers */
156 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
157 			(void) sprintf(fixlen, "%" PRIu32 " ",
158 			    knp[j].value.ui32);
159 			(void) printf("%-*s", field_width, fixlen);
160 		}
161 		(void) printf("\n");
162 	}
163 }
164 
165 static void
166 smbstat_smb_cmds_print()
167 {
168 	int field_width;
169 
170 	field_width = get_smbdispatch_stat();
171 	if (field_width == 0)
172 		return;
173 
174 	smbstat_print(gettext("\nAll dispatched SMB requests statistics:\n"),
175 	    smb_cmds, field_width);
176 }
177 
178 static void
179 smbstat_init(void)
180 {
181 	char	smbsrv_name[KSTAT_STRLEN];
182 
183 	(void) snprintf(smbsrv_name, sizeof (smbsrv_name), "%s%d",
184 	    SMBSRV_KSTAT_NAME, getzoneid());
185 
186 	if ((kc = kstat_open()) == NULL)
187 		smbstat_fail(1, gettext("kstat_open(): can't open /dev/kstat"));
188 
189 	smb_server = kstat_lookup(kc, SMBSRV_KSTAT_MODULE, 0, smbsrv_name);
190 	smb_cmds = kstat_lookup(kc, SMBSRV_KSTAT_MODULE, 0,
191 	    SMBSRV_KSTAT_NAME_CMDS);
192 
193 	if ((smb_server == NULL) || (smb_cmds == NULL))
194 		smbstat_fail(0, gettext("kstat lookups failed for smb. "
195 		    "Your kernel module may not be loaded\n"));
196 }
197 
198 static void
199 smbstat_fini(void)
200 {
201 	(void) kstat_close(kc);
202 }
203 
204 static int
205 smbstat_width(kstat_t *req, int field_width)
206 {
207 	int i, nreq, len;
208 	char fixlen[128];
209 	kstat_named_t *knp;
210 
211 	knp = KSTAT_NAMED_PTR(req);
212 	nreq = req->ks_ndata;
213 
214 	for (i = 0; i < nreq; i++) {
215 		len = strlen(knp[i].name) + 1;
216 		if (field_width < len)
217 			field_width = len;
218 		(void) sprintf(fixlen, "%" PRIu64, knp[i].value.ui64);
219 		len = strlen(fixlen) + 1;
220 		if (field_width < len)
221 			field_width = len;
222 	}
223 	return (field_width);
224 }
225 
226 static void
227 smbstat_print(const char *title_string, kstat_t *req, int field_width)
228 {
229 	int i, j, nreq, ncolumns;
230 	char fixlen[128];
231 	kstat_named_t *knp;
232 
233 	if (req == NULL)
234 		return;
235 
236 	if (field_width == 0)
237 		return;
238 
239 	(void) printf("%s\n", title_string);
240 	ncolumns = (MAX_COLUMNS -1)/field_width;
241 
242 	knp = KSTAT_NAMED_PTR(req);
243 	nreq = req->ks_ndata;
244 
245 	for (i = 0; i < nreq; i += ncolumns) {
246 		/* prints out the titles of the columns */
247 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
248 			(void) printf("%-*s", field_width, knp[j].name);
249 		}
250 		(void) printf("\n");
251 		/* prints out the stat numbers */
252 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
253 			(void) sprintf(fixlen, "%" PRIu64 " ",
254 			    knp[j].value.ui64);
255 			(void) printf("%-*s", field_width, fixlen);
256 		}
257 		(void) printf("\n");
258 
259 	}
260 }
261 
262 static void
263 smbstat_usage(void)
264 {
265 	(void) fprintf(stderr, gettext("Usage: smbstat [-id]\n"));
266 	exit(1);
267 }
268 
269 static void
270 smbstat_fail(int do_perror, char *message, ...)
271 {
272 	va_list args;
273 
274 	va_start(args, message);
275 	(void) fprintf(stderr, gettext("smbstat: "));
276 	/* LINTED E_SEC_PRINTF_VAR_FMT */
277 	(void) vfprintf(stderr, message, args);
278 	va_end(args);
279 	if (do_perror)
280 		(void) fprintf(stderr, ": %s", strerror(errno));
281 	(void) fprintf(stderr, "\n");
282 	exit(1);
283 }
284 
285 static kid_t
286 smbstat_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data)
287 {
288 	kid_t kstat_chain_id = kstat_read(kc, ksp, data);
289 
290 	if (kstat_chain_id == -1)
291 		smbstat_fail(1, gettext("kstat_read('%s') failed"),
292 		    ksp->ks_name);
293 	return (kstat_chain_id);
294 }
295 
296 /*
297  * Enable libumem debugging by default on DEBUG builds.
298  */
299 #ifdef DEBUG
300 const char *
301 _umem_debug_init(void)
302 {
303 	return ("default,verbose"); /* $UMEM_DEBUG setting */
304 }
305 
306 const char *
307 _umem_logging_init(void)
308 {
309 	return ("fail,contents"); /* $UMEM_LOGGING setting */
310 }
311 #endif
312