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 /* 23148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24*5015ecc3SGordon Ross * Copyright 2020 Nexenta by DDN, Inc. All rights reserved. 25da6c28aaSamw */ 26da6c28aaSamw 27da6c28aaSamw /* 28da6c28aaSamw * smbstat: Server Message Block File System statistics 29148c5f43SAlan Wright * 30148c5f43SAlan Wright * The statistics this CLI displays come from two sources: 31148c5f43SAlan Wright * 32148c5f43SAlan Wright * 1) The kernel module 'smbsrv'. 33148c5f43SAlan Wright * 2) The SMB workers task queue statistics the task queue manager of Solaris 34148c5f43SAlan Wright * maintains. 35148c5f43SAlan Wright * 36148c5f43SAlan Wright * The flow of the code is the following: 37148c5f43SAlan Wright * 38148c5f43SAlan Wright * 39*5015ecc3SGordon Ross * +----------------+ 40*5015ecc3SGordon Ross * | Initialization | 41*5015ecc3SGordon Ross * +----------------+ 42148c5f43SAlan Wright * | 43148c5f43SAlan Wright * | 44148c5f43SAlan Wright * v 45148c5f43SAlan Wright * +--------------------------* 46148c5f43SAlan Wright * | Take a snapshot the data | <--------+ 47148c5f43SAlan Wright * +--------------------------+ | 48148c5f43SAlan Wright * | | 49*5015ecc3SGordon Ross * | | 50148c5f43SAlan Wright * v | 51148c5f43SAlan Wright * +----------------------+ | 52148c5f43SAlan Wright * | Process the snapshot | | 53148c5f43SAlan Wright * +----------------------+ | 54148c5f43SAlan Wright * | | 55148c5f43SAlan Wright * | | 56148c5f43SAlan Wright * v | 57148c5f43SAlan Wright * +------------------------------------+ | 58148c5f43SAlan Wright * | Print the result of the processing | | 59148c5f43SAlan Wright * +------------------------------------+ | 60148c5f43SAlan Wright * | | 61148c5f43SAlan Wright * | | 62148c5f43SAlan Wright * v | 63148c5f43SAlan Wright * Yes --------------- | 64148c5f43SAlan Wright * +------------ < interval == 0 ? > | 65*5015ecc3SGordon Ross * | --------------- | 66148c5f43SAlan Wright * | | | 67*5015ecc3SGordon Ross * | | No | 68*5015ecc3SGordon Ross * | v | 69148c5f43SAlan Wright * | +------------------------+ | 70*5015ecc3SGordon Ross * | | Sleep for the duration | ----------+ 71*5015ecc3SGordon Ross * | | of the interval. | 72*5015ecc3SGordon Ross * | +------------------------+ 73*5015ecc3SGordon Ross * | 74*5015ecc3SGordon Ross * +---------------------+ 75148c5f43SAlan Wright * | 76148c5f43SAlan Wright * v 77148c5f43SAlan Wright * 78148c5f43SAlan Wright * Exit 79148c5f43SAlan Wright * 80148c5f43SAlan Wright * There are two sets of snapshots. One set for the smbsrv module and the other 81148c5f43SAlan Wright * for the task queue (SMB workers). Each set contains 2 snapshots. One is 82148c5f43SAlan Wright * labeled 'current' the other one 'previous'. Their role changes after each 83148c5f43SAlan Wright * snapshot. The 'current' becomes 'previous' and vice versa. 84148c5f43SAlan Wright * The first snapshot taken is compared against the data gathered since the 85148c5f43SAlan Wright * smbsrv module was loaded. Subsequent snapshots will be compared against the 86148c5f43SAlan Wright * previous snapshot. 87da6c28aaSamw */ 88148c5f43SAlan Wright 89da6c28aaSamw #include <stdio.h> 90da6c28aaSamw #include <stdlib.h> 91148c5f43SAlan Wright #include <unistd.h> 92da6c28aaSamw #include <kstat.h> 93da6c28aaSamw #include <stdarg.h> 94da6c28aaSamw #include <errno.h> 95da6c28aaSamw #include <inttypes.h> 96da6c28aaSamw #include <strings.h> 97da6c28aaSamw #include <utility.h> 98da6c28aaSamw #include <libintl.h> 99da6c28aaSamw #include <zone.h> 100148c5f43SAlan Wright #include <termios.h> 101148c5f43SAlan Wright #include <stropts.h> 102148c5f43SAlan Wright #include <math.h> 103148c5f43SAlan Wright #include <umem.h> 104148c5f43SAlan Wright #include <locale.h> 105b3b35633SGordon Ross #include <sys/processor.h> 1066537f381Sas #include <smbsrv/smb_kstat.h> 107da6c28aaSamw 108148c5f43SAlan Wright #if !defined(TEXT_DOMAIN) 109148c5f43SAlan Wright #define TEXT_DOMAIN "SYS_TEST" 110148c5f43SAlan Wright #endif /* TEXT_DOMAIN */ 111148c5f43SAlan Wright 112148c5f43SAlan Wright #define SMBSTAT_ID_NO_CPU -1 113148c5f43SAlan Wright #define SMBSTAT_SNAPSHOT_COUNT 2 /* Must be a power of 2 */ 114148c5f43SAlan Wright #define SMBSTAT_SNAPSHOT_MASK (SMBSTAT_SNAPSHOT_COUNT - 1) 115148c5f43SAlan Wright 116148c5f43SAlan Wright #define SMBSTAT_HELP \ 117148c5f43SAlan Wright "Usage: smbstat [-acnrtuz] [interval]\n" \ 118148c5f43SAlan Wright " -c: display counters\n" \ 119148c5f43SAlan Wright " -t: display throughput\n" \ 120148c5f43SAlan Wright " -u: display utilization\n" \ 121148c5f43SAlan Wright " -r: display requests\n" \ 122148c5f43SAlan Wright " -a: all the requests (supported and unsupported)\n" \ 123148c5f43SAlan Wright " -z: skip the requests not received\n" \ 124148c5f43SAlan Wright " -n: display in alphabetic order\n" \ 125148c5f43SAlan Wright " interval: refresh cycle in seconds\n" 126148c5f43SAlan Wright 127148c5f43SAlan Wright #define SMBSRV_COUNTERS_BANNER "\n nbt tcp users trees files pipes\n" 128148c5f43SAlan Wright #define SMBSRV_COUNTERS_FORMAT "%5d %5d %5d %5d %5d %5d\n" 129148c5f43SAlan Wright 130148c5f43SAlan Wright #define SMBSRV_THROUGHPUT_BANNER \ 131148c5f43SAlan Wright "\nrbytes/s tbytes/s reqs/s reads/s writes/s\n" 132148c5f43SAlan Wright #define SMBSRV_THROUGHPUT_FORMAT \ 133148c5f43SAlan Wright "%1.3e %1.3e %1.3e %1.3e %1.3e\n" 134148c5f43SAlan Wright 135148c5f43SAlan Wright #define SMBSRV_UTILIZATION_BANNER \ 136148c5f43SAlan Wright "\n wcnt rcnt wtime rtime" \ 137148c5f43SAlan Wright " w%% r%% u%% sat usr%% sys%% idle%%\n" 138148c5f43SAlan Wright #define SMBSRV_UTILIZATION_FORMAT \ 139148c5f43SAlan Wright "%1.3e %1.3e %1.3e %1.3e %3.0f %3.0f %3.0f %s " \ 140148c5f43SAlan Wright "%3.0f %3.0f %3.0f\n" 141148c5f43SAlan Wright 142148c5f43SAlan Wright #define SMBSRV_REQUESTS_BANNER \ 143148c5f43SAlan Wright "\n%30s code %% rbytes/s tbytes/s req/s rt-mean" \ 144148c5f43SAlan Wright " rt-stddev\n" 145148c5f43SAlan Wright #define SMBSRV_REQUESTS_FORMAT \ 146148c5f43SAlan Wright "%30s %02X %3.0f %1.3e %1.3e %1.3e %1.3e %1.3e\n" 147148c5f43SAlan Wright 148148c5f43SAlan Wright typedef enum { 149148c5f43SAlan Wright CPU_TICKS_IDLE = 0, 150148c5f43SAlan Wright CPU_TICKS_USER, 151148c5f43SAlan Wright CPU_TICKS_KERNEL, 152148c5f43SAlan Wright CPU_TICKS_SENTINEL 153148c5f43SAlan Wright } cpu_state_idx_t; 154148c5f43SAlan Wright 155148c5f43SAlan Wright typedef struct smbstat_cpu_snapshot { 156148c5f43SAlan Wright processorid_t cs_id; 157148c5f43SAlan Wright int cs_state; 158148c5f43SAlan Wright uint64_t cs_ticks[CPU_TICKS_SENTINEL]; 159148c5f43SAlan Wright } smbstat_cpu_snapshot_t; 160148c5f43SAlan Wright 161148c5f43SAlan Wright typedef struct smbstat_srv_snapshot { 162148c5f43SAlan Wright hrtime_t ss_snaptime; 163148c5f43SAlan Wright smbsrv_kstats_t ss_data; 164148c5f43SAlan Wright } smbstat_srv_snapshot_t; 165148c5f43SAlan Wright 166148c5f43SAlan Wright typedef struct smbstat_wrk_snapshot { 167148c5f43SAlan Wright uint64_t ws_maxthreads; 168148c5f43SAlan Wright uint64_t ws_bnalloc; 169148c5f43SAlan Wright } smbstat_wrk_snapshot_t; 170148c5f43SAlan Wright 171148c5f43SAlan Wright typedef struct smbstat_req_info { 172148c5f43SAlan Wright char ri_name[KSTAT_STRLEN]; 173148c5f43SAlan Wright int ri_opcode; 174148c5f43SAlan Wright double ri_pct; 175148c5f43SAlan Wright double ri_tbs; 176148c5f43SAlan Wright double ri_rbs; 177148c5f43SAlan Wright double ri_rqs; 178148c5f43SAlan Wright double ri_stddev; 179148c5f43SAlan Wright double ri_mean; 180148c5f43SAlan Wright } smbstat_req_info_t; 181148c5f43SAlan Wright 182148c5f43SAlan Wright typedef struct smbstat_srv_info { 183148c5f43SAlan Wright double si_hretime; 184148c5f43SAlan Wright double si_etime; 185148c5f43SAlan Wright double si_total_nreqs; 186148c5f43SAlan Wright /* 187148c5f43SAlan Wright * Counters 188148c5f43SAlan Wright */ 189148c5f43SAlan Wright uint32_t si_nbt_sess; /* NBT sessions */ 190148c5f43SAlan Wright uint32_t si_tcp_sess; /* TCP sessions */ 191148c5f43SAlan Wright uint32_t si_users; /* Users logged in */ 192148c5f43SAlan Wright uint32_t si_trees; /* Trees connected */ 193148c5f43SAlan Wright uint32_t si_files; /* Open files */ 194148c5f43SAlan Wright uint32_t si_pipes; /* Open pipes */ 195148c5f43SAlan Wright /* 196148c5f43SAlan Wright * Throughput of the server 197148c5f43SAlan Wright */ 198148c5f43SAlan Wright double si_tbs; /* Bytes transmitted / second */ 199148c5f43SAlan Wright double si_rbs; /* Bytes received / second */ 200148c5f43SAlan Wright double si_rqs; /* Requests treated / second */ 201148c5f43SAlan Wright double si_rds; /* Reads treated / second */ 202148c5f43SAlan Wright double si_wrs; /* Writes treated / second */ 203148c5f43SAlan Wright /* 204148c5f43SAlan Wright * Utilization of the server 205148c5f43SAlan Wright */ 206148c5f43SAlan Wright double si_wpct; /* */ 207148c5f43SAlan Wright double si_rpct; /* */ 208148c5f43SAlan Wright double si_upct; /* Utilization in % */ 209148c5f43SAlan Wright double si_avw; /* Average number of requests waiting */ 210148c5f43SAlan Wright double si_avr; /* Average number of requests running */ 211148c5f43SAlan Wright double si_wserv; /* Average waiting time */ 212148c5f43SAlan Wright double si_rserv; /* Average running time */ 213148c5f43SAlan Wright boolean_t si_sat; 214148c5f43SAlan Wright double si_ticks[CPU_TICKS_SENTINEL]; 215148c5f43SAlan Wright /* 216148c5f43SAlan Wright * Latency & Throughput per request 217148c5f43SAlan Wright */ 218a90cf9f2SGordon Ross smbstat_req_info_t si_reqs1[SMB_COM_NUM]; 219a90cf9f2SGordon Ross smbstat_req_info_t si_reqs2[SMB2__NCMDS]; 220148c5f43SAlan Wright } smbstat_srv_info_t; 221da6c28aaSamw 2226537f381Sas static void smbstat_init(void); 2236537f381Sas static void smbstat_fini(void); 224148c5f43SAlan Wright static void smbstat_kstat_snapshot(void); 225148c5f43SAlan Wright static void smbstat_kstat_process(void); 226148c5f43SAlan Wright static void smbstat_kstat_print(void); 227148c5f43SAlan Wright 228148c5f43SAlan Wright static void smbstat_print_counters(void); 229148c5f43SAlan Wright static void smbstat_print_throughput(void); 230148c5f43SAlan Wright static void smbstat_print_utilization(void); 231148c5f43SAlan Wright static void smbstat_print_requests(void); 232148c5f43SAlan Wright 233148c5f43SAlan Wright static void smbstat_cpu_init(void); 234148c5f43SAlan Wright static void smbstat_cpu_fini(void); 235148c5f43SAlan Wright static smbstat_cpu_snapshot_t *smbstat_cpu_current_snapshot(void); 236148c5f43SAlan Wright static smbstat_cpu_snapshot_t *smbstat_cpu_previous_snapshot(void); 237148c5f43SAlan Wright static void smbstat_cpu_snapshot(void); 238148c5f43SAlan Wright static void smbstat_cpu_process(void); 239148c5f43SAlan Wright 240148c5f43SAlan Wright static void smbstat_wrk_init(void); 241148c5f43SAlan Wright static void smbstat_wrk_fini(void); 242148c5f43SAlan Wright static void smbstat_wrk_snapshot(void); 243148c5f43SAlan Wright static void smbstat_wrk_process(void); 244148c5f43SAlan Wright static smbstat_wrk_snapshot_t *smbstat_wrk_current_snapshot(void); 245148c5f43SAlan Wright 246148c5f43SAlan Wright static void smbstat_srv_init(void); 247148c5f43SAlan Wright static void smbstat_srv_fini(void); 248148c5f43SAlan Wright static void smbstat_srv_snapshot(void); 249148c5f43SAlan Wright static void smbstat_srv_process(void); 250148c5f43SAlan Wright static void smbstat_srv_process_counters(smbstat_srv_snapshot_t *); 251148c5f43SAlan Wright static void smbstat_srv_process_throughput(smbstat_srv_snapshot_t *, 252148c5f43SAlan Wright smbstat_srv_snapshot_t *); 253148c5f43SAlan Wright static void smbstat_srv_process_utilization(smbstat_srv_snapshot_t *, 254148c5f43SAlan Wright smbstat_srv_snapshot_t *); 255148c5f43SAlan Wright static void smbstat_srv_process_requests(smbstat_srv_snapshot_t *, 256148c5f43SAlan Wright smbstat_srv_snapshot_t *); 257a90cf9f2SGordon Ross static void smbstat_srv_process_one_req(smbstat_req_info_t *, 258a90cf9f2SGordon Ross smb_kstat_req_t *, smb_kstat_req_t *, boolean_t); 259a90cf9f2SGordon Ross 260148c5f43SAlan Wright static smbstat_srv_snapshot_t *smbstat_srv_current_snapshot(void); 261148c5f43SAlan Wright static smbstat_srv_snapshot_t *smbstat_srv_previous_snapshot(void); 262148c5f43SAlan Wright 263148c5f43SAlan Wright static void *smbstat_zalloc(size_t); 264148c5f43SAlan Wright static void smbstat_free(void *, size_t); 265da6c28aaSamw static void smbstat_fail(int, char *, ...); 266148c5f43SAlan Wright static void smbstat_snapshot_inc_idx(void); 267f5aec946SToomas Soome static void smbstat_usage(FILE *, int) __NORETURN; 268148c5f43SAlan Wright static uint_t smbstat_strtoi(char const *, char *); 269148c5f43SAlan Wright static double smbstat_hrtime_delta(hrtime_t, hrtime_t); 270148c5f43SAlan Wright static double smbstat_sub_64(uint64_t, uint64_t); 271148c5f43SAlan Wright static void smbstat_req_order(void); 272148c5f43SAlan Wright static double smbstat_zero(double); 273148c5f43SAlan Wright static void smbstat_termio_init(void); 274148c5f43SAlan Wright 275148c5f43SAlan Wright #pragma does_not_return(smbstat_fail, smbstat_usage) 276148c5f43SAlan Wright 277148c5f43SAlan Wright static char *smbstat_cpu_states[CPU_TICKS_SENTINEL] = { 278148c5f43SAlan Wright "cpu_ticks_idle", 279148c5f43SAlan Wright "cpu_ticks_user", 280148c5f43SAlan Wright "cpu_ticks_kernel" 281148c5f43SAlan Wright }; 282da6c28aaSamw 283148c5f43SAlan Wright static boolean_t smbstat_opt_a = B_FALSE; /* all */ 284148c5f43SAlan Wright static boolean_t smbstat_opt_c = B_FALSE; /* counters */ 285148c5f43SAlan Wright static boolean_t smbstat_opt_n = B_FALSE; /* by name */ 286148c5f43SAlan Wright static boolean_t smbstat_opt_u = B_FALSE; /* utilization */ 287148c5f43SAlan Wright static boolean_t smbstat_opt_t = B_FALSE; /* throughput */ 288148c5f43SAlan Wright static boolean_t smbstat_opt_r = B_FALSE; /* requests */ 289148c5f43SAlan Wright static boolean_t smbstat_opt_z = B_FALSE; /* non-zero requests */ 290da6c28aaSamw 291148c5f43SAlan Wright static uint_t smbstat_interval = 0; 292148c5f43SAlan Wright static long smbstat_nrcpus = 0; 293148c5f43SAlan Wright static kstat_ctl_t *smbstat_ksc = NULL; 294148c5f43SAlan Wright static kstat_t *smbstat_srv_ksp = NULL; 295148c5f43SAlan Wright static kstat_t *smbstat_wrk_ksp = NULL; 296148c5f43SAlan Wright static struct winsize smbstat_ws; 297148c5f43SAlan Wright static uint16_t smbstat_rows = 0; 298148c5f43SAlan Wright 299148c5f43SAlan Wright static int smbstat_snapshot_idx = 0; 300148c5f43SAlan Wright static smbstat_cpu_snapshot_t *smbstat_cpu_snapshots[SMBSTAT_SNAPSHOT_COUNT]; 301148c5f43SAlan Wright static smbstat_srv_snapshot_t smbstat_srv_snapshots[SMBSTAT_SNAPSHOT_COUNT]; 302148c5f43SAlan Wright static smbstat_wrk_snapshot_t smbstat_wrk_snapshots[SMBSTAT_SNAPSHOT_COUNT]; 303148c5f43SAlan Wright static smbstat_srv_info_t smbstat_srv_info; 304148c5f43SAlan Wright 305148c5f43SAlan Wright /* 306148c5f43SAlan Wright * main 307148c5f43SAlan Wright */ 308da6c28aaSamw int 309da6c28aaSamw main(int argc, char *argv[]) 310da6c28aaSamw { 311148c5f43SAlan Wright int c; 312148c5f43SAlan Wright 313148c5f43SAlan Wright (void) setlocale(LC_ALL, ""); 314148c5f43SAlan Wright (void) textdomain(TEXT_DOMAIN); 315da6c28aaSamw 316da6c28aaSamw if (is_system_labeled()) { 317da6c28aaSamw (void) fprintf(stderr, 318da6c28aaSamw gettext("%s: Trusted Extensions not supported.\n"), 319da6c28aaSamw argv[0]); 3208622ec45SGordon Ross return (1); 321da6c28aaSamw } 322da6c28aaSamw 323148c5f43SAlan Wright while ((c = getopt(argc, argv, "achnrtuz")) != EOF) { 324da6c28aaSamw switch (c) { 325148c5f43SAlan Wright case 'a': 326148c5f43SAlan Wright smbstat_opt_a = B_TRUE; 327da6c28aaSamw break; 328148c5f43SAlan Wright case 'n': 329148c5f43SAlan Wright smbstat_opt_n = B_TRUE; 330da6c28aaSamw break; 331148c5f43SAlan Wright case 'u': 332148c5f43SAlan Wright smbstat_opt_u = B_TRUE; 333148c5f43SAlan Wright break; 334148c5f43SAlan Wright case 'c': 335148c5f43SAlan Wright smbstat_opt_c = B_TRUE; 336148c5f43SAlan Wright break; 337148c5f43SAlan Wright case 'r': 338148c5f43SAlan Wright smbstat_opt_r = B_TRUE; 339148c5f43SAlan Wright break; 340148c5f43SAlan Wright case 't': 341148c5f43SAlan Wright smbstat_opt_t = B_TRUE; 342148c5f43SAlan Wright break; 343148c5f43SAlan Wright case 'z': 344148c5f43SAlan Wright smbstat_opt_z = B_TRUE; 345148c5f43SAlan Wright break; 346148c5f43SAlan Wright case 'h': 347148c5f43SAlan Wright smbstat_usage(stdout, 0); 348da6c28aaSamw default: 349148c5f43SAlan Wright smbstat_usage(stderr, 1); 350da6c28aaSamw } 351da6c28aaSamw } 352da6c28aaSamw 353148c5f43SAlan Wright if (!smbstat_opt_u && 354148c5f43SAlan Wright !smbstat_opt_c && 355148c5f43SAlan Wright !smbstat_opt_r && 356148c5f43SAlan Wright !smbstat_opt_t) { 357148c5f43SAlan Wright /* Default options when none is specified. */ 358148c5f43SAlan Wright smbstat_opt_u = B_TRUE; 359148c5f43SAlan Wright smbstat_opt_t = B_TRUE; 360da6c28aaSamw } 361da6c28aaSamw 362148c5f43SAlan Wright if (optind < argc) { 363148c5f43SAlan Wright smbstat_interval = 364148c5f43SAlan Wright smbstat_strtoi(argv[optind], "invalid count"); 365148c5f43SAlan Wright optind++; 366da6c28aaSamw } 367da6c28aaSamw 368148c5f43SAlan Wright if ((argc - optind) > 1) 369148c5f43SAlan Wright smbstat_usage(stderr, 1); 370148c5f43SAlan Wright 371148c5f43SAlan Wright (void) atexit(smbstat_fini); 372148c5f43SAlan Wright smbstat_init(); 373148c5f43SAlan Wright for (;;) { 374148c5f43SAlan Wright smbstat_kstat_snapshot(); 375148c5f43SAlan Wright smbstat_kstat_process(); 376148c5f43SAlan Wright smbstat_kstat_print(); 377148c5f43SAlan Wright if (smbstat_interval == 0) 378148c5f43SAlan Wright break; 379148c5f43SAlan Wright (void) sleep(smbstat_interval); 380148c5f43SAlan Wright smbstat_snapshot_inc_idx(); 381148c5f43SAlan Wright } 382da6c28aaSamw return (0); 383da6c28aaSamw } 384da6c28aaSamw 385148c5f43SAlan Wright /* 386148c5f43SAlan Wright * smbstat_init 387148c5f43SAlan Wright * 388148c5f43SAlan Wright * Global initialization. 389148c5f43SAlan Wright */ 390148c5f43SAlan Wright static void 391148c5f43SAlan Wright smbstat_init(void) 392148c5f43SAlan Wright { 393148c5f43SAlan Wright if ((smbstat_ksc = kstat_open()) == NULL) 394148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_open(): can't open /dev/kstat")); 395da6c28aaSamw 396148c5f43SAlan Wright smbstat_cpu_init(); 397148c5f43SAlan Wright smbstat_srv_init(); 398148c5f43SAlan Wright smbstat_wrk_init(); 399148c5f43SAlan Wright smbstat_req_order(); 400148c5f43SAlan Wright } 401148c5f43SAlan Wright 402148c5f43SAlan Wright /* 403148c5f43SAlan Wright * smbstat_fini 404148c5f43SAlan Wright * 405148c5f43SAlan Wright * Releases the resources smbstat_init() allocated. 406148c5f43SAlan Wright */ 407148c5f43SAlan Wright static void 408148c5f43SAlan Wright smbstat_fini(void) 409da6c28aaSamw { 410148c5f43SAlan Wright smbstat_wrk_fini(); 411148c5f43SAlan Wright smbstat_srv_fini(); 412148c5f43SAlan Wright smbstat_cpu_fini(); 413148c5f43SAlan Wright (void) kstat_close(smbstat_ksc); 414da6c28aaSamw } 415da6c28aaSamw 416148c5f43SAlan Wright /* 417148c5f43SAlan Wright * smbstat_kstat_snapshot 418148c5f43SAlan Wright * 419148c5f43SAlan Wright * Takes a snapshot of the data. 420148c5f43SAlan Wright */ 421148c5f43SAlan Wright static void 422148c5f43SAlan Wright smbstat_kstat_snapshot(void) 423148c5f43SAlan Wright { 424148c5f43SAlan Wright smbstat_cpu_snapshot(); 425148c5f43SAlan Wright smbstat_srv_snapshot(); 426148c5f43SAlan Wright smbstat_wrk_snapshot(); 427148c5f43SAlan Wright } 428148c5f43SAlan Wright 429148c5f43SAlan Wright /* 430148c5f43SAlan Wright * smbstat_kstat_process 431148c5f43SAlan Wright */ 432148c5f43SAlan Wright static void 433148c5f43SAlan Wright smbstat_kstat_process(void) 434148c5f43SAlan Wright { 435148c5f43SAlan Wright smbstat_cpu_process(); 436148c5f43SAlan Wright smbstat_srv_process(); 437148c5f43SAlan Wright smbstat_wrk_process(); 438148c5f43SAlan Wright } 439148c5f43SAlan Wright 440148c5f43SAlan Wright /* 441148c5f43SAlan Wright * smbstat_kstat_print 442148c5f43SAlan Wright * 443148c5f43SAlan Wright * Print the data processed. 444148c5f43SAlan Wright */ 445148c5f43SAlan Wright static void 446148c5f43SAlan Wright smbstat_kstat_print(void) 447148c5f43SAlan Wright { 448148c5f43SAlan Wright smbstat_termio_init(); 449148c5f43SAlan Wright smbstat_print_counters(); 450148c5f43SAlan Wright smbstat_print_throughput(); 451148c5f43SAlan Wright smbstat_print_utilization(); 452148c5f43SAlan Wright smbstat_print_requests(); 453a90cf9f2SGordon Ross (void) fflush(stdout); 454148c5f43SAlan Wright } 455148c5f43SAlan Wright 456148c5f43SAlan Wright /* 457148c5f43SAlan Wright * smbstat_print_counters 458148c5f43SAlan Wright * 459148c5f43SAlan Wright * Displays the SMB server counters (session, users...). 460148c5f43SAlan Wright */ 461148c5f43SAlan Wright static void 462148c5f43SAlan Wright smbstat_print_counters(void) 463148c5f43SAlan Wright { 464148c5f43SAlan Wright if (!smbstat_opt_c) 465148c5f43SAlan Wright return; 466148c5f43SAlan Wright 467148c5f43SAlan Wright if (smbstat_opt_u || smbstat_opt_r || smbstat_opt_t || 468148c5f43SAlan Wright (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) { 469148c5f43SAlan Wright (void) printf(SMBSRV_COUNTERS_BANNER); 470148c5f43SAlan Wright smbstat_rows = 1; 471148c5f43SAlan Wright } 472148c5f43SAlan Wright 473148c5f43SAlan Wright (void) printf(SMBSRV_COUNTERS_FORMAT, 474148c5f43SAlan Wright smbstat_srv_info.si_nbt_sess, 475148c5f43SAlan Wright smbstat_srv_info.si_tcp_sess, 476148c5f43SAlan Wright smbstat_srv_info.si_users, 477148c5f43SAlan Wright smbstat_srv_info.si_trees, 478148c5f43SAlan Wright smbstat_srv_info.si_files, 479148c5f43SAlan Wright smbstat_srv_info.si_pipes); 480148c5f43SAlan Wright 481148c5f43SAlan Wright ++smbstat_rows; 482148c5f43SAlan Wright } 483148c5f43SAlan Wright /* 484148c5f43SAlan Wright * smbstat_print_throughput 485148c5f43SAlan Wright * 486148c5f43SAlan Wright * Formats the SMB server throughput output. 487148c5f43SAlan Wright */ 488148c5f43SAlan Wright static void 489148c5f43SAlan Wright smbstat_print_throughput(void) 490148c5f43SAlan Wright { 491148c5f43SAlan Wright if (!smbstat_opt_t) 492148c5f43SAlan Wright return; 493148c5f43SAlan Wright 494148c5f43SAlan Wright if (smbstat_opt_u || smbstat_opt_r || smbstat_opt_c || 495148c5f43SAlan Wright (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) { 496148c5f43SAlan Wright (void) printf(SMBSRV_THROUGHPUT_BANNER); 497148c5f43SAlan Wright smbstat_rows = 1; 498148c5f43SAlan Wright } 499148c5f43SAlan Wright (void) printf(SMBSRV_THROUGHPUT_FORMAT, 500148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rbs), 501148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_tbs), 502148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rqs), 503148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rds), 504148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_wrs)); 505148c5f43SAlan Wright 506148c5f43SAlan Wright ++smbstat_rows; 507148c5f43SAlan Wright } 508148c5f43SAlan Wright 509148c5f43SAlan Wright /* 510148c5f43SAlan Wright * smbstat_print_utilization 511148c5f43SAlan Wright */ 512148c5f43SAlan Wright static void 513148c5f43SAlan Wright smbstat_print_utilization(void) 514da6c28aaSamw { 515148c5f43SAlan Wright char *sat; 516148c5f43SAlan Wright if (!smbstat_opt_u) 517148c5f43SAlan Wright return; 518148c5f43SAlan Wright 519148c5f43SAlan Wright if (smbstat_opt_t || smbstat_opt_r || smbstat_opt_c || 520148c5f43SAlan Wright (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) { 521148c5f43SAlan Wright (void) printf(SMBSRV_UTILIZATION_BANNER); 522148c5f43SAlan Wright smbstat_rows = 1; 523148c5f43SAlan Wright } 524148c5f43SAlan Wright 525148c5f43SAlan Wright if (smbstat_srv_info.si_sat) 526148c5f43SAlan Wright sat = "yes"; 527148c5f43SAlan Wright else 528148c5f43SAlan Wright sat = "no "; 529148c5f43SAlan Wright 530148c5f43SAlan Wright (void) printf(SMBSRV_UTILIZATION_FORMAT, 531148c5f43SAlan Wright smbstat_srv_info.si_avw, 532148c5f43SAlan Wright smbstat_srv_info.si_avr, 533148c5f43SAlan Wright smbstat_srv_info.si_wserv, 534148c5f43SAlan Wright smbstat_srv_info.si_rserv, 535148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_wpct), 536148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rpct), 537148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_upct), 538148c5f43SAlan Wright sat, 539148c5f43SAlan Wright smbstat_srv_info.si_ticks[CPU_TICKS_USER], 540148c5f43SAlan Wright smbstat_srv_info.si_ticks[CPU_TICKS_KERNEL], 541148c5f43SAlan Wright smbstat_srv_info.si_ticks[CPU_TICKS_IDLE]); 542148c5f43SAlan Wright 543148c5f43SAlan Wright ++smbstat_rows; 544da6c28aaSamw } 545da6c28aaSamw 546148c5f43SAlan Wright /* 547148c5f43SAlan Wright * smbstat_print_requests 548148c5f43SAlan Wright */ 549da6c28aaSamw static void 550148c5f43SAlan Wright smbstat_print_requests(void) 551da6c28aaSamw { 552148c5f43SAlan Wright smbstat_req_info_t *prq; 553148c5f43SAlan Wright int i; 554da6c28aaSamw 555148c5f43SAlan Wright if (!smbstat_opt_r) 556da6c28aaSamw return; 557da6c28aaSamw 558148c5f43SAlan Wright (void) printf(SMBSRV_REQUESTS_BANNER, " "); 5596537f381Sas 560a90cf9f2SGordon Ross prq = smbstat_srv_info.si_reqs1; 561148c5f43SAlan Wright for (i = 0; i < SMB_COM_NUM; i++) { 562148c5f43SAlan Wright if (!smbstat_opt_a && 563148c5f43SAlan Wright strncmp(prq[i].ri_name, "Invalid", sizeof ("Invalid")) == 0) 564148c5f43SAlan Wright continue; 5656537f381Sas 566148c5f43SAlan Wright if (!smbstat_opt_z || (prq[i].ri_pct != 0)) { 567148c5f43SAlan Wright (void) printf(SMBSRV_REQUESTS_FORMAT, 568148c5f43SAlan Wright prq[i].ri_name, 569148c5f43SAlan Wright prq[i].ri_opcode, 570148c5f43SAlan Wright smbstat_zero(prq[i].ri_pct), 571148c5f43SAlan Wright smbstat_zero(prq[i].ri_rbs), 572148c5f43SAlan Wright smbstat_zero(prq[i].ri_tbs), 573148c5f43SAlan Wright smbstat_zero(prq[i].ri_rqs), 574148c5f43SAlan Wright prq[i].ri_mean, 575148c5f43SAlan Wright prq[i].ri_stddev); 5766537f381Sas } 577148c5f43SAlan Wright } 578a90cf9f2SGordon Ross 579a90cf9f2SGordon Ross prq = smbstat_srv_info.si_reqs2; 580a90cf9f2SGordon Ross for (i = 0; i < SMB2__NCMDS; i++) { 581a90cf9f2SGordon Ross if (!smbstat_opt_a && i == SMB2_INVALID_CMD) 582a90cf9f2SGordon Ross continue; 583a90cf9f2SGordon Ross 584a90cf9f2SGordon Ross if (!smbstat_opt_z || (prq[i].ri_pct != 0)) { 585a90cf9f2SGordon Ross (void) printf(SMBSRV_REQUESTS_FORMAT, 586a90cf9f2SGordon Ross prq[i].ri_name, 587a90cf9f2SGordon Ross prq[i].ri_opcode, 588a90cf9f2SGordon Ross smbstat_zero(prq[i].ri_pct), 589a90cf9f2SGordon Ross smbstat_zero(prq[i].ri_rbs), 590a90cf9f2SGordon Ross smbstat_zero(prq[i].ri_tbs), 591a90cf9f2SGordon Ross smbstat_zero(prq[i].ri_rqs), 592a90cf9f2SGordon Ross prq[i].ri_mean, 593a90cf9f2SGordon Ross prq[i].ri_stddev); 594a90cf9f2SGordon Ross } 595a90cf9f2SGordon Ross } 596148c5f43SAlan Wright } 597148c5f43SAlan Wright 598148c5f43SAlan Wright /* 599148c5f43SAlan Wright * smbstat_cpu_init 600148c5f43SAlan Wright */ 601148c5f43SAlan Wright static void 602148c5f43SAlan Wright smbstat_cpu_init(void) 603148c5f43SAlan Wright { 604148c5f43SAlan Wright size_t size; 605148c5f43SAlan Wright int i; 606148c5f43SAlan Wright 607148c5f43SAlan Wright smbstat_nrcpus = sysconf(_SC_CPUID_MAX) + 1; 608148c5f43SAlan Wright size = smbstat_nrcpus * sizeof (smbstat_cpu_snapshot_t); 609148c5f43SAlan Wright 610148c5f43SAlan Wright for (i = 0; i < SMBSTAT_SNAPSHOT_COUNT; i++) 611148c5f43SAlan Wright smbstat_cpu_snapshots[i] = smbstat_zalloc(size); 612148c5f43SAlan Wright } 613148c5f43SAlan Wright 614148c5f43SAlan Wright /* 615148c5f43SAlan Wright * smbstat_cpu_fini 616148c5f43SAlan Wright */ 617148c5f43SAlan Wright static void 618148c5f43SAlan Wright smbstat_cpu_fini(void) 619148c5f43SAlan Wright { 620148c5f43SAlan Wright size_t size; 621148c5f43SAlan Wright int i; 622148c5f43SAlan Wright 623148c5f43SAlan Wright size = smbstat_nrcpus * sizeof (smbstat_cpu_snapshot_t); 624148c5f43SAlan Wright 625148c5f43SAlan Wright for (i = 0; i < SMBSTAT_SNAPSHOT_COUNT; i++) 626148c5f43SAlan Wright smbstat_free(smbstat_cpu_snapshots[i], size); 627148c5f43SAlan Wright } 628148c5f43SAlan Wright 629148c5f43SAlan Wright /* 630148c5f43SAlan Wright * smbstat_cpu_current_snapshot 631148c5f43SAlan Wright */ 632148c5f43SAlan Wright static smbstat_cpu_snapshot_t * 633148c5f43SAlan Wright smbstat_cpu_current_snapshot(void) 634148c5f43SAlan Wright { 635148c5f43SAlan Wright return (smbstat_cpu_snapshots[smbstat_snapshot_idx]); 636148c5f43SAlan Wright } 637148c5f43SAlan Wright 638148c5f43SAlan Wright /* 639148c5f43SAlan Wright * smbstat_cpu_previous_snapshot 640148c5f43SAlan Wright */ 641148c5f43SAlan Wright static smbstat_cpu_snapshot_t * 642148c5f43SAlan Wright smbstat_cpu_previous_snapshot(void) 643148c5f43SAlan Wright { 644148c5f43SAlan Wright int idx; 645148c5f43SAlan Wright 646148c5f43SAlan Wright idx = (smbstat_snapshot_idx - 1) & SMBSTAT_SNAPSHOT_MASK; 647148c5f43SAlan Wright return (smbstat_cpu_snapshots[idx]); 648148c5f43SAlan Wright } 649148c5f43SAlan Wright 650148c5f43SAlan Wright /* 651148c5f43SAlan Wright * smbstat_cpu_snapshot 652148c5f43SAlan Wright */ 653148c5f43SAlan Wright static void 654148c5f43SAlan Wright smbstat_cpu_snapshot(void) 655148c5f43SAlan Wright { 656148c5f43SAlan Wright kstat_t *ksp; 657148c5f43SAlan Wright kstat_named_t *ksn; 658148c5f43SAlan Wright smbstat_cpu_snapshot_t *curr; 659148c5f43SAlan Wright long i; 660148c5f43SAlan Wright int j; 661148c5f43SAlan Wright 662148c5f43SAlan Wright curr = smbstat_cpu_current_snapshot(); 663148c5f43SAlan Wright 664148c5f43SAlan Wright for (i = 0; i < smbstat_nrcpus; i++, curr++) { 665148c5f43SAlan Wright curr->cs_id = SMBSTAT_ID_NO_CPU; 666148c5f43SAlan Wright curr->cs_state = p_online(i, P_STATUS); 667148c5f43SAlan Wright /* If no valid CPU is present, move on to the next one */ 668148c5f43SAlan Wright if (curr->cs_state == -1) 669148c5f43SAlan Wright continue; 670148c5f43SAlan Wright 671148c5f43SAlan Wright curr->cs_id = i; 672148c5f43SAlan Wright 673148c5f43SAlan Wright ksp = kstat_lookup(smbstat_ksc, "cpu", i, "sys"); 674148c5f43SAlan Wright if (ksp == NULL) 675148c5f43SAlan Wright smbstat_fail(1, 676148c5f43SAlan Wright gettext("kstat_lookup('cpu sys %d') failed"), i); 677148c5f43SAlan Wright 678148c5f43SAlan Wright if (kstat_read(smbstat_ksc, ksp, NULL) == -1) 679148c5f43SAlan Wright smbstat_fail(1, 680148c5f43SAlan Wright gettext("kstat_read('cpu sys %d') failed"), i); 681148c5f43SAlan Wright 682148c5f43SAlan Wright for (j = 0; j < CPU_TICKS_SENTINEL; j++) { 683148c5f43SAlan Wright ksn = kstat_data_lookup(ksp, smbstat_cpu_states[j]); 684148c5f43SAlan Wright if (ksn == NULL) 685148c5f43SAlan Wright smbstat_fail(1, 686148c5f43SAlan Wright gettext("kstat_data_lookup('%s') failed"), 687148c5f43SAlan Wright smbstat_cpu_states[j]); 688148c5f43SAlan Wright curr->cs_ticks[j] = ksn->value.ui64; 6896537f381Sas } 6906537f381Sas } 691da6c28aaSamw } 692da6c28aaSamw 693148c5f43SAlan Wright /* 694148c5f43SAlan Wright * smbstat_cpu_process 695148c5f43SAlan Wright */ 696da6c28aaSamw static void 697148c5f43SAlan Wright smbstat_cpu_process(void) 698da6c28aaSamw { 699148c5f43SAlan Wright smbstat_cpu_snapshot_t *curr, *prev; 700148c5f43SAlan Wright double total_ticks; 701148c5f43SAlan Wright double agg_ticks[CPU_TICKS_SENTINEL]; 702148c5f43SAlan Wright int i, j; 703da6c28aaSamw 704148c5f43SAlan Wright curr = smbstat_cpu_current_snapshot(); 705148c5f43SAlan Wright prev = smbstat_cpu_previous_snapshot(); 706148c5f43SAlan Wright bzero(agg_ticks, sizeof (agg_ticks)); 707148c5f43SAlan Wright total_ticks = 0; 708da6c28aaSamw 709148c5f43SAlan Wright for (i = 0; i < smbstat_nrcpus; i++, curr++, prev++) { 710148c5f43SAlan Wright for (j = 0; j < CPU_TICKS_SENTINEL; j++) { 711148c5f43SAlan Wright agg_ticks[j] += smbstat_sub_64(curr->cs_ticks[j], 712148c5f43SAlan Wright prev->cs_ticks[j]); 713148c5f43SAlan Wright total_ticks += smbstat_sub_64(curr->cs_ticks[j], 714148c5f43SAlan Wright prev->cs_ticks[j]); 715148c5f43SAlan Wright } 716148c5f43SAlan Wright } 717148c5f43SAlan Wright 718148c5f43SAlan Wright for (j = 0; j < CPU_TICKS_SENTINEL; j++) 719148c5f43SAlan Wright smbstat_srv_info.si_ticks[j] = 720148c5f43SAlan Wright (agg_ticks[j] * 100.0) / total_ticks; 721da6c28aaSamw } 722da6c28aaSamw 723148c5f43SAlan Wright /* 724148c5f43SAlan Wright * smbstat_wrk_init 725148c5f43SAlan Wright */ 726da6c28aaSamw static void 727148c5f43SAlan Wright smbstat_wrk_init(void) 728da6c28aaSamw { 729148c5f43SAlan Wright smbstat_wrk_ksp = 730148c5f43SAlan Wright kstat_lookup(smbstat_ksc, "unix", -1, SMBSRV_KSTAT_WORKERS); 731148c5f43SAlan Wright if (smbstat_wrk_ksp == NULL) 732148c5f43SAlan Wright smbstat_fail(1, 733148c5f43SAlan Wright gettext("cannot retrieve smbsrv workers kstat\n")); 734148c5f43SAlan Wright } 7356537f381Sas 736148c5f43SAlan Wright static void 737148c5f43SAlan Wright smbstat_wrk_fini(void) 738148c5f43SAlan Wright { 739148c5f43SAlan Wright smbstat_wrk_ksp = NULL; 740148c5f43SAlan Wright } 7416537f381Sas 742148c5f43SAlan Wright /* 743148c5f43SAlan Wright * smbstat_wrk_snapshot 744148c5f43SAlan Wright */ 745148c5f43SAlan Wright static void 746148c5f43SAlan Wright smbstat_wrk_snapshot(void) 747148c5f43SAlan Wright { 748148c5f43SAlan Wright smbstat_wrk_snapshot_t *curr; 749148c5f43SAlan Wright kstat_named_t *kn; 750da6c28aaSamw 751148c5f43SAlan Wright curr = smbstat_wrk_current_snapshot(); 752da6c28aaSamw 753148c5f43SAlan Wright if (kstat_read(smbstat_ksc, smbstat_wrk_ksp, NULL) == -1) 754148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"), 755148c5f43SAlan Wright smbstat_wrk_ksp->ks_name); 756148c5f43SAlan Wright 757148c5f43SAlan Wright kn = kstat_data_lookup(smbstat_wrk_ksp, "maxthreads"); 758148c5f43SAlan Wright if ((kn == NULL) || (kn->data_type != KSTAT_DATA_UINT64)) 759148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"), 760148c5f43SAlan Wright "maxthreads"); 761148c5f43SAlan Wright curr->ws_maxthreads = kn->value.ui64; 762148c5f43SAlan Wright 763148c5f43SAlan Wright kn = kstat_data_lookup(smbstat_wrk_ksp, "bnalloc"); 764148c5f43SAlan Wright if ((kn == NULL) || (kn->data_type != KSTAT_DATA_UINT64)) 765148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"), 766148c5f43SAlan Wright "bnalloc"); 767148c5f43SAlan Wright curr->ws_bnalloc = kn->value.ui64; 768da6c28aaSamw } 769da6c28aaSamw 770148c5f43SAlan Wright /* 771148c5f43SAlan Wright * smbstat_wrk_process 772148c5f43SAlan Wright */ 7736537f381Sas static void 774148c5f43SAlan Wright smbstat_wrk_process(void) 7756537f381Sas { 776148c5f43SAlan Wright smbstat_wrk_snapshot_t *curr; 777148c5f43SAlan Wright 778148c5f43SAlan Wright curr = smbstat_wrk_current_snapshot(); 779148c5f43SAlan Wright 780a90cf9f2SGordon Ross if (curr->ws_bnalloc >= curr->ws_maxthreads) 781148c5f43SAlan Wright smbstat_srv_info.si_sat = B_TRUE; 782148c5f43SAlan Wright else 783148c5f43SAlan Wright smbstat_srv_info.si_sat = B_FALSE; 7846537f381Sas } 7856537f381Sas 786148c5f43SAlan Wright /* 787148c5f43SAlan Wright * smbstat_wrk_current_snapshot 788148c5f43SAlan Wright */ 789148c5f43SAlan Wright static smbstat_wrk_snapshot_t * 790148c5f43SAlan Wright smbstat_wrk_current_snapshot(void) 791148c5f43SAlan Wright { 792148c5f43SAlan Wright return (&smbstat_wrk_snapshots[smbstat_snapshot_idx]); 793148c5f43SAlan Wright } 794148c5f43SAlan Wright 795148c5f43SAlan Wright /* 796148c5f43SAlan Wright * smbstat_srv_init 797148c5f43SAlan Wright */ 798148c5f43SAlan Wright static void 799148c5f43SAlan Wright smbstat_srv_init(void) 800148c5f43SAlan Wright { 801148c5f43SAlan Wright smbstat_srv_ksp = kstat_lookup(smbstat_ksc, SMBSRV_KSTAT_MODULE, 802148c5f43SAlan Wright getzoneid(), SMBSRV_KSTAT_STATISTICS); 803148c5f43SAlan Wright if (smbstat_srv_ksp == NULL) 804148c5f43SAlan Wright smbstat_fail(1, gettext("cannot retrieve smbsrv kstat\n")); 805148c5f43SAlan Wright } 806148c5f43SAlan Wright 807148c5f43SAlan Wright /* 808148c5f43SAlan Wright * smbstat_srv_fini 809148c5f43SAlan Wright */ 810148c5f43SAlan Wright static void 811148c5f43SAlan Wright smbstat_srv_fini(void) 812148c5f43SAlan Wright { 813148c5f43SAlan Wright smbstat_srv_ksp = NULL; 814148c5f43SAlan Wright } 815148c5f43SAlan Wright 816148c5f43SAlan Wright /* 817148c5f43SAlan Wright * smbstat_srv_snapshot 818148c5f43SAlan Wright * 819148c5f43SAlan Wright * Take a snapshot of the smbsrv module statistics. 820148c5f43SAlan Wright */ 821148c5f43SAlan Wright static void 822148c5f43SAlan Wright smbstat_srv_snapshot(void) 823148c5f43SAlan Wright { 824148c5f43SAlan Wright smbstat_srv_snapshot_t *curr; 825148c5f43SAlan Wright 826148c5f43SAlan Wright curr = smbstat_srv_current_snapshot(); 827148c5f43SAlan Wright 828148c5f43SAlan Wright if ((kstat_read(smbstat_ksc, smbstat_srv_ksp, NULL) == -1) || 829148c5f43SAlan Wright (smbstat_srv_ksp->ks_data_size != sizeof (curr->ss_data))) 830148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"), 831148c5f43SAlan Wright smbstat_srv_ksp->ks_name); 832148c5f43SAlan Wright 833148c5f43SAlan Wright curr->ss_snaptime = smbstat_srv_ksp->ks_snaptime; 834148c5f43SAlan Wright bcopy(smbstat_srv_ksp->ks_data, &curr->ss_data, sizeof (curr->ss_data)); 835148c5f43SAlan Wright } 836148c5f43SAlan Wright 837148c5f43SAlan Wright /* 838148c5f43SAlan Wright * smbstat_srv_process 839148c5f43SAlan Wright * 840148c5f43SAlan Wright * Processes the snapshot data. 841148c5f43SAlan Wright */ 842148c5f43SAlan Wright static void 843148c5f43SAlan Wright smbstat_srv_process(void) 844148c5f43SAlan Wright { 845148c5f43SAlan Wright smbstat_srv_snapshot_t *curr, *prev; 846148c5f43SAlan Wright 847148c5f43SAlan Wright curr = smbstat_srv_current_snapshot(); 848148c5f43SAlan Wright prev = smbstat_srv_previous_snapshot(); 849148c5f43SAlan Wright 850148c5f43SAlan Wright if (prev->ss_snaptime == 0) 851148c5f43SAlan Wright smbstat_srv_info.si_hretime = 852148c5f43SAlan Wright smbstat_hrtime_delta(curr->ss_data.ks_start_time, 853148c5f43SAlan Wright curr->ss_snaptime); 854148c5f43SAlan Wright else 855148c5f43SAlan Wright smbstat_srv_info.si_hretime = 856148c5f43SAlan Wright smbstat_hrtime_delta(prev->ss_snaptime, curr->ss_snaptime); 857148c5f43SAlan Wright 858148c5f43SAlan Wright smbstat_srv_info.si_etime = smbstat_srv_info.si_hretime / NANOSEC; 859148c5f43SAlan Wright smbstat_srv_info.si_total_nreqs = 860148c5f43SAlan Wright smbstat_sub_64(curr->ss_data.ks_nreq, prev->ss_data.ks_nreq); 861148c5f43SAlan Wright 862148c5f43SAlan Wright if (smbstat_opt_c) 863148c5f43SAlan Wright smbstat_srv_process_counters(curr); 864148c5f43SAlan Wright if (smbstat_opt_t) 865148c5f43SAlan Wright smbstat_srv_process_throughput(curr, prev); 866148c5f43SAlan Wright if (smbstat_opt_u) 867148c5f43SAlan Wright smbstat_srv_process_utilization(curr, prev); 868148c5f43SAlan Wright if (smbstat_opt_r) 869148c5f43SAlan Wright smbstat_srv_process_requests(curr, prev); 870148c5f43SAlan Wright } 871148c5f43SAlan Wright 872148c5f43SAlan Wright /* 873148c5f43SAlan Wright * smbstat_srv_process_counters 874148c5f43SAlan Wright */ 875148c5f43SAlan Wright static void 876148c5f43SAlan Wright smbstat_srv_process_counters(smbstat_srv_snapshot_t *curr) 877148c5f43SAlan Wright { 878148c5f43SAlan Wright smbstat_srv_info.si_nbt_sess = curr->ss_data.ks_nbt_sess; 879148c5f43SAlan Wright smbstat_srv_info.si_tcp_sess = curr->ss_data.ks_tcp_sess; 880148c5f43SAlan Wright smbstat_srv_info.si_users = curr->ss_data.ks_users; 881148c5f43SAlan Wright smbstat_srv_info.si_trees = curr->ss_data.ks_trees; 882148c5f43SAlan Wright smbstat_srv_info.si_files = curr->ss_data.ks_files; 883148c5f43SAlan Wright smbstat_srv_info.si_pipes = curr->ss_data.ks_pipes; 884148c5f43SAlan Wright } 885148c5f43SAlan Wright 886148c5f43SAlan Wright /* 887148c5f43SAlan Wright * smbstat_srv_process_throughput 888148c5f43SAlan Wright * 889148c5f43SAlan Wright * Processes the data relative to the throughput of the smbsrv module and 890148c5f43SAlan Wright * stores the results in the structure smbstat_srv_info. 891148c5f43SAlan Wright */ 892148c5f43SAlan Wright static void 893148c5f43SAlan Wright smbstat_srv_process_throughput( 894148c5f43SAlan Wright smbstat_srv_snapshot_t *curr, 895148c5f43SAlan Wright smbstat_srv_snapshot_t *prev) 896148c5f43SAlan Wright { 897148c5f43SAlan Wright smbstat_srv_info.si_tbs = 898148c5f43SAlan Wright smbstat_sub_64(curr->ss_data.ks_txb, prev->ss_data.ks_txb); 899148c5f43SAlan Wright smbstat_srv_info.si_tbs /= smbstat_srv_info.si_etime; 900148c5f43SAlan Wright smbstat_srv_info.si_rbs = 901148c5f43SAlan Wright smbstat_sub_64(curr->ss_data.ks_rxb, prev->ss_data.ks_rxb); 902148c5f43SAlan Wright smbstat_srv_info.si_rbs /= smbstat_srv_info.si_etime; 903148c5f43SAlan Wright smbstat_srv_info.si_rqs = smbstat_srv_info.si_total_nreqs; 904148c5f43SAlan Wright smbstat_srv_info.si_rqs /= smbstat_srv_info.si_etime; 905148c5f43SAlan Wright 906148c5f43SAlan Wright smbstat_srv_info.si_rds = smbstat_sub_64( 907a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_READ].kr_nreq, 908a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_READ].kr_nreq); 909a90cf9f2SGordon Ross smbstat_srv_info.si_rds += smbstat_sub_64( 910a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_LOCK_AND_READ].kr_nreq, 911a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_LOCK_AND_READ].kr_nreq); 912148c5f43SAlan Wright smbstat_srv_info.si_rds += smbstat_sub_64( 913a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_READ_RAW].kr_nreq, 914a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_READ_RAW].kr_nreq); 915148c5f43SAlan Wright smbstat_srv_info.si_rds += smbstat_sub_64( 916a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_READ_ANDX].kr_nreq, 917a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_READ_ANDX].kr_nreq); 918148c5f43SAlan Wright smbstat_srv_info.si_rds += smbstat_sub_64( 919a90cf9f2SGordon Ross curr->ss_data.ks_reqs2[SMB2_READ].kr_nreq, 920a90cf9f2SGordon Ross prev->ss_data.ks_reqs2[SMB2_READ].kr_nreq); 921148c5f43SAlan Wright smbstat_srv_info.si_rds /= smbstat_srv_info.si_etime; 922148c5f43SAlan Wright 923148c5f43SAlan Wright smbstat_srv_info.si_wrs = smbstat_sub_64( 924a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE].kr_nreq, 925a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE].kr_nreq); 926148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64( 927a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE_AND_UNLOCK].kr_nreq, 928a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE_AND_UNLOCK].kr_nreq); 929148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64( 930a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE_RAW].kr_nreq, 931a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE_RAW].kr_nreq); 932148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64( 933a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE_AND_CLOSE].kr_nreq, 934a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE_AND_CLOSE].kr_nreq); 935148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64( 936a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE_ANDX].kr_nreq, 937a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE_ANDX].kr_nreq); 938a90cf9f2SGordon Ross smbstat_srv_info.si_wrs += smbstat_sub_64( 939a90cf9f2SGordon Ross curr->ss_data.ks_reqs2[SMB2_WRITE].kr_nreq, 940a90cf9f2SGordon Ross prev->ss_data.ks_reqs2[SMB2_WRITE].kr_nreq); 941148c5f43SAlan Wright smbstat_srv_info.si_wrs /= smbstat_srv_info.si_etime; 942148c5f43SAlan Wright } 943148c5f43SAlan Wright 944148c5f43SAlan Wright /* 945148c5f43SAlan Wright * smbstat_srv_process_utilization 946148c5f43SAlan Wright * 947148c5f43SAlan Wright * Processes the data relative to the utilization of the smbsrv module and 948148c5f43SAlan Wright * stores the results in the structure smbstat_srv_info. 949148c5f43SAlan Wright */ 950148c5f43SAlan Wright static void 951148c5f43SAlan Wright smbstat_srv_process_utilization( 952148c5f43SAlan Wright smbstat_srv_snapshot_t *curr, 953148c5f43SAlan Wright smbstat_srv_snapshot_t *prev) 954148c5f43SAlan Wright { 955148c5f43SAlan Wright double tw_delta, tr_delta; 956148c5f43SAlan Wright double w_delta, r_delta; 957148c5f43SAlan Wright double tps, rqs; 958148c5f43SAlan Wright 959148c5f43SAlan Wright w_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_wlentime, 960148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_wlentime); 961148c5f43SAlan Wright r_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_rlentime, 962148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_rlentime); 963148c5f43SAlan Wright tw_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_wtime, 964148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_wtime); 965148c5f43SAlan Wright tr_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_rtime, 966148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_rtime); 967148c5f43SAlan Wright rqs = smbstat_srv_info.si_total_nreqs / smbstat_srv_info.si_etime; 968148c5f43SAlan Wright 969148c5f43SAlan Wright /* Average number of requests waiting */ 970148c5f43SAlan Wright if (w_delta != 0) 971148c5f43SAlan Wright smbstat_srv_info.si_avw = w_delta / smbstat_srv_info.si_hretime; 972148c5f43SAlan Wright else 973148c5f43SAlan Wright smbstat_srv_info.si_avw = 0.0; 974148c5f43SAlan Wright 975148c5f43SAlan Wright /* Average number of request running */ 976148c5f43SAlan Wright if (r_delta != 0) 977148c5f43SAlan Wright smbstat_srv_info.si_avr = r_delta / smbstat_srv_info.si_hretime; 978148c5f43SAlan Wright else 979148c5f43SAlan Wright smbstat_srv_info.si_avr = 0.0; 980148c5f43SAlan Wright 981148c5f43SAlan Wright /* Utilization */ 982148c5f43SAlan Wright smbstat_srv_info.si_upct = 983148c5f43SAlan Wright (smbstat_srv_info.si_avr / curr->ss_data.ks_maxreqs) * 100; 984148c5f43SAlan Wright 985148c5f43SAlan Wright /* Average wait service time in milliseconds */ 986148c5f43SAlan Wright smbstat_srv_info.si_rserv = 0.0; 987148c5f43SAlan Wright smbstat_srv_info.si_wserv = 0.0; 988148c5f43SAlan Wright if (rqs > 0.0 && 989148c5f43SAlan Wright (smbstat_srv_info.si_avw != 0.0 || 990148c5f43SAlan Wright smbstat_srv_info.si_avr != 0.0)) { 991148c5f43SAlan Wright tps = 1 / rqs; 992148c5f43SAlan Wright if (smbstat_srv_info.si_avw != 0.0) 993148c5f43SAlan Wright smbstat_srv_info.si_wserv = 994148c5f43SAlan Wright smbstat_srv_info.si_avw * tps; 995148c5f43SAlan Wright if (smbstat_srv_info.si_avr != 0.0) 996148c5f43SAlan Wright smbstat_srv_info.si_rserv = 997148c5f43SAlan Wright smbstat_srv_info.si_avr * tps; 998148c5f43SAlan Wright } 999148c5f43SAlan Wright 1000148c5f43SAlan Wright /* % of time there is a transaction waiting for service */ 1001148c5f43SAlan Wright if (tw_delta != 0) { 1002148c5f43SAlan Wright smbstat_srv_info.si_wpct = tw_delta; 1003148c5f43SAlan Wright smbstat_srv_info.si_wpct /= smbstat_srv_info.si_hretime; 1004148c5f43SAlan Wright smbstat_srv_info.si_wpct *= 100.0; 1005148c5f43SAlan Wright } else { 1006148c5f43SAlan Wright smbstat_srv_info.si_wpct = 0.0; 1007148c5f43SAlan Wright } 1008148c5f43SAlan Wright 1009148c5f43SAlan Wright /* % of time there is a transaction running */ 1010148c5f43SAlan Wright if (tr_delta != 0) { 1011148c5f43SAlan Wright smbstat_srv_info.si_rpct = tr_delta; 1012148c5f43SAlan Wright smbstat_srv_info.si_rpct /= smbstat_srv_info.si_hretime; 1013148c5f43SAlan Wright smbstat_srv_info.si_rpct *= 100.0; 1014148c5f43SAlan Wright } else { 1015148c5f43SAlan Wright smbstat_srv_info.si_rpct = 0.0; 1016da6c28aaSamw } 1017da6c28aaSamw } 1018da6c28aaSamw 1019148c5f43SAlan Wright /* 1020148c5f43SAlan Wright * smbstat_srv_process_requests 1021148c5f43SAlan Wright * 1022148c5f43SAlan Wright * Processes the data relative to the SMB requests and stores the results in 1023148c5f43SAlan Wright * the structure smbstat_srv_info. 1024148c5f43SAlan Wright */ 1025da6c28aaSamw static void 1026148c5f43SAlan Wright smbstat_srv_process_requests( 1027148c5f43SAlan Wright smbstat_srv_snapshot_t *curr, 1028148c5f43SAlan Wright smbstat_srv_snapshot_t *prev) 1029da6c28aaSamw { 1030148c5f43SAlan Wright smbstat_req_info_t *info; 1031a90cf9f2SGordon Ross smb_kstat_req_t *curr_req; 1032a90cf9f2SGordon Ross smb_kstat_req_t *prev_req; 1033148c5f43SAlan Wright int i, idx; 1034a90cf9f2SGordon Ross boolean_t firstcall = (prev->ss_snaptime == 0); 1035da6c28aaSamw 1036148c5f43SAlan Wright for (i = 0; i < SMB_COM_NUM; i++) { 1037a90cf9f2SGordon Ross info = &smbstat_srv_info.si_reqs1[i]; 1038*5015ecc3SGordon Ross idx = info->ri_opcode; 1039*5015ecc3SGordon Ross if (idx >= SMB_COM_NUM) 1040*5015ecc3SGordon Ross continue; 1041a90cf9f2SGordon Ross curr_req = &curr->ss_data.ks_reqs1[idx]; 1042a90cf9f2SGordon Ross prev_req = &prev->ss_data.ks_reqs1[idx]; 1043a90cf9f2SGordon Ross smbstat_srv_process_one_req( 1044a90cf9f2SGordon Ross info, curr_req, prev_req, firstcall); 1045a90cf9f2SGordon Ross } 1046a90cf9f2SGordon Ross 1047a90cf9f2SGordon Ross for (i = 0; i < SMB2__NCMDS; i++) { 1048a90cf9f2SGordon Ross info = &smbstat_srv_info.si_reqs2[i]; 1049*5015ecc3SGordon Ross idx = info->ri_opcode; 1050*5015ecc3SGordon Ross if (idx >= SMB2__NCMDS) 1051*5015ecc3SGordon Ross continue; 1052*5015ecc3SGordon Ross curr_req = &curr->ss_data.ks_reqs2[idx]; 1053*5015ecc3SGordon Ross prev_req = &prev->ss_data.ks_reqs2[idx]; 1054a90cf9f2SGordon Ross smbstat_srv_process_one_req( 1055a90cf9f2SGordon Ross info, curr_req, prev_req, firstcall); 1056a90cf9f2SGordon Ross } 1057a90cf9f2SGordon Ross } 1058a90cf9f2SGordon Ross 1059a90cf9f2SGordon Ross static void 1060a90cf9f2SGordon Ross smbstat_srv_process_one_req( 1061a90cf9f2SGordon Ross smbstat_req_info_t *info, 1062a90cf9f2SGordon Ross smb_kstat_req_t *curr_req, 1063a90cf9f2SGordon Ross smb_kstat_req_t *prev_req, 1064a90cf9f2SGordon Ross boolean_t firstcall) 1065a90cf9f2SGordon Ross { 1066a90cf9f2SGordon Ross double nrqs; 1067a90cf9f2SGordon Ross 1068a90cf9f2SGordon Ross nrqs = smbstat_sub_64(curr_req->kr_nreq, 1069a90cf9f2SGordon Ross prev_req->kr_nreq); 1070a90cf9f2SGordon Ross 1071a90cf9f2SGordon Ross info->ri_rqs = nrqs / smbstat_srv_info.si_etime; 1072a90cf9f2SGordon Ross 1073a90cf9f2SGordon Ross info->ri_rbs = smbstat_sub_64( 1074a90cf9f2SGordon Ross curr_req->kr_rxb, 1075a90cf9f2SGordon Ross prev_req->kr_rxb) / 1076a90cf9f2SGordon Ross smbstat_srv_info.si_etime; 1077a90cf9f2SGordon Ross 1078a90cf9f2SGordon Ross info->ri_tbs = smbstat_sub_64( 1079a90cf9f2SGordon Ross curr_req->kr_txb, 1080a90cf9f2SGordon Ross prev_req->kr_txb) / 1081a90cf9f2SGordon Ross smbstat_srv_info.si_etime; 1082a90cf9f2SGordon Ross 1083a90cf9f2SGordon Ross info->ri_pct = nrqs * 100; 1084a90cf9f2SGordon Ross if (smbstat_srv_info.si_total_nreqs > 0) 1085a90cf9f2SGordon Ross info->ri_pct /= smbstat_srv_info.si_total_nreqs; 1086a90cf9f2SGordon Ross 1087a90cf9f2SGordon Ross if (firstcall) { 1088a90cf9f2SGordon Ross /* First time. Take the aggregate */ 1089a90cf9f2SGordon Ross info->ri_stddev = 1090a90cf9f2SGordon Ross curr_req->kr_a_stddev; 1091a90cf9f2SGordon Ross info->ri_mean = curr_req->kr_a_mean; 1092a90cf9f2SGordon Ross } else { 1093a90cf9f2SGordon Ross /* Take the differential */ 1094a90cf9f2SGordon Ross info->ri_stddev = 1095a90cf9f2SGordon Ross curr_req->kr_d_stddev; 1096a90cf9f2SGordon Ross info->ri_mean = curr_req->kr_d_mean; 1097a90cf9f2SGordon Ross } 1098a90cf9f2SGordon Ross if (nrqs > 0) { 1099a90cf9f2SGordon Ross info->ri_stddev /= nrqs; 1100a90cf9f2SGordon Ross info->ri_stddev = sqrt(info->ri_stddev); 1101a90cf9f2SGordon Ross } else { 1102a90cf9f2SGordon Ross info->ri_stddev = 0; 1103da6c28aaSamw } 1104a90cf9f2SGordon Ross info->ri_stddev /= NANOSEC; 1105a90cf9f2SGordon Ross info->ri_mean /= NANOSEC; 1106da6c28aaSamw } 1107da6c28aaSamw 1108a90cf9f2SGordon Ross 1109148c5f43SAlan Wright /* 1110148c5f43SAlan Wright * smbstat_srv_current_snapshot 1111148c5f43SAlan Wright * 1112148c5f43SAlan Wright * Returns the current snapshot. 1113148c5f43SAlan Wright */ 1114148c5f43SAlan Wright static smbstat_srv_snapshot_t * 1115148c5f43SAlan Wright smbstat_srv_current_snapshot(void) 1116148c5f43SAlan Wright { 1117148c5f43SAlan Wright return (&smbstat_srv_snapshots[smbstat_snapshot_idx]); 1118148c5f43SAlan Wright } 1119148c5f43SAlan Wright 1120148c5f43SAlan Wright /* 1121148c5f43SAlan Wright * smbstat_srv_previous_snapshot 1122148c5f43SAlan Wright * 1123148c5f43SAlan Wright * Returns the previous snapshot. 1124148c5f43SAlan Wright */ 1125148c5f43SAlan Wright static smbstat_srv_snapshot_t * 1126148c5f43SAlan Wright smbstat_srv_previous_snapshot(void) 1127148c5f43SAlan Wright { 1128148c5f43SAlan Wright int idx; 1129148c5f43SAlan Wright 1130148c5f43SAlan Wright idx = (smbstat_snapshot_idx - 1) & SMBSTAT_SNAPSHOT_MASK; 1131148c5f43SAlan Wright return (&smbstat_srv_snapshots[idx]); 1132148c5f43SAlan Wright } 1133148c5f43SAlan Wright 1134148c5f43SAlan Wright /* 1135148c5f43SAlan Wright * smbstat_usage 1136148c5f43SAlan Wright * 1137148c5f43SAlan Wright * Prints out a help message. 1138148c5f43SAlan Wright */ 1139da6c28aaSamw static void 1140148c5f43SAlan Wright smbstat_usage(FILE *fd, int exit_code) 1141da6c28aaSamw { 1142148c5f43SAlan Wright (void) fprintf(fd, gettext(SMBSTAT_HELP)); 1143148c5f43SAlan Wright exit(exit_code); 1144da6c28aaSamw } 1145da6c28aaSamw 1146148c5f43SAlan Wright /* 1147148c5f43SAlan Wright * smbstat_fail 1148148c5f43SAlan Wright * 1149148c5f43SAlan Wright * Prints out to stderr an error message and exits the process. 1150148c5f43SAlan Wright */ 1151da6c28aaSamw static void 1152da6c28aaSamw smbstat_fail(int do_perror, char *message, ...) 1153da6c28aaSamw { 1154da6c28aaSamw va_list args; 1155da6c28aaSamw 1156da6c28aaSamw va_start(args, message); 1157da6c28aaSamw (void) fprintf(stderr, gettext("smbstat: ")); 1158da6c28aaSamw /* LINTED E_SEC_PRINTF_VAR_FMT */ 1159da6c28aaSamw (void) vfprintf(stderr, message, args); 1160da6c28aaSamw va_end(args); 1161da6c28aaSamw if (do_perror) 1162da6c28aaSamw (void) fprintf(stderr, ": %s", strerror(errno)); 1163da6c28aaSamw (void) fprintf(stderr, "\n"); 1164da6c28aaSamw exit(1); 1165da6c28aaSamw } 1166da6c28aaSamw 1167148c5f43SAlan Wright /* 1168148c5f43SAlan Wright * smbstat_sub_64 1169148c5f43SAlan Wright * 1170148c5f43SAlan Wright * Substract 2 uint64_t and returns a double. 1171148c5f43SAlan Wright */ 1172148c5f43SAlan Wright static double 1173148c5f43SAlan Wright smbstat_sub_64(uint64_t a, uint64_t b) 1174da6c28aaSamw { 1175148c5f43SAlan Wright return ((double)(a - b)); 1176148c5f43SAlan Wright } 1177da6c28aaSamw 1178148c5f43SAlan Wright /* 1179148c5f43SAlan Wright * smbstat_zero 1180148c5f43SAlan Wright * 1181148c5f43SAlan Wright * Returns zero if the value passed in is less than 1. 1182148c5f43SAlan Wright */ 1183148c5f43SAlan Wright static double 1184148c5f43SAlan Wright smbstat_zero(double value) 1185148c5f43SAlan Wright { 1186148c5f43SAlan Wright if (value < 1) 1187148c5f43SAlan Wright value = 0; 1188148c5f43SAlan Wright return (value); 1189148c5f43SAlan Wright } 1190148c5f43SAlan Wright 1191148c5f43SAlan Wright /* 1192148c5f43SAlan Wright * smbstat_strtoi 1193148c5f43SAlan Wright * 1194148c5f43SAlan Wright * Converts a string representing an integer value into its binary value. 1195148c5f43SAlan Wright * If the conversion fails this routine exits the process. 1196148c5f43SAlan Wright */ 1197148c5f43SAlan Wright static uint_t 1198148c5f43SAlan Wright smbstat_strtoi(char const *val, char *errmsg) 1199148c5f43SAlan Wright { 1200148c5f43SAlan Wright char *end; 1201148c5f43SAlan Wright long tmp; 1202148c5f43SAlan Wright 1203148c5f43SAlan Wright errno = 0; 1204148c5f43SAlan Wright tmp = strtol(val, &end, 10); 1205148c5f43SAlan Wright if (*end != '\0' || errno) 1206148c5f43SAlan Wright smbstat_fail(1, "%s %s", errmsg, val); 1207148c5f43SAlan Wright return ((uint_t)tmp); 1208148c5f43SAlan Wright } 1209148c5f43SAlan Wright 1210148c5f43SAlan Wright /* 1211148c5f43SAlan Wright * smbstat_termio_init 1212148c5f43SAlan Wright * 1213148c5f43SAlan Wright * Determines the size of the terminal associated with the process. 1214148c5f43SAlan Wright */ 1215148c5f43SAlan Wright static void 1216148c5f43SAlan Wright smbstat_termio_init(void) 1217148c5f43SAlan Wright { 1218148c5f43SAlan Wright char *envp; 1219148c5f43SAlan Wright 1220148c5f43SAlan Wright if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &smbstat_ws) != -1) { 1221148c5f43SAlan Wright if (smbstat_ws.ws_row == 0) { 1222148c5f43SAlan Wright envp = getenv("LINES"); 1223148c5f43SAlan Wright if (envp != NULL) 1224148c5f43SAlan Wright smbstat_ws.ws_row = atoi(envp); 1225148c5f43SAlan Wright } 1226148c5f43SAlan Wright 1227148c5f43SAlan Wright if (smbstat_ws.ws_col == 0) { 1228148c5f43SAlan Wright envp = getenv("COLUMNS"); 1229148c5f43SAlan Wright if (envp != NULL) 1230148c5f43SAlan Wright smbstat_ws.ws_row = atoi(envp); 1231148c5f43SAlan Wright } 1232148c5f43SAlan Wright } 1233148c5f43SAlan Wright if (smbstat_ws.ws_col == 0) 1234148c5f43SAlan Wright smbstat_ws.ws_col = 80; 1235148c5f43SAlan Wright if (smbstat_ws.ws_row == 0) 1236148c5f43SAlan Wright smbstat_ws.ws_row = 25; 1237148c5f43SAlan Wright } 1238148c5f43SAlan Wright 1239148c5f43SAlan Wright /* 1240148c5f43SAlan Wright * smbstat_snapshot_idx_inc 1241148c5f43SAlan Wright * 1242148c5f43SAlan Wright * Increments the snapshot index. 1243148c5f43SAlan Wright */ 1244148c5f43SAlan Wright static void 1245148c5f43SAlan Wright smbstat_snapshot_inc_idx(void) 1246148c5f43SAlan Wright { 1247148c5f43SAlan Wright smbstat_snapshot_idx++; 1248148c5f43SAlan Wright smbstat_snapshot_idx &= SMBSTAT_SNAPSHOT_MASK; 1249da6c28aaSamw } 1250da6c28aaSamw 1251da6c28aaSamw /* 1252148c5f43SAlan Wright * smbstat_req_cmp_name 1253148c5f43SAlan Wright * 1254148c5f43SAlan Wright * Call back function passed to qsort() when the list of requests must be sorted 1255148c5f43SAlan Wright * by name. 1256da6c28aaSamw */ 1257148c5f43SAlan Wright static int 1258148c5f43SAlan Wright smbstat_req_cmp_name(const void *obj1, const void *obj2) 1259da6c28aaSamw { 1260148c5f43SAlan Wright return (strncasecmp( 1261148c5f43SAlan Wright ((smbstat_req_info_t *)obj1)->ri_name, 1262148c5f43SAlan Wright ((smbstat_req_info_t *)obj2)->ri_name, 1263148c5f43SAlan Wright sizeof (((smbstat_req_info_t *)obj2)->ri_name))); 1264da6c28aaSamw } 1265da6c28aaSamw 1266148c5f43SAlan Wright /* 1267148c5f43SAlan Wright * smbstat_req_order 1268148c5f43SAlan Wright * 1269148c5f43SAlan Wright * Snapshots the smbsrv module statistics once to get the name of the requests. 1270148c5f43SAlan Wright * The request list is smbstat_srv_info is then sorted by name or by code 1271148c5f43SAlan Wright * depending on the boolean smbstat_opt_a. 1272148c5f43SAlan Wright * The function should be called once during initialization. 1273148c5f43SAlan Wright */ 1274148c5f43SAlan Wright static void 1275148c5f43SAlan Wright smbstat_req_order(void) 1276148c5f43SAlan Wright { 1277a90cf9f2SGordon Ross smbstat_srv_snapshot_t *ss; 1278148c5f43SAlan Wright smbstat_req_info_t *info; 1279148c5f43SAlan Wright smb_kstat_req_t *reqs; 1280148c5f43SAlan Wright int i; 1281148c5f43SAlan Wright 1282148c5f43SAlan Wright smbstat_srv_snapshot(); 1283a90cf9f2SGordon Ross ss = smbstat_srv_current_snapshot(); 1284148c5f43SAlan Wright 1285a90cf9f2SGordon Ross reqs = ss->ss_data.ks_reqs1; 1286a90cf9f2SGordon Ross info = smbstat_srv_info.si_reqs1; 1287148c5f43SAlan Wright for (i = 0; i < SMB_COM_NUM; i++) { 1288148c5f43SAlan Wright (void) strlcpy(info[i].ri_name, reqs[i].kr_name, 1289148c5f43SAlan Wright sizeof (reqs[i].kr_name)); 1290148c5f43SAlan Wright info[i].ri_opcode = i; 1291148c5f43SAlan Wright } 1292148c5f43SAlan Wright if (smbstat_opt_n) 1293148c5f43SAlan Wright qsort(info, SMB_COM_NUM, sizeof (smbstat_req_info_t), 1294148c5f43SAlan Wright smbstat_req_cmp_name); 1295a90cf9f2SGordon Ross 1296a90cf9f2SGordon Ross reqs = ss->ss_data.ks_reqs2; 1297a90cf9f2SGordon Ross info = smbstat_srv_info.si_reqs2; 1298a90cf9f2SGordon Ross for (i = 0; i < SMB2__NCMDS; i++) { 1299a90cf9f2SGordon Ross (void) strlcpy(info[i].ri_name, reqs[i].kr_name, 1300a90cf9f2SGordon Ross sizeof (reqs[i].kr_name)); 1301a90cf9f2SGordon Ross info[i].ri_opcode = i; 1302a90cf9f2SGordon Ross } 1303a90cf9f2SGordon Ross if (smbstat_opt_n) 1304a90cf9f2SGordon Ross qsort(info, SMB2__NCMDS, sizeof (smbstat_req_info_t), 1305a90cf9f2SGordon Ross smbstat_req_cmp_name); 1306148c5f43SAlan Wright } 1307148c5f43SAlan Wright 1308148c5f43SAlan Wright /* 1309148c5f43SAlan Wright * Return the number of ticks delta between two hrtime_t 1310148c5f43SAlan Wright * values. Attempt to cater for various kinds of overflow 1311148c5f43SAlan Wright * in hrtime_t - no matter how improbable. 1312148c5f43SAlan Wright */ 1313148c5f43SAlan Wright static double 1314148c5f43SAlan Wright smbstat_hrtime_delta(hrtime_t old, hrtime_t new) 1315148c5f43SAlan Wright { 1316148c5f43SAlan Wright uint64_t del; 1317148c5f43SAlan Wright 1318148c5f43SAlan Wright if ((new >= old) && (old >= 0L)) 1319148c5f43SAlan Wright return ((double)(new - old)); 1320148c5f43SAlan Wright /* 1321148c5f43SAlan Wright * We've overflowed the positive portion of an hrtime_t. 1322148c5f43SAlan Wright */ 1323148c5f43SAlan Wright if (new < 0L) { 1324148c5f43SAlan Wright /* 1325148c5f43SAlan Wright * The new value is negative. Handle the case where the old 1326148c5f43SAlan Wright * value is positive or negative. 1327148c5f43SAlan Wright */ 1328148c5f43SAlan Wright uint64_t n1; 1329148c5f43SAlan Wright uint64_t o1; 1330148c5f43SAlan Wright 1331148c5f43SAlan Wright n1 = -new; 1332148c5f43SAlan Wright if (old > 0L) 1333148c5f43SAlan Wright return ((double)(n1 - old)); 1334148c5f43SAlan Wright 1335148c5f43SAlan Wright o1 = -old; 1336148c5f43SAlan Wright del = n1 - o1; 1337148c5f43SAlan Wright return ((double)del); 1338148c5f43SAlan Wright } 1339148c5f43SAlan Wright 1340148c5f43SAlan Wright /* 1341148c5f43SAlan Wright * Either we've just gone from being negative to positive *or* the last 1342148c5f43SAlan Wright * entry was positive and the new entry is also positive but *less* than 1343148c5f43SAlan Wright * the old entry. This implies we waited quite a few days on a very fast 1344148c5f43SAlan Wright * system between displays. 1345148c5f43SAlan Wright */ 1346148c5f43SAlan Wright if (old < 0L) { 1347148c5f43SAlan Wright uint64_t o2; 1348148c5f43SAlan Wright o2 = -old; 1349148c5f43SAlan Wright del = UINT64_MAX - o2; 1350148c5f43SAlan Wright } else { 1351148c5f43SAlan Wright del = UINT64_MAX - old; 1352148c5f43SAlan Wright } 1353148c5f43SAlan Wright del += new; 1354148c5f43SAlan Wright return ((double)del); 1355148c5f43SAlan Wright } 1356148c5f43SAlan Wright 1357148c5f43SAlan Wright static void * 1358148c5f43SAlan Wright smbstat_zalloc(size_t size) 1359148c5f43SAlan Wright { 1360148c5f43SAlan Wright void *ptr; 1361148c5f43SAlan Wright 1362148c5f43SAlan Wright ptr = umem_zalloc(size, UMEM_DEFAULT); 1363148c5f43SAlan Wright if (ptr == NULL) 1364148c5f43SAlan Wright smbstat_fail(1, gettext("out of memory")); 1365148c5f43SAlan Wright return (ptr); 1366148c5f43SAlan Wright } 1367148c5f43SAlan Wright 1368148c5f43SAlan Wright static void 1369148c5f43SAlan Wright smbstat_free(void *ptr, size_t size) 1370da6c28aaSamw { 1371148c5f43SAlan Wright umem_free(ptr, size); 1372da6c28aaSamw } 1373