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