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