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*148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * smbstat: Server Message Block File System statistics 28*148c5f43SAlan Wright * 29*148c5f43SAlan Wright * The statistics this CLI displays come from two sources: 30*148c5f43SAlan Wright * 31*148c5f43SAlan Wright * 1) The kernel module 'smbsrv'. 32*148c5f43SAlan Wright * 2) The SMB workers task queue statistics the task queue manager of Solaris 33*148c5f43SAlan Wright * maintains. 34*148c5f43SAlan Wright * 35*148c5f43SAlan Wright * The flow of the code is the following: 36*148c5f43SAlan Wright * 37*148c5f43SAlan Wright * 38*148c5f43SAlan Wright * +----------------+ 39*148c5f43SAlan Wright * | Initialization | 40*148c5f43SAlan Wright * +----------------+ 41*148c5f43SAlan Wright * | 42*148c5f43SAlan Wright * | 43*148c5f43SAlan Wright * v 44*148c5f43SAlan Wright * +--------------------------* 45*148c5f43SAlan Wright * | Take a snapshot the data | <--------+ 46*148c5f43SAlan Wright * +--------------------------+ | 47*148c5f43SAlan Wright * | | 48*148c5f43SAlan Wright * | | 49*148c5f43SAlan Wright * v | 50*148c5f43SAlan Wright * +----------------------+ | 51*148c5f43SAlan Wright * | Process the snapshot | | 52*148c5f43SAlan Wright * +----------------------+ | 53*148c5f43SAlan Wright * | | 54*148c5f43SAlan Wright * | | 55*148c5f43SAlan Wright * v | 56*148c5f43SAlan Wright * +------------------------------------+ | 57*148c5f43SAlan Wright * | Print the result of the processing | | 58*148c5f43SAlan Wright * +------------------------------------+ | 59*148c5f43SAlan Wright * | | 60*148c5f43SAlan Wright * | | 61*148c5f43SAlan Wright * v | 62*148c5f43SAlan Wright * Yes --------------- | 63*148c5f43SAlan Wright * +------------ < interval == 0 ? > | 64*148c5f43SAlan Wright * | --------------- | 65*148c5f43SAlan Wright * | | | 66*148c5f43SAlan Wright * | | No | 67*148c5f43SAlan Wright * | v | 68*148c5f43SAlan Wright * | +------------------------+ | 69*148c5f43SAlan Wright * | | Sleep for the duration | ----------+ 70*148c5f43SAlan Wright * | | of the interval. | 71*148c5f43SAlan Wright * | +------------------------+ 72*148c5f43SAlan Wright * | 73*148c5f43SAlan Wright * +---------------------+ 74*148c5f43SAlan Wright * | 75*148c5f43SAlan Wright * v 76*148c5f43SAlan Wright * 77*148c5f43SAlan Wright * Exit 78*148c5f43SAlan Wright * 79*148c5f43SAlan Wright * There are two sets of snapshots. One set for the smbsrv module and the other 80*148c5f43SAlan Wright * for the task queue (SMB workers). Each set contains 2 snapshots. One is 81*148c5f43SAlan Wright * labeled 'current' the other one 'previous'. Their role changes after each 82*148c5f43SAlan Wright * snapshot. The 'current' becomes 'previous' and vice versa. 83*148c5f43SAlan Wright * The first snapshot taken is compared against the data gathered since the 84*148c5f43SAlan Wright * smbsrv module was loaded. Subsequent snapshots will be compared against the 85*148c5f43SAlan Wright * previous snapshot. 86da6c28aaSamw */ 87*148c5f43SAlan Wright 88da6c28aaSamw #include <stdio.h> 89da6c28aaSamw #include <stdlib.h> 90*148c5f43SAlan Wright #include <unistd.h> 91da6c28aaSamw #include <kstat.h> 92da6c28aaSamw #include <stdarg.h> 93da6c28aaSamw #include <errno.h> 94da6c28aaSamw #include <inttypes.h> 95da6c28aaSamw #include <strings.h> 96da6c28aaSamw #include <utility.h> 97da6c28aaSamw #include <libintl.h> 98da6c28aaSamw #include <zone.h> 99*148c5f43SAlan Wright #include <termios.h> 100*148c5f43SAlan Wright #include <stropts.h> 101*148c5f43SAlan Wright #include <math.h> 102*148c5f43SAlan Wright #include <umem.h> 103*148c5f43SAlan Wright #include <locale.h> 1046537f381Sas200622 #include <smbsrv/smb_kstat.h> 105da6c28aaSamw 106*148c5f43SAlan Wright #if !defined(TEXT_DOMAIN) 107*148c5f43SAlan Wright #define TEXT_DOMAIN "SYS_TEST" 108*148c5f43SAlan Wright #endif /* TEXT_DOMAIN */ 109da6c28aaSamw 110*148c5f43SAlan Wright #define SMBSTAT_ID_NO_CPU -1 111*148c5f43SAlan Wright #define SMBSTAT_SNAPSHOT_COUNT 2 /* Must be a power of 2 */ 112*148c5f43SAlan Wright #define SMBSTAT_SNAPSHOT_MASK (SMBSTAT_SNAPSHOT_COUNT - 1) 113*148c5f43SAlan Wright 114*148c5f43SAlan Wright #define SMBSTAT_HELP \ 115*148c5f43SAlan Wright "Usage: smbstat [-acnrtuz] [interval]\n" \ 116*148c5f43SAlan Wright " -c: display counters\n" \ 117*148c5f43SAlan Wright " -t: display throughput\n" \ 118*148c5f43SAlan Wright " -u: display utilization\n" \ 119*148c5f43SAlan Wright " -r: display requests\n" \ 120*148c5f43SAlan Wright " -a: all the requests (supported and unsupported)\n" \ 121*148c5f43SAlan Wright " -z: skip the requests not received\n" \ 122*148c5f43SAlan Wright " -n: display in alphabetic order\n" \ 123*148c5f43SAlan Wright " interval: refresh cycle in seconds\n" 124*148c5f43SAlan Wright 125*148c5f43SAlan Wright #define SMBSRV_COUNTERS_BANNER "\n nbt tcp users trees files pipes\n" 126*148c5f43SAlan Wright #define SMBSRV_COUNTERS_FORMAT "%5d %5d %5d %5d %5d %5d\n" 127*148c5f43SAlan Wright 128*148c5f43SAlan Wright #define SMBSRV_THROUGHPUT_BANNER \ 129*148c5f43SAlan Wright "\nrbytes/s tbytes/s reqs/s reads/s writes/s\n" 130*148c5f43SAlan Wright #define SMBSRV_THROUGHPUT_FORMAT \ 131*148c5f43SAlan Wright "%1.3e %1.3e %1.3e %1.3e %1.3e\n" 132*148c5f43SAlan Wright 133*148c5f43SAlan Wright #define SMBSRV_UTILIZATION_BANNER \ 134*148c5f43SAlan Wright "\n wcnt rcnt wtime rtime" \ 135*148c5f43SAlan Wright " w%% r%% u%% sat usr%% sys%% idle%%\n" 136*148c5f43SAlan Wright #define SMBSRV_UTILIZATION_FORMAT \ 137*148c5f43SAlan Wright "%1.3e %1.3e %1.3e %1.3e %3.0f %3.0f %3.0f %s " \ 138*148c5f43SAlan Wright "%3.0f %3.0f %3.0f\n" 139*148c5f43SAlan Wright 140*148c5f43SAlan Wright #define SMBSRV_REQUESTS_BANNER \ 141*148c5f43SAlan Wright "\n%30s code %% rbytes/s tbytes/s req/s rt-mean" \ 142*148c5f43SAlan Wright " rt-stddev\n" 143*148c5f43SAlan Wright #define SMBSRV_REQUESTS_FORMAT \ 144*148c5f43SAlan Wright "%30s %02X %3.0f %1.3e %1.3e %1.3e %1.3e %1.3e\n" 145*148c5f43SAlan Wright 146*148c5f43SAlan Wright typedef enum { 147*148c5f43SAlan Wright CPU_TICKS_IDLE = 0, 148*148c5f43SAlan Wright CPU_TICKS_USER, 149*148c5f43SAlan Wright CPU_TICKS_KERNEL, 150*148c5f43SAlan Wright CPU_TICKS_SENTINEL 151*148c5f43SAlan Wright } cpu_state_idx_t; 152*148c5f43SAlan Wright 153*148c5f43SAlan Wright typedef struct smbstat_cpu_snapshot { 154*148c5f43SAlan Wright processorid_t cs_id; 155*148c5f43SAlan Wright int cs_state; 156*148c5f43SAlan Wright uint64_t cs_ticks[CPU_TICKS_SENTINEL]; 157*148c5f43SAlan Wright } smbstat_cpu_snapshot_t; 158*148c5f43SAlan Wright 159*148c5f43SAlan Wright typedef struct smbstat_srv_snapshot { 160*148c5f43SAlan Wright hrtime_t ss_snaptime; 161*148c5f43SAlan Wright smbsrv_kstats_t ss_data; 162*148c5f43SAlan Wright } smbstat_srv_snapshot_t; 163*148c5f43SAlan Wright 164*148c5f43SAlan Wright typedef struct smbstat_wrk_snapshot { 165*148c5f43SAlan Wright uint64_t ws_maxthreads; 166*148c5f43SAlan Wright uint64_t ws_bnalloc; 167*148c5f43SAlan Wright } smbstat_wrk_snapshot_t; 168*148c5f43SAlan Wright 169*148c5f43SAlan Wright typedef struct smbstat_req_info { 170*148c5f43SAlan Wright char ri_name[KSTAT_STRLEN]; 171*148c5f43SAlan Wright int ri_opcode; 172*148c5f43SAlan Wright double ri_pct; 173*148c5f43SAlan Wright double ri_tbs; 174*148c5f43SAlan Wright double ri_rbs; 175*148c5f43SAlan Wright double ri_rqs; 176*148c5f43SAlan Wright double ri_stddev; 177*148c5f43SAlan Wright double ri_mean; 178*148c5f43SAlan Wright } smbstat_req_info_t; 179*148c5f43SAlan Wright 180*148c5f43SAlan Wright typedef struct smbstat_srv_info { 181*148c5f43SAlan Wright double si_hretime; 182*148c5f43SAlan Wright double si_etime; 183*148c5f43SAlan Wright double si_total_nreqs; 184*148c5f43SAlan Wright /* 185*148c5f43SAlan Wright * Counters 186*148c5f43SAlan Wright */ 187*148c5f43SAlan Wright uint32_t si_nbt_sess; /* NBT sessions */ 188*148c5f43SAlan Wright uint32_t si_tcp_sess; /* TCP sessions */ 189*148c5f43SAlan Wright uint32_t si_users; /* Users logged in */ 190*148c5f43SAlan Wright uint32_t si_trees; /* Trees connected */ 191*148c5f43SAlan Wright uint32_t si_files; /* Open files */ 192*148c5f43SAlan Wright uint32_t si_pipes; /* Open pipes */ 193*148c5f43SAlan Wright /* 194*148c5f43SAlan Wright * Throughput of the server 195*148c5f43SAlan Wright */ 196*148c5f43SAlan Wright double si_tbs; /* Bytes transmitted / second */ 197*148c5f43SAlan Wright double si_rbs; /* Bytes received / second */ 198*148c5f43SAlan Wright double si_rqs; /* Requests treated / second */ 199*148c5f43SAlan Wright double si_rds; /* Reads treated / second */ 200*148c5f43SAlan Wright double si_wrs; /* Writes treated / second */ 201*148c5f43SAlan Wright /* 202*148c5f43SAlan Wright * Utilization of the server 203*148c5f43SAlan Wright */ 204*148c5f43SAlan Wright double si_wpct; /* */ 205*148c5f43SAlan Wright double si_rpct; /* */ 206*148c5f43SAlan Wright double si_upct; /* Utilization in % */ 207*148c5f43SAlan Wright double si_avw; /* Average number of requests waiting */ 208*148c5f43SAlan Wright double si_avr; /* Average number of requests running */ 209*148c5f43SAlan Wright double si_wserv; /* Average waiting time */ 210*148c5f43SAlan Wright double si_rserv; /* Average running time */ 211*148c5f43SAlan Wright boolean_t si_sat; 212*148c5f43SAlan Wright double si_ticks[CPU_TICKS_SENTINEL]; 213*148c5f43SAlan Wright /* 214*148c5f43SAlan Wright * Latency & Throughput per request 215*148c5f43SAlan Wright */ 216*148c5f43SAlan Wright smbstat_req_info_t si_reqs[SMB_COM_NUM]; 217*148c5f43SAlan Wright } smbstat_srv_info_t; 218*148c5f43SAlan Wright 2196537f381Sas200622 static void smbstat_init(void); 2206537f381Sas200622 static void smbstat_fini(void); 221*148c5f43SAlan Wright static void smbstat_kstat_snapshot(void); 222*148c5f43SAlan Wright static void smbstat_kstat_process(void); 223*148c5f43SAlan Wright static void smbstat_kstat_print(void); 224*148c5f43SAlan Wright 225*148c5f43SAlan Wright static void smbstat_print_counters(void); 226*148c5f43SAlan Wright static void smbstat_print_throughput(void); 227*148c5f43SAlan Wright static void smbstat_print_utilization(void); 228*148c5f43SAlan Wright static void smbstat_print_requests(void); 229*148c5f43SAlan Wright 230*148c5f43SAlan Wright static void smbstat_cpu_init(void); 231*148c5f43SAlan Wright static void smbstat_cpu_fini(void); 232*148c5f43SAlan Wright static smbstat_cpu_snapshot_t *smbstat_cpu_current_snapshot(void); 233*148c5f43SAlan Wright static smbstat_cpu_snapshot_t *smbstat_cpu_previous_snapshot(void); 234*148c5f43SAlan Wright static void smbstat_cpu_snapshot(void); 235*148c5f43SAlan Wright static void smbstat_cpu_process(void); 236*148c5f43SAlan Wright 237*148c5f43SAlan Wright static void smbstat_wrk_init(void); 238*148c5f43SAlan Wright static void smbstat_wrk_fini(void); 239*148c5f43SAlan Wright static void smbstat_wrk_snapshot(void); 240*148c5f43SAlan Wright static void smbstat_wrk_process(void); 241*148c5f43SAlan Wright static smbstat_wrk_snapshot_t *smbstat_wrk_current_snapshot(void); 242*148c5f43SAlan Wright 243*148c5f43SAlan Wright static void smbstat_srv_init(void); 244*148c5f43SAlan Wright static void smbstat_srv_fini(void); 245*148c5f43SAlan Wright static void smbstat_srv_snapshot(void); 246*148c5f43SAlan Wright static void smbstat_srv_process(void); 247*148c5f43SAlan Wright static void smbstat_srv_process_counters(smbstat_srv_snapshot_t *); 248*148c5f43SAlan Wright static void smbstat_srv_process_throughput(smbstat_srv_snapshot_t *, 249*148c5f43SAlan Wright smbstat_srv_snapshot_t *); 250*148c5f43SAlan Wright static void smbstat_srv_process_utilization(smbstat_srv_snapshot_t *, 251*148c5f43SAlan Wright smbstat_srv_snapshot_t *); 252*148c5f43SAlan Wright static void smbstat_srv_process_requests(smbstat_srv_snapshot_t *, 253*148c5f43SAlan Wright smbstat_srv_snapshot_t *); 254*148c5f43SAlan Wright static smbstat_srv_snapshot_t *smbstat_srv_current_snapshot(void); 255*148c5f43SAlan Wright static smbstat_srv_snapshot_t *smbstat_srv_previous_snapshot(void); 256*148c5f43SAlan Wright 257*148c5f43SAlan Wright static void *smbstat_zalloc(size_t); 258*148c5f43SAlan Wright static void smbstat_free(void *, size_t); 259da6c28aaSamw static void smbstat_fail(int, char *, ...); 260*148c5f43SAlan Wright static void smbstat_snapshot_inc_idx(void); 261*148c5f43SAlan Wright static void smbstat_usage(FILE *, int); 262*148c5f43SAlan Wright static uint_t smbstat_strtoi(char const *, char *); 263*148c5f43SAlan Wright static double smbstat_hrtime_delta(hrtime_t, hrtime_t); 264*148c5f43SAlan Wright static double smbstat_sub_64(uint64_t, uint64_t); 265*148c5f43SAlan Wright static void smbstat_req_order(void); 266*148c5f43SAlan Wright static double smbstat_zero(double); 267*148c5f43SAlan Wright static void smbstat_termio_init(void); 268da6c28aaSamw 269*148c5f43SAlan Wright #pragma does_not_return(smbstat_fail, smbstat_usage) 270da6c28aaSamw 271*148c5f43SAlan Wright static char *smbstat_cpu_states[CPU_TICKS_SENTINEL] = { 272*148c5f43SAlan Wright "cpu_ticks_idle", 273*148c5f43SAlan Wright "cpu_ticks_user", 274*148c5f43SAlan Wright "cpu_ticks_kernel" 275*148c5f43SAlan Wright }; 276*148c5f43SAlan Wright 277*148c5f43SAlan Wright static boolean_t smbstat_opt_a = B_FALSE; /* all */ 278*148c5f43SAlan Wright static boolean_t smbstat_opt_c = B_FALSE; /* counters */ 279*148c5f43SAlan Wright static boolean_t smbstat_opt_n = B_FALSE; /* by name */ 280*148c5f43SAlan Wright static boolean_t smbstat_opt_u = B_FALSE; /* utilization */ 281*148c5f43SAlan Wright static boolean_t smbstat_opt_t = B_FALSE; /* throughput */ 282*148c5f43SAlan Wright static boolean_t smbstat_opt_r = B_FALSE; /* requests */ 283*148c5f43SAlan Wright static boolean_t smbstat_opt_z = B_FALSE; /* non-zero requests */ 284*148c5f43SAlan Wright 285*148c5f43SAlan Wright static uint_t smbstat_interval = 0; 286*148c5f43SAlan Wright static long smbstat_nrcpus = 0; 287*148c5f43SAlan Wright static kstat_ctl_t *smbstat_ksc = NULL; 288*148c5f43SAlan Wright static kstat_t *smbstat_srv_ksp = NULL; 289*148c5f43SAlan Wright static kstat_t *smbstat_wrk_ksp = NULL; 290*148c5f43SAlan Wright static struct winsize smbstat_ws; 291*148c5f43SAlan Wright static uint16_t smbstat_rows = 0; 292*148c5f43SAlan Wright 293*148c5f43SAlan Wright static int smbstat_snapshot_idx = 0; 294*148c5f43SAlan Wright static smbstat_cpu_snapshot_t *smbstat_cpu_snapshots[SMBSTAT_SNAPSHOT_COUNT]; 295*148c5f43SAlan Wright static smbstat_srv_snapshot_t smbstat_srv_snapshots[SMBSTAT_SNAPSHOT_COUNT]; 296*148c5f43SAlan Wright static smbstat_wrk_snapshot_t smbstat_wrk_snapshots[SMBSTAT_SNAPSHOT_COUNT]; 297*148c5f43SAlan Wright static smbstat_srv_info_t smbstat_srv_info; 298*148c5f43SAlan Wright 299*148c5f43SAlan Wright /* 300*148c5f43SAlan Wright * main 301*148c5f43SAlan Wright */ 302da6c28aaSamw int 303da6c28aaSamw main(int argc, char *argv[]) 304da6c28aaSamw { 305da6c28aaSamw int c; 306*148c5f43SAlan Wright 307*148c5f43SAlan Wright (void) setlocale(LC_ALL, ""); 308*148c5f43SAlan Wright (void) textdomain(TEXT_DOMAIN); 309da6c28aaSamw 310da6c28aaSamw if (getzoneid() != GLOBAL_ZONEID) { 311da6c28aaSamw (void) fprintf(stderr, 312da6c28aaSamw gettext("%s: Cannot execute in non-global zone.\n"), 313da6c28aaSamw argv[0]); 314da6c28aaSamw return (0); 315da6c28aaSamw } 316da6c28aaSamw 317da6c28aaSamw if (is_system_labeled()) { 318da6c28aaSamw (void) fprintf(stderr, 319da6c28aaSamw gettext("%s: Trusted Extensions not supported.\n"), 320da6c28aaSamw argv[0]); 321da6c28aaSamw return (0); 322da6c28aaSamw } 323da6c28aaSamw 324*148c5f43SAlan Wright while ((c = getopt(argc, argv, "achnrtuz")) != EOF) { 325da6c28aaSamw switch (c) { 326*148c5f43SAlan Wright case 'a': 327*148c5f43SAlan Wright smbstat_opt_a = B_TRUE; 328da6c28aaSamw break; 329*148c5f43SAlan Wright case 'n': 330*148c5f43SAlan Wright smbstat_opt_n = B_TRUE; 331da6c28aaSamw break; 332*148c5f43SAlan Wright case 'u': 333*148c5f43SAlan Wright smbstat_opt_u = B_TRUE; 334*148c5f43SAlan Wright break; 335*148c5f43SAlan Wright case 'c': 336*148c5f43SAlan Wright smbstat_opt_c = B_TRUE; 337*148c5f43SAlan Wright break; 338*148c5f43SAlan Wright case 'r': 339*148c5f43SAlan Wright smbstat_opt_r = B_TRUE; 340*148c5f43SAlan Wright break; 341*148c5f43SAlan Wright case 't': 342*148c5f43SAlan Wright smbstat_opt_t = B_TRUE; 343*148c5f43SAlan Wright break; 344*148c5f43SAlan Wright case 'z': 345*148c5f43SAlan Wright smbstat_opt_z = B_TRUE; 346*148c5f43SAlan Wright break; 347*148c5f43SAlan Wright case 'h': 348*148c5f43SAlan Wright smbstat_usage(stdout, 0); 349da6c28aaSamw default: 350*148c5f43SAlan Wright smbstat_usage(stderr, 1); 351da6c28aaSamw } 352da6c28aaSamw } 353da6c28aaSamw 354*148c5f43SAlan Wright if (!smbstat_opt_u && 355*148c5f43SAlan Wright !smbstat_opt_c && 356*148c5f43SAlan Wright !smbstat_opt_r && 357*148c5f43SAlan Wright !smbstat_opt_t) { 358*148c5f43SAlan Wright /* Default options when none is specified. */ 359*148c5f43SAlan Wright smbstat_opt_u = B_TRUE; 360*148c5f43SAlan Wright smbstat_opt_t = B_TRUE; 361da6c28aaSamw } 362da6c28aaSamw 363*148c5f43SAlan Wright if (optind < argc) { 364*148c5f43SAlan Wright smbstat_interval = 365*148c5f43SAlan Wright smbstat_strtoi(argv[optind], "invalid count"); 366*148c5f43SAlan Wright optind++; 367*148c5f43SAlan Wright } 368*148c5f43SAlan Wright 369*148c5f43SAlan Wright if ((argc - optind) > 1) 370*148c5f43SAlan Wright smbstat_usage(stderr, 1); 371*148c5f43SAlan Wright 372*148c5f43SAlan Wright (void) atexit(smbstat_fini); 3736537f381Sas200622 smbstat_init(); 374*148c5f43SAlan Wright for (;;) { 375*148c5f43SAlan Wright smbstat_kstat_snapshot(); 376*148c5f43SAlan Wright smbstat_kstat_process(); 377*148c5f43SAlan Wright smbstat_kstat_print(); 378*148c5f43SAlan Wright if (smbstat_interval == 0) 379*148c5f43SAlan Wright break; 380*148c5f43SAlan Wright (void) sleep(smbstat_interval); 381*148c5f43SAlan Wright smbstat_snapshot_inc_idx(); 382da6c28aaSamw } 383da6c28aaSamw return (0); 384da6c28aaSamw } 385da6c28aaSamw 386*148c5f43SAlan Wright /* 387*148c5f43SAlan Wright * smbstat_init 388*148c5f43SAlan Wright * 389*148c5f43SAlan Wright * Global initialization. 390*148c5f43SAlan Wright */ 391da6c28aaSamw static void 3926537f381Sas200622 smbstat_init(void) 393da6c28aaSamw { 394*148c5f43SAlan Wright if ((smbstat_ksc = kstat_open()) == NULL) 395da6c28aaSamw smbstat_fail(1, gettext("kstat_open(): can't open /dev/kstat")); 396da6c28aaSamw 397*148c5f43SAlan Wright smbstat_cpu_init(); 398*148c5f43SAlan Wright smbstat_srv_init(); 399*148c5f43SAlan Wright smbstat_wrk_init(); 400*148c5f43SAlan Wright smbstat_req_order(); 401da6c28aaSamw } 402da6c28aaSamw 403*148c5f43SAlan Wright /* 404*148c5f43SAlan Wright * smbstat_fini 405*148c5f43SAlan Wright * 406*148c5f43SAlan Wright * Releases the resources smbstat_init() allocated. 407*148c5f43SAlan Wright */ 4086537f381Sas200622 static void 4096537f381Sas200622 smbstat_fini(void) 4106537f381Sas200622 { 411*148c5f43SAlan Wright smbstat_wrk_fini(); 412*148c5f43SAlan Wright smbstat_srv_fini(); 413*148c5f43SAlan Wright smbstat_cpu_fini(); 414*148c5f43SAlan Wright (void) kstat_close(smbstat_ksc); 4156537f381Sas200622 } 4166537f381Sas200622 417*148c5f43SAlan Wright /* 418*148c5f43SAlan Wright * smbstat_kstat_snapshot 419*148c5f43SAlan Wright * 420*148c5f43SAlan Wright * Takes a snapshot of the data. 421*148c5f43SAlan Wright */ 422*148c5f43SAlan Wright static void 423*148c5f43SAlan Wright smbstat_kstat_snapshot(void) 424da6c28aaSamw { 425*148c5f43SAlan Wright smbstat_cpu_snapshot(); 426*148c5f43SAlan Wright smbstat_srv_snapshot(); 427*148c5f43SAlan Wright smbstat_wrk_snapshot(); 428da6c28aaSamw } 429*148c5f43SAlan Wright 430*148c5f43SAlan Wright /* 431*148c5f43SAlan Wright * smbstat_kstat_process 432*148c5f43SAlan Wright */ 433*148c5f43SAlan Wright static void 434*148c5f43SAlan Wright smbstat_kstat_process(void) 435*148c5f43SAlan Wright { 436*148c5f43SAlan Wright smbstat_cpu_process(); 437*148c5f43SAlan Wright smbstat_srv_process(); 438*148c5f43SAlan Wright smbstat_wrk_process(); 439*148c5f43SAlan Wright } 440*148c5f43SAlan Wright 441*148c5f43SAlan Wright /* 442*148c5f43SAlan Wright * smbstat_kstat_print 443*148c5f43SAlan Wright * 444*148c5f43SAlan Wright * Print the data processed. 445*148c5f43SAlan Wright */ 446*148c5f43SAlan Wright static void 447*148c5f43SAlan Wright smbstat_kstat_print(void) 448*148c5f43SAlan Wright { 449*148c5f43SAlan Wright smbstat_termio_init(); 450*148c5f43SAlan Wright smbstat_print_counters(); 451*148c5f43SAlan Wright smbstat_print_throughput(); 452*148c5f43SAlan Wright smbstat_print_utilization(); 453*148c5f43SAlan Wright smbstat_print_requests(); 454*148c5f43SAlan Wright } 455*148c5f43SAlan Wright 456*148c5f43SAlan Wright /* 457*148c5f43SAlan Wright * smbstat_print_counters 458*148c5f43SAlan Wright * 459*148c5f43SAlan Wright * Displays the SMB server counters (session, users...). 460*148c5f43SAlan Wright */ 461*148c5f43SAlan Wright static void 462*148c5f43SAlan Wright smbstat_print_counters(void) 463*148c5f43SAlan Wright { 464*148c5f43SAlan Wright if (!smbstat_opt_c) 465*148c5f43SAlan Wright return; 466*148c5f43SAlan Wright 467*148c5f43SAlan Wright if (smbstat_opt_u || smbstat_opt_r || smbstat_opt_t || 468*148c5f43SAlan Wright (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) { 469*148c5f43SAlan Wright (void) printf(SMBSRV_COUNTERS_BANNER); 470*148c5f43SAlan Wright smbstat_rows = 1; 471*148c5f43SAlan Wright } 472*148c5f43SAlan Wright 473*148c5f43SAlan Wright (void) printf(SMBSRV_COUNTERS_FORMAT, 474*148c5f43SAlan Wright smbstat_srv_info.si_nbt_sess, 475*148c5f43SAlan Wright smbstat_srv_info.si_tcp_sess, 476*148c5f43SAlan Wright smbstat_srv_info.si_users, 477*148c5f43SAlan Wright smbstat_srv_info.si_trees, 478*148c5f43SAlan Wright smbstat_srv_info.si_files, 479*148c5f43SAlan Wright smbstat_srv_info.si_pipes); 480*148c5f43SAlan Wright 481*148c5f43SAlan Wright ++smbstat_rows; 482*148c5f43SAlan Wright } 483*148c5f43SAlan Wright /* 484*148c5f43SAlan Wright * smbstat_print_throughput 485*148c5f43SAlan Wright * 486*148c5f43SAlan Wright * Formats the SMB server throughput output. 487*148c5f43SAlan Wright */ 488*148c5f43SAlan Wright static void 489*148c5f43SAlan Wright smbstat_print_throughput(void) 490*148c5f43SAlan Wright { 491*148c5f43SAlan Wright if (!smbstat_opt_t) 492*148c5f43SAlan Wright return; 493*148c5f43SAlan Wright 494*148c5f43SAlan Wright if (smbstat_opt_u || smbstat_opt_r || smbstat_opt_c || 495*148c5f43SAlan Wright (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) { 496*148c5f43SAlan Wright (void) printf(SMBSRV_THROUGHPUT_BANNER); 497*148c5f43SAlan Wright smbstat_rows = 1; 498*148c5f43SAlan Wright } 499*148c5f43SAlan Wright (void) printf(SMBSRV_THROUGHPUT_FORMAT, 500*148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rbs), 501*148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_tbs), 502*148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rqs), 503*148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rds), 504*148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_wrs)); 505*148c5f43SAlan Wright 506*148c5f43SAlan Wright ++smbstat_rows; 507*148c5f43SAlan Wright } 508*148c5f43SAlan Wright 509*148c5f43SAlan Wright /* 510*148c5f43SAlan Wright * smbstat_print_utilization 511*148c5f43SAlan Wright */ 512*148c5f43SAlan Wright static void 513*148c5f43SAlan Wright smbstat_print_utilization(void) 514*148c5f43SAlan Wright { 515*148c5f43SAlan Wright char *sat; 516*148c5f43SAlan Wright if (!smbstat_opt_u) 517*148c5f43SAlan Wright return; 518*148c5f43SAlan Wright 519*148c5f43SAlan Wright if (smbstat_opt_t || smbstat_opt_r || smbstat_opt_c || 520*148c5f43SAlan Wright (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) { 521*148c5f43SAlan Wright (void) printf(SMBSRV_UTILIZATION_BANNER); 522*148c5f43SAlan Wright smbstat_rows = 1; 523*148c5f43SAlan Wright } 524*148c5f43SAlan Wright 525*148c5f43SAlan Wright if (smbstat_srv_info.si_sat) 526*148c5f43SAlan Wright sat = "yes"; 527*148c5f43SAlan Wright else 528*148c5f43SAlan Wright sat = "no "; 529*148c5f43SAlan Wright 530*148c5f43SAlan Wright (void) printf(SMBSRV_UTILIZATION_FORMAT, 531*148c5f43SAlan Wright smbstat_srv_info.si_avw, 532*148c5f43SAlan Wright smbstat_srv_info.si_avr, 533*148c5f43SAlan Wright smbstat_srv_info.si_wserv, 534*148c5f43SAlan Wright smbstat_srv_info.si_rserv, 535*148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_wpct), 536*148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rpct), 537*148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_upct), 538*148c5f43SAlan Wright sat, 539*148c5f43SAlan Wright smbstat_srv_info.si_ticks[CPU_TICKS_USER], 540*148c5f43SAlan Wright smbstat_srv_info.si_ticks[CPU_TICKS_KERNEL], 541*148c5f43SAlan Wright smbstat_srv_info.si_ticks[CPU_TICKS_IDLE]); 542*148c5f43SAlan Wright 543*148c5f43SAlan Wright ++smbstat_rows; 544*148c5f43SAlan Wright } 545*148c5f43SAlan Wright 546*148c5f43SAlan Wright /* 547*148c5f43SAlan Wright * smbstat_print_requests 548*148c5f43SAlan Wright */ 549*148c5f43SAlan Wright static void 550*148c5f43SAlan Wright smbstat_print_requests(void) 551*148c5f43SAlan Wright { 552*148c5f43SAlan Wright smbstat_req_info_t *prq; 553*148c5f43SAlan Wright int i; 554*148c5f43SAlan Wright 555*148c5f43SAlan Wright if (!smbstat_opt_r) 556*148c5f43SAlan Wright return; 557*148c5f43SAlan Wright 558*148c5f43SAlan Wright prq = smbstat_srv_info.si_reqs; 559*148c5f43SAlan Wright 560*148c5f43SAlan Wright (void) printf(SMBSRV_REQUESTS_BANNER, " "); 561*148c5f43SAlan Wright 562*148c5f43SAlan Wright for (i = 0; i < SMB_COM_NUM; i++) { 563*148c5f43SAlan Wright if (!smbstat_opt_a && 564*148c5f43SAlan Wright strncmp(prq[i].ri_name, "Invalid", sizeof ("Invalid")) == 0) 565*148c5f43SAlan Wright continue; 566*148c5f43SAlan Wright 567*148c5f43SAlan Wright if (!smbstat_opt_z || (prq[i].ri_pct != 0)) { 568*148c5f43SAlan Wright (void) printf(SMBSRV_REQUESTS_FORMAT, 569*148c5f43SAlan Wright prq[i].ri_name, 570*148c5f43SAlan Wright prq[i].ri_opcode, 571*148c5f43SAlan Wright smbstat_zero(prq[i].ri_pct), 572*148c5f43SAlan Wright smbstat_zero(prq[i].ri_rbs), 573*148c5f43SAlan Wright smbstat_zero(prq[i].ri_tbs), 574*148c5f43SAlan Wright smbstat_zero(prq[i].ri_rqs), 575*148c5f43SAlan Wright prq[i].ri_mean, 576*148c5f43SAlan Wright prq[i].ri_stddev); 577*148c5f43SAlan Wright } 578*148c5f43SAlan Wright } 579*148c5f43SAlan Wright } 580*148c5f43SAlan Wright 581*148c5f43SAlan Wright /* 582*148c5f43SAlan Wright * smbstat_cpu_init 583*148c5f43SAlan Wright */ 584*148c5f43SAlan Wright static void 585*148c5f43SAlan Wright smbstat_cpu_init(void) 586*148c5f43SAlan Wright { 587*148c5f43SAlan Wright size_t size; 588*148c5f43SAlan Wright int i; 589*148c5f43SAlan Wright 590*148c5f43SAlan Wright smbstat_nrcpus = sysconf(_SC_CPUID_MAX) + 1; 591*148c5f43SAlan Wright size = smbstat_nrcpus * sizeof (smbstat_cpu_snapshot_t); 592*148c5f43SAlan Wright 593*148c5f43SAlan Wright for (i = 0; i < SMBSTAT_SNAPSHOT_COUNT; i++) 594*148c5f43SAlan Wright smbstat_cpu_snapshots[i] = smbstat_zalloc(size); 595*148c5f43SAlan Wright } 596*148c5f43SAlan Wright 597*148c5f43SAlan Wright /* 598*148c5f43SAlan Wright * smbstat_cpu_fini 599*148c5f43SAlan Wright */ 600*148c5f43SAlan Wright static void 601*148c5f43SAlan Wright smbstat_cpu_fini(void) 602*148c5f43SAlan Wright { 603*148c5f43SAlan Wright size_t size; 604*148c5f43SAlan Wright int i; 605*148c5f43SAlan Wright 606*148c5f43SAlan Wright size = smbstat_nrcpus * sizeof (smbstat_cpu_snapshot_t); 607*148c5f43SAlan Wright 608*148c5f43SAlan Wright for (i = 0; i < SMBSTAT_SNAPSHOT_COUNT; i++) 609*148c5f43SAlan Wright smbstat_free(smbstat_cpu_snapshots[i], size); 610*148c5f43SAlan Wright } 611*148c5f43SAlan Wright 612*148c5f43SAlan Wright /* 613*148c5f43SAlan Wright * smbstat_cpu_current_snapshot 614*148c5f43SAlan Wright */ 615*148c5f43SAlan Wright static smbstat_cpu_snapshot_t * 616*148c5f43SAlan Wright smbstat_cpu_current_snapshot(void) 617*148c5f43SAlan Wright { 618*148c5f43SAlan Wright return (smbstat_cpu_snapshots[smbstat_snapshot_idx]); 619*148c5f43SAlan Wright } 620*148c5f43SAlan Wright 621*148c5f43SAlan Wright /* 622*148c5f43SAlan Wright * smbstat_cpu_previous_snapshot 623*148c5f43SAlan Wright */ 624*148c5f43SAlan Wright static smbstat_cpu_snapshot_t * 625*148c5f43SAlan Wright smbstat_cpu_previous_snapshot(void) 626*148c5f43SAlan Wright { 627*148c5f43SAlan Wright int idx; 628*148c5f43SAlan Wright 629*148c5f43SAlan Wright idx = (smbstat_snapshot_idx - 1) & SMBSTAT_SNAPSHOT_MASK; 630*148c5f43SAlan Wright return (smbstat_cpu_snapshots[idx]); 631*148c5f43SAlan Wright } 632*148c5f43SAlan Wright 633*148c5f43SAlan Wright /* 634*148c5f43SAlan Wright * smbstat_cpu_snapshot 635*148c5f43SAlan Wright */ 636*148c5f43SAlan Wright static void 637*148c5f43SAlan Wright smbstat_cpu_snapshot(void) 638*148c5f43SAlan Wright { 639*148c5f43SAlan Wright kstat_t *ksp; 640*148c5f43SAlan Wright kstat_named_t *ksn; 641*148c5f43SAlan Wright smbstat_cpu_snapshot_t *curr; 642*148c5f43SAlan Wright long i; 643*148c5f43SAlan Wright int j; 644*148c5f43SAlan Wright 645*148c5f43SAlan Wright curr = smbstat_cpu_current_snapshot(); 646*148c5f43SAlan Wright 647*148c5f43SAlan Wright for (i = 0; i < smbstat_nrcpus; i++, curr++) { 648*148c5f43SAlan Wright curr->cs_id = SMBSTAT_ID_NO_CPU; 649*148c5f43SAlan Wright curr->cs_state = p_online(i, P_STATUS); 650*148c5f43SAlan Wright /* If no valid CPU is present, move on to the next one */ 651*148c5f43SAlan Wright if (curr->cs_state == -1) 652*148c5f43SAlan Wright continue; 653*148c5f43SAlan Wright 654*148c5f43SAlan Wright curr->cs_id = i; 655*148c5f43SAlan Wright 656*148c5f43SAlan Wright ksp = kstat_lookup(smbstat_ksc, "cpu", i, "sys"); 657*148c5f43SAlan Wright if (ksp == NULL) 658*148c5f43SAlan Wright smbstat_fail(1, 659*148c5f43SAlan Wright gettext("kstat_lookup('cpu sys %d') failed"), i); 660*148c5f43SAlan Wright 661*148c5f43SAlan Wright if (kstat_read(smbstat_ksc, ksp, NULL) == -1) 662*148c5f43SAlan Wright smbstat_fail(1, 663*148c5f43SAlan Wright gettext("kstat_read('cpu sys %d') failed"), i); 664*148c5f43SAlan Wright 665*148c5f43SAlan Wright for (j = 0; j < CPU_TICKS_SENTINEL; j++) { 666*148c5f43SAlan Wright ksn = kstat_data_lookup(ksp, smbstat_cpu_states[j]); 667*148c5f43SAlan Wright if (ksn == NULL) 668*148c5f43SAlan Wright smbstat_fail(1, 669*148c5f43SAlan Wright gettext("kstat_data_lookup('%s') failed"), 670*148c5f43SAlan Wright smbstat_cpu_states[j]); 671*148c5f43SAlan Wright curr->cs_ticks[j] = ksn->value.ui64; 672*148c5f43SAlan Wright } 673*148c5f43SAlan Wright } 674*148c5f43SAlan Wright } 675*148c5f43SAlan Wright 676*148c5f43SAlan Wright /* 677*148c5f43SAlan Wright * smbstat_cpu_process 678*148c5f43SAlan Wright */ 679*148c5f43SAlan Wright static void 680*148c5f43SAlan Wright smbstat_cpu_process(void) 681*148c5f43SAlan Wright { 682*148c5f43SAlan Wright smbstat_cpu_snapshot_t *curr, *prev; 683*148c5f43SAlan Wright double total_ticks; 684*148c5f43SAlan Wright double agg_ticks[CPU_TICKS_SENTINEL]; 685*148c5f43SAlan Wright int i, j; 686*148c5f43SAlan Wright 687*148c5f43SAlan Wright curr = smbstat_cpu_current_snapshot(); 688*148c5f43SAlan Wright prev = smbstat_cpu_previous_snapshot(); 689*148c5f43SAlan Wright bzero(agg_ticks, sizeof (agg_ticks)); 690*148c5f43SAlan Wright total_ticks = 0; 691*148c5f43SAlan Wright 692*148c5f43SAlan Wright for (i = 0; i < smbstat_nrcpus; i++, curr++, prev++) { 693*148c5f43SAlan Wright for (j = 0; j < CPU_TICKS_SENTINEL; j++) { 694*148c5f43SAlan Wright agg_ticks[j] += smbstat_sub_64(curr->cs_ticks[j], 695*148c5f43SAlan Wright prev->cs_ticks[j]); 696*148c5f43SAlan Wright total_ticks += smbstat_sub_64(curr->cs_ticks[j], 697*148c5f43SAlan Wright prev->cs_ticks[j]); 698*148c5f43SAlan Wright } 699*148c5f43SAlan Wright } 700*148c5f43SAlan Wright 701*148c5f43SAlan Wright for (j = 0; j < CPU_TICKS_SENTINEL; j++) 702*148c5f43SAlan Wright smbstat_srv_info.si_ticks[j] = 703*148c5f43SAlan Wright (agg_ticks[j] * 100.0) / total_ticks; 704*148c5f43SAlan Wright } 705*148c5f43SAlan Wright 706*148c5f43SAlan Wright /* 707*148c5f43SAlan Wright * smbstat_wrk_init 708*148c5f43SAlan Wright */ 709*148c5f43SAlan Wright static void 710*148c5f43SAlan Wright smbstat_wrk_init(void) 711*148c5f43SAlan Wright { 712*148c5f43SAlan Wright smbstat_wrk_ksp = 713*148c5f43SAlan Wright kstat_lookup(smbstat_ksc, "unix", -1, SMBSRV_KSTAT_WORKERS); 714*148c5f43SAlan Wright if (smbstat_wrk_ksp == NULL) 715*148c5f43SAlan Wright smbstat_fail(1, 716*148c5f43SAlan Wright gettext("cannot retrieve smbsrv workers kstat\n")); 717da6c28aaSamw } 718da6c28aaSamw 719da6c28aaSamw static void 720*148c5f43SAlan Wright smbstat_wrk_fini(void) 721da6c28aaSamw { 722*148c5f43SAlan Wright smbstat_wrk_ksp = NULL; 723da6c28aaSamw } 724da6c28aaSamw 725*148c5f43SAlan Wright /* 726*148c5f43SAlan Wright * smbstat_wrk_snapshot 727*148c5f43SAlan Wright */ 728da6c28aaSamw static void 729*148c5f43SAlan Wright smbstat_wrk_snapshot(void) 730da6c28aaSamw { 731*148c5f43SAlan Wright smbstat_wrk_snapshot_t *curr; 732*148c5f43SAlan Wright kstat_named_t *kn; 733*148c5f43SAlan Wright 734*148c5f43SAlan Wright curr = smbstat_wrk_current_snapshot(); 735*148c5f43SAlan Wright 736*148c5f43SAlan Wright if (kstat_read(smbstat_ksc, smbstat_wrk_ksp, NULL) == -1) 737*148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"), 738*148c5f43SAlan Wright smbstat_wrk_ksp->ks_name); 739*148c5f43SAlan Wright 740*148c5f43SAlan Wright kn = kstat_data_lookup(smbstat_wrk_ksp, "maxthreads"); 741*148c5f43SAlan Wright if ((kn == NULL) || (kn->data_type != KSTAT_DATA_UINT64)) 742*148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"), 743*148c5f43SAlan Wright "maxthreads"); 744*148c5f43SAlan Wright curr->ws_maxthreads = kn->value.ui64; 745*148c5f43SAlan Wright 746*148c5f43SAlan Wright kn = kstat_data_lookup(smbstat_wrk_ksp, "bnalloc"); 747*148c5f43SAlan Wright if ((kn == NULL) || (kn->data_type != KSTAT_DATA_UINT64)) 748*148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"), 749*148c5f43SAlan Wright "bnalloc"); 750*148c5f43SAlan Wright curr->ws_bnalloc = kn->value.ui64; 751da6c28aaSamw } 752da6c28aaSamw 753*148c5f43SAlan Wright /* 754*148c5f43SAlan Wright * smbstat_wrk_process 755*148c5f43SAlan Wright */ 756*148c5f43SAlan Wright static void 757*148c5f43SAlan Wright smbstat_wrk_process(void) 758*148c5f43SAlan Wright { 759*148c5f43SAlan Wright smbstat_wrk_snapshot_t *curr; 760*148c5f43SAlan Wright 761*148c5f43SAlan Wright curr = smbstat_wrk_current_snapshot(); 762*148c5f43SAlan Wright 763*148c5f43SAlan Wright if (curr->ws_maxthreads >= curr->ws_bnalloc) 764*148c5f43SAlan Wright smbstat_srv_info.si_sat = B_TRUE; 765*148c5f43SAlan Wright else 766*148c5f43SAlan Wright smbstat_srv_info.si_sat = B_FALSE; 767*148c5f43SAlan Wright } 768*148c5f43SAlan Wright 769*148c5f43SAlan Wright /* 770*148c5f43SAlan Wright * smbstat_wrk_current_snapshot 771*148c5f43SAlan Wright */ 772*148c5f43SAlan Wright static smbstat_wrk_snapshot_t * 773*148c5f43SAlan Wright smbstat_wrk_current_snapshot(void) 774*148c5f43SAlan Wright { 775*148c5f43SAlan Wright return (&smbstat_wrk_snapshots[smbstat_snapshot_idx]); 776*148c5f43SAlan Wright } 777*148c5f43SAlan Wright 778*148c5f43SAlan Wright /* 779*148c5f43SAlan Wright * smbstat_srv_init 780*148c5f43SAlan Wright */ 781*148c5f43SAlan Wright static void 782*148c5f43SAlan Wright smbstat_srv_init(void) 783*148c5f43SAlan Wright { 784*148c5f43SAlan Wright smbstat_srv_ksp = kstat_lookup(smbstat_ksc, SMBSRV_KSTAT_MODULE, 785*148c5f43SAlan Wright getzoneid(), SMBSRV_KSTAT_STATISTICS); 786*148c5f43SAlan Wright if (smbstat_srv_ksp == NULL) 787*148c5f43SAlan Wright smbstat_fail(1, gettext("cannot retrieve smbsrv kstat\n")); 788*148c5f43SAlan Wright } 789*148c5f43SAlan Wright 790*148c5f43SAlan Wright /* 791*148c5f43SAlan Wright * smbstat_srv_fini 792*148c5f43SAlan Wright */ 793*148c5f43SAlan Wright static void 794*148c5f43SAlan Wright smbstat_srv_fini(void) 795*148c5f43SAlan Wright { 796*148c5f43SAlan Wright smbstat_srv_ksp = NULL; 797*148c5f43SAlan Wright } 798*148c5f43SAlan Wright 799*148c5f43SAlan Wright /* 800*148c5f43SAlan Wright * smbstat_srv_snapshot 801*148c5f43SAlan Wright * 802*148c5f43SAlan Wright * Take a snapshot of the smbsrv module statistics. 803*148c5f43SAlan Wright */ 804*148c5f43SAlan Wright static void 805*148c5f43SAlan Wright smbstat_srv_snapshot(void) 806*148c5f43SAlan Wright { 807*148c5f43SAlan Wright smbstat_srv_snapshot_t *curr; 808*148c5f43SAlan Wright 809*148c5f43SAlan Wright curr = smbstat_srv_current_snapshot(); 810*148c5f43SAlan Wright 811*148c5f43SAlan Wright if ((kstat_read(smbstat_ksc, smbstat_srv_ksp, NULL) == -1) || 812*148c5f43SAlan Wright (smbstat_srv_ksp->ks_data_size != sizeof (curr->ss_data))) 813*148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"), 814*148c5f43SAlan Wright smbstat_srv_ksp->ks_name); 815*148c5f43SAlan Wright 816*148c5f43SAlan Wright curr->ss_snaptime = smbstat_srv_ksp->ks_snaptime; 817*148c5f43SAlan Wright bcopy(smbstat_srv_ksp->ks_data, &curr->ss_data, sizeof (curr->ss_data)); 818*148c5f43SAlan Wright } 819*148c5f43SAlan Wright 820*148c5f43SAlan Wright /* 821*148c5f43SAlan Wright * smbstat_srv_process 822*148c5f43SAlan Wright * 823*148c5f43SAlan Wright * Processes the snapshot data. 824*148c5f43SAlan Wright */ 825*148c5f43SAlan Wright static void 826*148c5f43SAlan Wright smbstat_srv_process(void) 827*148c5f43SAlan Wright { 828*148c5f43SAlan Wright smbstat_srv_snapshot_t *curr, *prev; 829*148c5f43SAlan Wright 830*148c5f43SAlan Wright curr = smbstat_srv_current_snapshot(); 831*148c5f43SAlan Wright prev = smbstat_srv_previous_snapshot(); 832*148c5f43SAlan Wright 833*148c5f43SAlan Wright if (prev->ss_snaptime == 0) 834*148c5f43SAlan Wright smbstat_srv_info.si_hretime = 835*148c5f43SAlan Wright smbstat_hrtime_delta(curr->ss_data.ks_start_time, 836*148c5f43SAlan Wright curr->ss_snaptime); 837*148c5f43SAlan Wright else 838*148c5f43SAlan Wright smbstat_srv_info.si_hretime = 839*148c5f43SAlan Wright smbstat_hrtime_delta(prev->ss_snaptime, curr->ss_snaptime); 840*148c5f43SAlan Wright 841*148c5f43SAlan Wright smbstat_srv_info.si_etime = smbstat_srv_info.si_hretime / NANOSEC; 842*148c5f43SAlan Wright smbstat_srv_info.si_total_nreqs = 843*148c5f43SAlan Wright smbstat_sub_64(curr->ss_data.ks_nreq, prev->ss_data.ks_nreq); 844*148c5f43SAlan Wright 845*148c5f43SAlan Wright if (smbstat_opt_c) 846*148c5f43SAlan Wright smbstat_srv_process_counters(curr); 847*148c5f43SAlan Wright if (smbstat_opt_t) 848*148c5f43SAlan Wright smbstat_srv_process_throughput(curr, prev); 849*148c5f43SAlan Wright if (smbstat_opt_u) 850*148c5f43SAlan Wright smbstat_srv_process_utilization(curr, prev); 851*148c5f43SAlan Wright if (smbstat_opt_r) 852*148c5f43SAlan Wright smbstat_srv_process_requests(curr, prev); 853*148c5f43SAlan Wright } 854*148c5f43SAlan Wright 855*148c5f43SAlan Wright /* 856*148c5f43SAlan Wright * smbstat_srv_process_counters 857*148c5f43SAlan Wright */ 858*148c5f43SAlan Wright static void 859*148c5f43SAlan Wright smbstat_srv_process_counters(smbstat_srv_snapshot_t *curr) 860*148c5f43SAlan Wright { 861*148c5f43SAlan Wright smbstat_srv_info.si_nbt_sess = curr->ss_data.ks_nbt_sess; 862*148c5f43SAlan Wright smbstat_srv_info.si_tcp_sess = curr->ss_data.ks_tcp_sess; 863*148c5f43SAlan Wright smbstat_srv_info.si_users = curr->ss_data.ks_users; 864*148c5f43SAlan Wright smbstat_srv_info.si_trees = curr->ss_data.ks_trees; 865*148c5f43SAlan Wright smbstat_srv_info.si_files = curr->ss_data.ks_files; 866*148c5f43SAlan Wright smbstat_srv_info.si_pipes = curr->ss_data.ks_pipes; 867*148c5f43SAlan Wright } 868*148c5f43SAlan Wright 869*148c5f43SAlan Wright /* 870*148c5f43SAlan Wright * smbstat_srv_process_throughput 871*148c5f43SAlan Wright * 872*148c5f43SAlan Wright * Processes the data relative to the throughput of the smbsrv module and 873*148c5f43SAlan Wright * stores the results in the structure smbstat_srv_info. 874*148c5f43SAlan Wright */ 875*148c5f43SAlan Wright static void 876*148c5f43SAlan Wright smbstat_srv_process_throughput( 877*148c5f43SAlan Wright smbstat_srv_snapshot_t *curr, 878*148c5f43SAlan Wright smbstat_srv_snapshot_t *prev) 879*148c5f43SAlan Wright { 880*148c5f43SAlan Wright smbstat_srv_info.si_tbs = 881*148c5f43SAlan Wright smbstat_sub_64(curr->ss_data.ks_txb, prev->ss_data.ks_txb); 882*148c5f43SAlan Wright smbstat_srv_info.si_tbs /= smbstat_srv_info.si_etime; 883*148c5f43SAlan Wright smbstat_srv_info.si_rbs = 884*148c5f43SAlan Wright smbstat_sub_64(curr->ss_data.ks_rxb, prev->ss_data.ks_rxb); 885*148c5f43SAlan Wright smbstat_srv_info.si_rbs /= smbstat_srv_info.si_etime; 886*148c5f43SAlan Wright smbstat_srv_info.si_rqs = smbstat_srv_info.si_total_nreqs; 887*148c5f43SAlan Wright smbstat_srv_info.si_rqs /= smbstat_srv_info.si_etime; 888*148c5f43SAlan Wright 889*148c5f43SAlan Wright smbstat_srv_info.si_rds = smbstat_sub_64( 890*148c5f43SAlan Wright curr->ss_data.ks_reqs[SMB_COM_READ].kr_nreq, 891*148c5f43SAlan Wright prev->ss_data.ks_reqs[SMB_COM_READ].kr_nreq); 892*148c5f43SAlan Wright smbstat_srv_info.si_rds += smbstat_sub_64( 893*148c5f43SAlan Wright curr->ss_data.ks_reqs[SMB_COM_LOCK_AND_READ].kr_nreq, 894*148c5f43SAlan Wright prev->ss_data.ks_reqs[SMB_COM_LOCK_AND_READ].kr_nreq); 895*148c5f43SAlan Wright smbstat_srv_info.si_rds += smbstat_sub_64( 896*148c5f43SAlan Wright curr->ss_data.ks_reqs[SMB_COM_READ_RAW].kr_nreq, 897*148c5f43SAlan Wright prev->ss_data.ks_reqs[SMB_COM_READ_RAW].kr_nreq); 898*148c5f43SAlan Wright smbstat_srv_info.si_rds += smbstat_sub_64( 899*148c5f43SAlan Wright curr->ss_data.ks_reqs[SMB_COM_READ_ANDX].kr_nreq, 900*148c5f43SAlan Wright prev->ss_data.ks_reqs[SMB_COM_READ_ANDX].kr_nreq); 901*148c5f43SAlan Wright smbstat_srv_info.si_rds /= smbstat_srv_info.si_etime; 902*148c5f43SAlan Wright 903*148c5f43SAlan Wright smbstat_srv_info.si_wrs = smbstat_sub_64( 904*148c5f43SAlan Wright curr->ss_data.ks_reqs[SMB_COM_WRITE].kr_nreq, 905*148c5f43SAlan Wright prev->ss_data.ks_reqs[SMB_COM_WRITE].kr_nreq); 906*148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64( 907*148c5f43SAlan Wright curr->ss_data.ks_reqs[SMB_COM_WRITE_AND_UNLOCK].kr_nreq, 908*148c5f43SAlan Wright prev->ss_data.ks_reqs[SMB_COM_WRITE_AND_UNLOCK].kr_nreq); 909*148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64( 910*148c5f43SAlan Wright curr->ss_data.ks_reqs[SMB_COM_WRITE_RAW].kr_nreq, 911*148c5f43SAlan Wright prev->ss_data.ks_reqs[SMB_COM_WRITE_RAW].kr_nreq); 912*148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64( 913*148c5f43SAlan Wright curr->ss_data.ks_reqs[SMB_COM_WRITE_AND_CLOSE].kr_nreq, 914*148c5f43SAlan Wright prev->ss_data.ks_reqs[SMB_COM_WRITE_AND_CLOSE].kr_nreq); 915*148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64( 916*148c5f43SAlan Wright curr->ss_data.ks_reqs[SMB_COM_WRITE_ANDX].kr_nreq, 917*148c5f43SAlan Wright prev->ss_data.ks_reqs[SMB_COM_WRITE_ANDX].kr_nreq); 918*148c5f43SAlan Wright smbstat_srv_info.si_wrs /= smbstat_srv_info.si_etime; 919*148c5f43SAlan Wright } 920*148c5f43SAlan Wright 921*148c5f43SAlan Wright /* 922*148c5f43SAlan Wright * smbstat_srv_process_utilization 923*148c5f43SAlan Wright * 924*148c5f43SAlan Wright * Processes the data relative to the utilization of the smbsrv module and 925*148c5f43SAlan Wright * stores the results in the structure smbstat_srv_info. 926*148c5f43SAlan Wright */ 927*148c5f43SAlan Wright static void 928*148c5f43SAlan Wright smbstat_srv_process_utilization( 929*148c5f43SAlan Wright smbstat_srv_snapshot_t *curr, 930*148c5f43SAlan Wright smbstat_srv_snapshot_t *prev) 931*148c5f43SAlan Wright { 932*148c5f43SAlan Wright double tw_delta, tr_delta; 933*148c5f43SAlan Wright double w_delta, r_delta; 934*148c5f43SAlan Wright double tps, rqs; 935*148c5f43SAlan Wright 936*148c5f43SAlan Wright w_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_wlentime, 937*148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_wlentime); 938*148c5f43SAlan Wright r_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_rlentime, 939*148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_rlentime); 940*148c5f43SAlan Wright tw_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_wtime, 941*148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_wtime); 942*148c5f43SAlan Wright tr_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_rtime, 943*148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_rtime); 944*148c5f43SAlan Wright rqs = smbstat_srv_info.si_total_nreqs / smbstat_srv_info.si_etime; 945*148c5f43SAlan Wright 946*148c5f43SAlan Wright /* Average number of requests waiting */ 947*148c5f43SAlan Wright if (w_delta != 0) 948*148c5f43SAlan Wright smbstat_srv_info.si_avw = w_delta / smbstat_srv_info.si_hretime; 949*148c5f43SAlan Wright else 950*148c5f43SAlan Wright smbstat_srv_info.si_avw = 0.0; 951*148c5f43SAlan Wright 952*148c5f43SAlan Wright /* Average number of request running */ 953*148c5f43SAlan Wright if (r_delta != 0) 954*148c5f43SAlan Wright smbstat_srv_info.si_avr = r_delta / smbstat_srv_info.si_hretime; 955*148c5f43SAlan Wright else 956*148c5f43SAlan Wright smbstat_srv_info.si_avr = 0.0; 957*148c5f43SAlan Wright 958*148c5f43SAlan Wright /* Utilization */ 959*148c5f43SAlan Wright smbstat_srv_info.si_upct = 960*148c5f43SAlan Wright (smbstat_srv_info.si_avr / curr->ss_data.ks_maxreqs) * 100; 961*148c5f43SAlan Wright 962*148c5f43SAlan Wright /* Average wait service time in milliseconds */ 963*148c5f43SAlan Wright smbstat_srv_info.si_rserv = 0.0; 964*148c5f43SAlan Wright smbstat_srv_info.si_wserv = 0.0; 965*148c5f43SAlan Wright if (rqs > 0.0 && 966*148c5f43SAlan Wright (smbstat_srv_info.si_avw != 0.0 || 967*148c5f43SAlan Wright smbstat_srv_info.si_avr != 0.0)) { 968*148c5f43SAlan Wright tps = 1 / rqs; 969*148c5f43SAlan Wright if (smbstat_srv_info.si_avw != 0.0) 970*148c5f43SAlan Wright smbstat_srv_info.si_wserv = 971*148c5f43SAlan Wright smbstat_srv_info.si_avw * tps; 972*148c5f43SAlan Wright if (smbstat_srv_info.si_avr != 0.0) 973*148c5f43SAlan Wright smbstat_srv_info.si_rserv = 974*148c5f43SAlan Wright smbstat_srv_info.si_avr * tps; 975*148c5f43SAlan Wright } 976*148c5f43SAlan Wright 977*148c5f43SAlan Wright /* % of time there is a transaction waiting for service */ 978*148c5f43SAlan Wright if (tw_delta != 0) { 979*148c5f43SAlan Wright smbstat_srv_info.si_wpct = tw_delta; 980*148c5f43SAlan Wright smbstat_srv_info.si_wpct /= smbstat_srv_info.si_hretime; 981*148c5f43SAlan Wright smbstat_srv_info.si_wpct *= 100.0; 982*148c5f43SAlan Wright } else { 983*148c5f43SAlan Wright smbstat_srv_info.si_wpct = 0.0; 984*148c5f43SAlan Wright } 985*148c5f43SAlan Wright 986*148c5f43SAlan Wright /* % of time there is a transaction running */ 987*148c5f43SAlan Wright if (tr_delta != 0) { 988*148c5f43SAlan Wright smbstat_srv_info.si_rpct = tr_delta; 989*148c5f43SAlan Wright smbstat_srv_info.si_rpct /= smbstat_srv_info.si_hretime; 990*148c5f43SAlan Wright smbstat_srv_info.si_rpct *= 100.0; 991*148c5f43SAlan Wright } else { 992*148c5f43SAlan Wright smbstat_srv_info.si_rpct = 0.0; 993*148c5f43SAlan Wright } 994*148c5f43SAlan Wright } 995*148c5f43SAlan Wright 996*148c5f43SAlan Wright /* 997*148c5f43SAlan Wright * smbstat_srv_process_requests 998*148c5f43SAlan Wright * 999*148c5f43SAlan Wright * Processes the data relative to the SMB requests and stores the results in 1000*148c5f43SAlan Wright * the structure smbstat_srv_info. 1001*148c5f43SAlan Wright */ 1002*148c5f43SAlan Wright static void 1003*148c5f43SAlan Wright smbstat_srv_process_requests( 1004*148c5f43SAlan Wright smbstat_srv_snapshot_t *curr, 1005*148c5f43SAlan Wright smbstat_srv_snapshot_t *prev) 1006*148c5f43SAlan Wright { 1007*148c5f43SAlan Wright smbstat_req_info_t *info; 1008*148c5f43SAlan Wright double nrqs; 1009*148c5f43SAlan Wright int i, idx; 1010*148c5f43SAlan Wright 1011*148c5f43SAlan Wright info = smbstat_srv_info.si_reqs; 1012*148c5f43SAlan Wright 1013*148c5f43SAlan Wright for (i = 0; i < SMB_COM_NUM; i++) { 1014*148c5f43SAlan Wright idx = info[i].ri_opcode; 1015*148c5f43SAlan Wright 1016*148c5f43SAlan Wright nrqs = smbstat_sub_64(curr->ss_data.ks_reqs[idx].kr_nreq, 1017*148c5f43SAlan Wright prev->ss_data.ks_reqs[idx].kr_nreq); 1018*148c5f43SAlan Wright 1019*148c5f43SAlan Wright info[i].ri_rqs = nrqs / smbstat_srv_info.si_etime; 1020*148c5f43SAlan Wright 1021*148c5f43SAlan Wright info[i].ri_rbs = smbstat_sub_64( 1022*148c5f43SAlan Wright curr->ss_data.ks_reqs[idx].kr_rxb, 1023*148c5f43SAlan Wright prev->ss_data.ks_reqs[idx].kr_rxb) / 1024*148c5f43SAlan Wright smbstat_srv_info.si_etime; 1025*148c5f43SAlan Wright 1026*148c5f43SAlan Wright info[i].ri_tbs = smbstat_sub_64( 1027*148c5f43SAlan Wright curr->ss_data.ks_reqs[idx].kr_txb, 1028*148c5f43SAlan Wright prev->ss_data.ks_reqs[idx].kr_txb) / 1029*148c5f43SAlan Wright smbstat_srv_info.si_etime; 1030*148c5f43SAlan Wright 1031*148c5f43SAlan Wright info[i].ri_pct = nrqs * 100; 1032*148c5f43SAlan Wright if (smbstat_srv_info.si_total_nreqs > 0) 1033*148c5f43SAlan Wright info[i].ri_pct /= smbstat_srv_info.si_total_nreqs; 1034*148c5f43SAlan Wright 1035*148c5f43SAlan Wright if (prev->ss_snaptime == 0) { 1036*148c5f43SAlan Wright /* First time. Take the aggregate */ 1037*148c5f43SAlan Wright info[i].ri_stddev = 1038*148c5f43SAlan Wright curr->ss_data.ks_reqs[idx].kr_a_stddev; 1039*148c5f43SAlan Wright info[i].ri_mean = curr->ss_data.ks_reqs[idx].kr_a_mean; 1040*148c5f43SAlan Wright } else { 1041*148c5f43SAlan Wright /* Take the differential */ 1042*148c5f43SAlan Wright info[i].ri_stddev = 1043*148c5f43SAlan Wright curr->ss_data.ks_reqs[idx].kr_d_stddev; 1044*148c5f43SAlan Wright info[i].ri_mean = curr->ss_data.ks_reqs[idx].kr_d_mean; 1045*148c5f43SAlan Wright } 1046*148c5f43SAlan Wright if (nrqs > 0) { 1047*148c5f43SAlan Wright info[i].ri_stddev /= nrqs; 1048*148c5f43SAlan Wright info[i].ri_stddev = sqrt(info[i].ri_stddev); 1049*148c5f43SAlan Wright } else { 1050*148c5f43SAlan Wright info[i].ri_stddev = 0; 1051*148c5f43SAlan Wright } 1052*148c5f43SAlan Wright info[i].ri_stddev /= NANOSEC; 1053*148c5f43SAlan Wright info[i].ri_mean /= NANOSEC; 1054*148c5f43SAlan Wright } 1055*148c5f43SAlan Wright } 1056*148c5f43SAlan Wright 1057*148c5f43SAlan Wright /* 1058*148c5f43SAlan Wright * smbstat_srv_current_snapshot 1059*148c5f43SAlan Wright * 1060*148c5f43SAlan Wright * Returns the current snapshot. 1061*148c5f43SAlan Wright */ 1062*148c5f43SAlan Wright static smbstat_srv_snapshot_t * 1063*148c5f43SAlan Wright smbstat_srv_current_snapshot(void) 1064*148c5f43SAlan Wright { 1065*148c5f43SAlan Wright return (&smbstat_srv_snapshots[smbstat_snapshot_idx]); 1066*148c5f43SAlan Wright } 1067*148c5f43SAlan Wright 1068*148c5f43SAlan Wright /* 1069*148c5f43SAlan Wright * smbstat_srv_previous_snapshot 1070*148c5f43SAlan Wright * 1071*148c5f43SAlan Wright * Returns the previous snapshot. 1072*148c5f43SAlan Wright */ 1073*148c5f43SAlan Wright static smbstat_srv_snapshot_t * 1074*148c5f43SAlan Wright smbstat_srv_previous_snapshot(void) 1075*148c5f43SAlan Wright { 1076*148c5f43SAlan Wright int idx; 1077*148c5f43SAlan Wright 1078*148c5f43SAlan Wright idx = (smbstat_snapshot_idx - 1) & SMBSTAT_SNAPSHOT_MASK; 1079*148c5f43SAlan Wright return (&smbstat_srv_snapshots[idx]); 1080*148c5f43SAlan Wright } 1081*148c5f43SAlan Wright 1082*148c5f43SAlan Wright /* 1083*148c5f43SAlan Wright * smbstat_usage 1084*148c5f43SAlan Wright * 1085*148c5f43SAlan Wright * Prints out a help message. 1086*148c5f43SAlan Wright */ 1087*148c5f43SAlan Wright static void 1088*148c5f43SAlan Wright smbstat_usage(FILE *fd, int exit_code) 1089*148c5f43SAlan Wright { 1090*148c5f43SAlan Wright (void) fprintf(fd, gettext(SMBSTAT_HELP)); 1091*148c5f43SAlan Wright exit(exit_code); 1092*148c5f43SAlan Wright } 1093*148c5f43SAlan Wright 1094*148c5f43SAlan Wright /* 1095*148c5f43SAlan Wright * smbstat_fail 1096*148c5f43SAlan Wright * 1097*148c5f43SAlan Wright * Prints out to stderr an error message and exits the process. 1098*148c5f43SAlan Wright */ 1099da6c28aaSamw static void 1100da6c28aaSamw smbstat_fail(int do_perror, char *message, ...) 1101da6c28aaSamw { 1102da6c28aaSamw va_list args; 1103da6c28aaSamw 1104da6c28aaSamw va_start(args, message); 1105da6c28aaSamw (void) fprintf(stderr, gettext("smbstat: ")); 1106da6c28aaSamw /* LINTED E_SEC_PRINTF_VAR_FMT */ 1107da6c28aaSamw (void) vfprintf(stderr, message, args); 1108da6c28aaSamw va_end(args); 1109da6c28aaSamw if (do_perror) 1110da6c28aaSamw (void) fprintf(stderr, ": %s", strerror(errno)); 1111da6c28aaSamw (void) fprintf(stderr, "\n"); 1112da6c28aaSamw exit(1); 1113da6c28aaSamw } 1114da6c28aaSamw 1115*148c5f43SAlan Wright /* 1116*148c5f43SAlan Wright * smbstat_sub_64 1117*148c5f43SAlan Wright * 1118*148c5f43SAlan Wright * Substract 2 uint64_t and returns a double. 1119*148c5f43SAlan Wright */ 1120*148c5f43SAlan Wright static double 1121*148c5f43SAlan Wright smbstat_sub_64(uint64_t a, uint64_t b) 1122da6c28aaSamw { 1123*148c5f43SAlan Wright return ((double)(a - b)); 1124da6c28aaSamw } 1125da6c28aaSamw 1126da6c28aaSamw /* 1127*148c5f43SAlan Wright * smbstat_zero 1128*148c5f43SAlan Wright * 1129*148c5f43SAlan Wright * Returns zero if the value passed in is less than 1. 1130da6c28aaSamw */ 1131*148c5f43SAlan Wright static double 1132*148c5f43SAlan Wright smbstat_zero(double value) 1133da6c28aaSamw { 1134*148c5f43SAlan Wright if (value < 1) 1135*148c5f43SAlan Wright value = 0; 1136*148c5f43SAlan Wright return (value); 1137da6c28aaSamw } 1138da6c28aaSamw 1139*148c5f43SAlan Wright /* 1140*148c5f43SAlan Wright * smbstat_strtoi 1141*148c5f43SAlan Wright * 1142*148c5f43SAlan Wright * Converts a string representing an integer value into its binary value. 1143*148c5f43SAlan Wright * If the conversion fails this routine exits the process. 1144*148c5f43SAlan Wright */ 1145*148c5f43SAlan Wright static uint_t 1146*148c5f43SAlan Wright smbstat_strtoi(char const *val, char *errmsg) 1147da6c28aaSamw { 1148*148c5f43SAlan Wright char *end; 1149*148c5f43SAlan Wright long tmp; 1150*148c5f43SAlan Wright 1151*148c5f43SAlan Wright errno = 0; 1152*148c5f43SAlan Wright tmp = strtol(val, &end, 10); 1153*148c5f43SAlan Wright if (*end != '\0' || errno) 1154*148c5f43SAlan Wright smbstat_fail(1, "%s %s", errmsg, val); 1155*148c5f43SAlan Wright return ((uint_t)tmp); 1156da6c28aaSamw } 1157*148c5f43SAlan Wright 1158*148c5f43SAlan Wright /* 1159*148c5f43SAlan Wright * smbstat_termio_init 1160*148c5f43SAlan Wright * 1161*148c5f43SAlan Wright * Determines the size of the terminal associated with the process. 1162*148c5f43SAlan Wright */ 1163*148c5f43SAlan Wright static void 1164*148c5f43SAlan Wright smbstat_termio_init(void) 1165*148c5f43SAlan Wright { 1166*148c5f43SAlan Wright char *envp; 1167*148c5f43SAlan Wright 1168*148c5f43SAlan Wright if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &smbstat_ws) != -1) { 1169*148c5f43SAlan Wright if (smbstat_ws.ws_row == 0) { 1170*148c5f43SAlan Wright envp = getenv("LINES"); 1171*148c5f43SAlan Wright if (envp != NULL) 1172*148c5f43SAlan Wright smbstat_ws.ws_row = atoi(envp); 1173*148c5f43SAlan Wright } 1174*148c5f43SAlan Wright 1175*148c5f43SAlan Wright if (smbstat_ws.ws_col == 0) { 1176*148c5f43SAlan Wright envp = getenv("COLUMNS"); 1177*148c5f43SAlan Wright if (envp != NULL) 1178*148c5f43SAlan Wright smbstat_ws.ws_row = atoi(envp); 1179*148c5f43SAlan Wright } 1180*148c5f43SAlan Wright } 1181*148c5f43SAlan Wright if (smbstat_ws.ws_col == 0) 1182*148c5f43SAlan Wright smbstat_ws.ws_col = 80; 1183*148c5f43SAlan Wright if (smbstat_ws.ws_row == 0) 1184*148c5f43SAlan Wright smbstat_ws.ws_row = 25; 1185*148c5f43SAlan Wright } 1186*148c5f43SAlan Wright 1187*148c5f43SAlan Wright /* 1188*148c5f43SAlan Wright * smbstat_snapshot_idx_inc 1189*148c5f43SAlan Wright * 1190*148c5f43SAlan Wright * Increments the snapshot index. 1191*148c5f43SAlan Wright */ 1192*148c5f43SAlan Wright static void 1193*148c5f43SAlan Wright smbstat_snapshot_inc_idx(void) 1194*148c5f43SAlan Wright { 1195*148c5f43SAlan Wright smbstat_snapshot_idx++; 1196*148c5f43SAlan Wright smbstat_snapshot_idx &= SMBSTAT_SNAPSHOT_MASK; 1197*148c5f43SAlan Wright } 1198*148c5f43SAlan Wright 1199*148c5f43SAlan Wright /* 1200*148c5f43SAlan Wright * smbstat_req_cmp_name 1201*148c5f43SAlan Wright * 1202*148c5f43SAlan Wright * Call back function passed to qsort() when the list of requests must be sorted 1203*148c5f43SAlan Wright * by name. 1204*148c5f43SAlan Wright */ 1205*148c5f43SAlan Wright static int 1206*148c5f43SAlan Wright smbstat_req_cmp_name(const void *obj1, const void *obj2) 1207*148c5f43SAlan Wright { 1208*148c5f43SAlan Wright return (strncasecmp( 1209*148c5f43SAlan Wright ((smbstat_req_info_t *)obj1)->ri_name, 1210*148c5f43SAlan Wright ((smbstat_req_info_t *)obj2)->ri_name, 1211*148c5f43SAlan Wright sizeof (((smbstat_req_info_t *)obj2)->ri_name))); 1212*148c5f43SAlan Wright } 1213*148c5f43SAlan Wright 1214*148c5f43SAlan Wright /* 1215*148c5f43SAlan Wright * smbstat_req_order 1216*148c5f43SAlan Wright * 1217*148c5f43SAlan Wright * Snapshots the smbsrv module statistics once to get the name of the requests. 1218*148c5f43SAlan Wright * The request list is smbstat_srv_info is then sorted by name or by code 1219*148c5f43SAlan Wright * depending on the boolean smbstat_opt_a. 1220*148c5f43SAlan Wright * The function should be called once during initialization. 1221*148c5f43SAlan Wright */ 1222*148c5f43SAlan Wright static void 1223*148c5f43SAlan Wright smbstat_req_order(void) 1224*148c5f43SAlan Wright { 1225*148c5f43SAlan Wright smbstat_req_info_t *info; 1226*148c5f43SAlan Wright smb_kstat_req_t *reqs; 1227*148c5f43SAlan Wright int i; 1228*148c5f43SAlan Wright 1229*148c5f43SAlan Wright smbstat_srv_snapshot(); 1230*148c5f43SAlan Wright reqs = smbstat_srv_current_snapshot()->ss_data.ks_reqs; 1231*148c5f43SAlan Wright info = smbstat_srv_info.si_reqs; 1232*148c5f43SAlan Wright 1233*148c5f43SAlan Wright for (i = 0; i < SMB_COM_NUM; i++) { 1234*148c5f43SAlan Wright (void) strlcpy(info[i].ri_name, reqs[i].kr_name, 1235*148c5f43SAlan Wright sizeof (reqs[i].kr_name)); 1236*148c5f43SAlan Wright info[i].ri_opcode = i; 1237*148c5f43SAlan Wright } 1238*148c5f43SAlan Wright if (smbstat_opt_n) 1239*148c5f43SAlan Wright qsort(info, SMB_COM_NUM, sizeof (smbstat_req_info_t), 1240*148c5f43SAlan Wright smbstat_req_cmp_name); 1241*148c5f43SAlan Wright } 1242*148c5f43SAlan Wright 1243*148c5f43SAlan Wright /* 1244*148c5f43SAlan Wright * Return the number of ticks delta between two hrtime_t 1245*148c5f43SAlan Wright * values. Attempt to cater for various kinds of overflow 1246*148c5f43SAlan Wright * in hrtime_t - no matter how improbable. 1247*148c5f43SAlan Wright */ 1248*148c5f43SAlan Wright static double 1249*148c5f43SAlan Wright smbstat_hrtime_delta(hrtime_t old, hrtime_t new) 1250*148c5f43SAlan Wright { 1251*148c5f43SAlan Wright uint64_t del; 1252*148c5f43SAlan Wright 1253*148c5f43SAlan Wright if ((new >= old) && (old >= 0L)) 1254*148c5f43SAlan Wright return ((double)(new - old)); 1255*148c5f43SAlan Wright /* 1256*148c5f43SAlan Wright * We've overflowed the positive portion of an hrtime_t. 1257*148c5f43SAlan Wright */ 1258*148c5f43SAlan Wright if (new < 0L) { 1259*148c5f43SAlan Wright /* 1260*148c5f43SAlan Wright * The new value is negative. Handle the case where the old 1261*148c5f43SAlan Wright * value is positive or negative. 1262*148c5f43SAlan Wright */ 1263*148c5f43SAlan Wright uint64_t n1; 1264*148c5f43SAlan Wright uint64_t o1; 1265*148c5f43SAlan Wright 1266*148c5f43SAlan Wright n1 = -new; 1267*148c5f43SAlan Wright if (old > 0L) 1268*148c5f43SAlan Wright return ((double)(n1 - old)); 1269*148c5f43SAlan Wright 1270*148c5f43SAlan Wright o1 = -old; 1271*148c5f43SAlan Wright del = n1 - o1; 1272*148c5f43SAlan Wright return ((double)del); 1273*148c5f43SAlan Wright } 1274*148c5f43SAlan Wright 1275*148c5f43SAlan Wright /* 1276*148c5f43SAlan Wright * Either we've just gone from being negative to positive *or* the last 1277*148c5f43SAlan Wright * entry was positive and the new entry is also positive but *less* than 1278*148c5f43SAlan Wright * the old entry. This implies we waited quite a few days on a very fast 1279*148c5f43SAlan Wright * system between displays. 1280*148c5f43SAlan Wright */ 1281*148c5f43SAlan Wright if (old < 0L) { 1282*148c5f43SAlan Wright uint64_t o2; 1283*148c5f43SAlan Wright o2 = -old; 1284*148c5f43SAlan Wright del = UINT64_MAX - o2; 1285*148c5f43SAlan Wright } else { 1286*148c5f43SAlan Wright del = UINT64_MAX - old; 1287*148c5f43SAlan Wright } 1288*148c5f43SAlan Wright del += new; 1289*148c5f43SAlan Wright return ((double)del); 1290*148c5f43SAlan Wright } 1291*148c5f43SAlan Wright 1292*148c5f43SAlan Wright static void * 1293*148c5f43SAlan Wright smbstat_zalloc(size_t size) 1294*148c5f43SAlan Wright { 1295*148c5f43SAlan Wright void *ptr; 1296*148c5f43SAlan Wright 1297*148c5f43SAlan Wright ptr = umem_zalloc(size, UMEM_DEFAULT); 1298*148c5f43SAlan Wright if (ptr == NULL) 1299*148c5f43SAlan Wright smbstat_fail(1, gettext("out of memory")); 1300*148c5f43SAlan Wright return (ptr); 1301*148c5f43SAlan Wright } 1302*148c5f43SAlan Wright 1303*148c5f43SAlan Wright static void 1304*148c5f43SAlan Wright smbstat_free(void *ptr, size_t size) 1305*148c5f43SAlan Wright { 1306*148c5f43SAlan Wright umem_free(ptr, size); 1307*148c5f43SAlan Wright } 1308