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