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.
245015ecc3SGordon Ross * Copyright 2020 Nexenta by DDN, Inc. All rights reserved.
25*eeabb06cSGordon Ross * Copyright 2023 RackTop Systems, Inc.
26da6c28aaSamw */
27da6c28aaSamw
28da6c28aaSamw /*
29da6c28aaSamw * smbstat: Server Message Block File System statistics
30148c5f43SAlan Wright *
31148c5f43SAlan Wright * The statistics this CLI displays come from two sources:
32148c5f43SAlan Wright *
33148c5f43SAlan Wright * 1) The kernel module 'smbsrv'.
34148c5f43SAlan Wright * 2) The SMB workers task queue statistics the task queue manager of Solaris
35148c5f43SAlan Wright * maintains.
36148c5f43SAlan Wright *
37148c5f43SAlan Wright * The flow of the code is the following:
38148c5f43SAlan Wright *
39148c5f43SAlan Wright *
405015ecc3SGordon Ross * +----------------+
415015ecc3SGordon Ross * | Initialization |
425015ecc3SGordon Ross * +----------------+
43148c5f43SAlan Wright * |
44148c5f43SAlan Wright * |
45148c5f43SAlan Wright * v
46148c5f43SAlan Wright * +--------------------------*
47148c5f43SAlan Wright * | Take a snapshot the data | <--------+
48148c5f43SAlan Wright * +--------------------------+ |
49148c5f43SAlan Wright * | |
505015ecc3SGordon Ross * | |
51148c5f43SAlan Wright * v |
52148c5f43SAlan Wright * +----------------------+ |
53148c5f43SAlan Wright * | Process the snapshot | |
54148c5f43SAlan Wright * +----------------------+ |
55148c5f43SAlan Wright * | |
56148c5f43SAlan Wright * | |
57148c5f43SAlan Wright * v |
58148c5f43SAlan Wright * +------------------------------------+ |
59148c5f43SAlan Wright * | Print the result of the processing | |
60148c5f43SAlan Wright * +------------------------------------+ |
61148c5f43SAlan Wright * | |
62148c5f43SAlan Wright * | |
63148c5f43SAlan Wright * v |
64148c5f43SAlan Wright * Yes --------------- |
65148c5f43SAlan Wright * +------------ < interval == 0 ? > |
665015ecc3SGordon Ross * | --------------- |
67148c5f43SAlan Wright * | | |
685015ecc3SGordon Ross * | | No |
695015ecc3SGordon Ross * | v |
70148c5f43SAlan Wright * | +------------------------+ |
715015ecc3SGordon Ross * | | Sleep for the duration | ----------+
725015ecc3SGordon Ross * | | of the interval. |
735015ecc3SGordon Ross * | +------------------------+
745015ecc3SGordon Ross * |
755015ecc3SGordon Ross * +---------------------+
76148c5f43SAlan Wright * |
77148c5f43SAlan Wright * v
78148c5f43SAlan Wright *
79148c5f43SAlan Wright * Exit
80148c5f43SAlan Wright *
81148c5f43SAlan Wright * There are two sets of snapshots. One set for the smbsrv module and the other
82148c5f43SAlan Wright * for the task queue (SMB workers). Each set contains 2 snapshots. One is
83148c5f43SAlan Wright * labeled 'current' the other one 'previous'. Their role changes after each
84148c5f43SAlan Wright * snapshot. The 'current' becomes 'previous' and vice versa.
85148c5f43SAlan Wright * The first snapshot taken is compared against the data gathered since the
86148c5f43SAlan Wright * smbsrv module was loaded. Subsequent snapshots will be compared against the
87148c5f43SAlan Wright * previous snapshot.
88da6c28aaSamw */
89148c5f43SAlan Wright
90da6c28aaSamw #include <stdio.h>
91da6c28aaSamw #include <stdlib.h>
92148c5f43SAlan Wright #include <unistd.h>
93da6c28aaSamw #include <kstat.h>
94da6c28aaSamw #include <stdarg.h>
95da6c28aaSamw #include <errno.h>
96da6c28aaSamw #include <inttypes.h>
97da6c28aaSamw #include <strings.h>
98da6c28aaSamw #include <utility.h>
99da6c28aaSamw #include <libintl.h>
100da6c28aaSamw #include <zone.h>
101148c5f43SAlan Wright #include <termios.h>
102148c5f43SAlan Wright #include <stropts.h>
103148c5f43SAlan Wright #include <math.h>
104148c5f43SAlan Wright #include <umem.h>
105148c5f43SAlan Wright #include <locale.h>
106b3b35633SGordon Ross #include <sys/processor.h>
1076537f381Sas #include <smbsrv/smb_kstat.h>
1088365a6eaSGordon Ross #include <smbsrv/smb.h>
1098365a6eaSGordon Ross #include <smbsrv/smb2.h>
110da6c28aaSamw
111148c5f43SAlan Wright #if !defined(TEXT_DOMAIN)
112148c5f43SAlan Wright #define TEXT_DOMAIN "SYS_TEST"
113148c5f43SAlan Wright #endif /* TEXT_DOMAIN */
114148c5f43SAlan Wright
115148c5f43SAlan Wright #define SMBSTAT_ID_NO_CPU -1
116148c5f43SAlan Wright #define SMBSTAT_SNAPSHOT_COUNT 2 /* Must be a power of 2 */
117148c5f43SAlan Wright #define SMBSTAT_SNAPSHOT_MASK (SMBSTAT_SNAPSHOT_COUNT - 1)
118148c5f43SAlan Wright
119148c5f43SAlan Wright #define SMBSTAT_HELP \
120148c5f43SAlan Wright "Usage: smbstat [-acnrtuz] [interval]\n" \
121148c5f43SAlan Wright " -c: display counters\n" \
122148c5f43SAlan Wright " -t: display throughput\n" \
123148c5f43SAlan Wright " -u: display utilization\n" \
124148c5f43SAlan Wright " -r: display requests\n" \
125148c5f43SAlan Wright " -a: all the requests (supported and unsupported)\n" \
126148c5f43SAlan Wright " -z: skip the requests not received\n" \
127148c5f43SAlan Wright " -n: display in alphabetic order\n" \
128148c5f43SAlan Wright " interval: refresh cycle in seconds\n"
129148c5f43SAlan Wright
130148c5f43SAlan Wright #define SMBSRV_COUNTERS_BANNER "\n nbt tcp users trees files pipes\n"
131148c5f43SAlan Wright #define SMBSRV_COUNTERS_FORMAT "%5d %5d %5d %5d %5d %5d\n"
132148c5f43SAlan Wright
133148c5f43SAlan Wright #define SMBSRV_THROUGHPUT_BANNER \
134148c5f43SAlan Wright "\nrbytes/s tbytes/s reqs/s reads/s writes/s\n"
135148c5f43SAlan Wright #define SMBSRV_THROUGHPUT_FORMAT \
136148c5f43SAlan Wright "%1.3e %1.3e %1.3e %1.3e %1.3e\n"
137148c5f43SAlan Wright
138148c5f43SAlan Wright #define SMBSRV_UTILIZATION_BANNER \
139148c5f43SAlan Wright "\n wcnt rcnt wtime rtime" \
140148c5f43SAlan Wright " w%% r%% u%% sat usr%% sys%% idle%%\n"
141148c5f43SAlan Wright #define SMBSRV_UTILIZATION_FORMAT \
142148c5f43SAlan Wright "%1.3e %1.3e %1.3e %1.3e %3.0f %3.0f %3.0f %s " \
143148c5f43SAlan Wright "%3.0f %3.0f %3.0f\n"
144148c5f43SAlan Wright
145148c5f43SAlan Wright #define SMBSRV_REQUESTS_BANNER \
146148c5f43SAlan Wright "\n%30s code %% rbytes/s tbytes/s req/s rt-mean" \
147148c5f43SAlan Wright " rt-stddev\n"
148148c5f43SAlan Wright #define SMBSRV_REQUESTS_FORMAT \
149148c5f43SAlan Wright "%30s %02X %3.0f %1.3e %1.3e %1.3e %1.3e %1.3e\n"
150148c5f43SAlan Wright
151148c5f43SAlan Wright typedef enum {
152148c5f43SAlan Wright CPU_TICKS_IDLE = 0,
153148c5f43SAlan Wright CPU_TICKS_USER,
154148c5f43SAlan Wright CPU_TICKS_KERNEL,
155148c5f43SAlan Wright CPU_TICKS_SENTINEL
156148c5f43SAlan Wright } cpu_state_idx_t;
157148c5f43SAlan Wright
158148c5f43SAlan Wright typedef struct smbstat_cpu_snapshot {
159148c5f43SAlan Wright processorid_t cs_id;
160148c5f43SAlan Wright int cs_state;
161148c5f43SAlan Wright uint64_t cs_ticks[CPU_TICKS_SENTINEL];
162148c5f43SAlan Wright } smbstat_cpu_snapshot_t;
163148c5f43SAlan Wright
164148c5f43SAlan Wright typedef struct smbstat_srv_snapshot {
165148c5f43SAlan Wright hrtime_t ss_snaptime;
166148c5f43SAlan Wright smbsrv_kstats_t ss_data;
167148c5f43SAlan Wright } smbstat_srv_snapshot_t;
168148c5f43SAlan Wright
169148c5f43SAlan Wright typedef struct smbstat_wrk_snapshot {
170148c5f43SAlan Wright uint64_t ws_maxthreads;
171148c5f43SAlan Wright uint64_t ws_bnalloc;
172148c5f43SAlan Wright } smbstat_wrk_snapshot_t;
173148c5f43SAlan Wright
174148c5f43SAlan Wright typedef struct smbstat_req_info {
175148c5f43SAlan Wright char ri_name[KSTAT_STRLEN];
176148c5f43SAlan Wright int ri_opcode;
177148c5f43SAlan Wright double ri_pct;
178148c5f43SAlan Wright double ri_tbs;
179148c5f43SAlan Wright double ri_rbs;
180148c5f43SAlan Wright double ri_rqs;
181148c5f43SAlan Wright double ri_stddev;
182148c5f43SAlan Wright double ri_mean;
183148c5f43SAlan Wright } smbstat_req_info_t;
184148c5f43SAlan Wright
185148c5f43SAlan Wright typedef struct smbstat_srv_info {
186148c5f43SAlan Wright double si_hretime;
187148c5f43SAlan Wright double si_etime;
188148c5f43SAlan Wright double si_total_nreqs;
189148c5f43SAlan Wright /*
190148c5f43SAlan Wright * Counters
191148c5f43SAlan Wright */
192148c5f43SAlan Wright uint32_t si_nbt_sess; /* NBT sessions */
193148c5f43SAlan Wright uint32_t si_tcp_sess; /* TCP sessions */
194148c5f43SAlan Wright uint32_t si_users; /* Users logged in */
195148c5f43SAlan Wright uint32_t si_trees; /* Trees connected */
196148c5f43SAlan Wright uint32_t si_files; /* Open files */
197148c5f43SAlan Wright uint32_t si_pipes; /* Open pipes */
198148c5f43SAlan Wright /*
199148c5f43SAlan Wright * Throughput of the server
200148c5f43SAlan Wright */
201148c5f43SAlan Wright double si_tbs; /* Bytes transmitted / second */
202148c5f43SAlan Wright double si_rbs; /* Bytes received / second */
203148c5f43SAlan Wright double si_rqs; /* Requests treated / second */
204148c5f43SAlan Wright double si_rds; /* Reads treated / second */
205148c5f43SAlan Wright double si_wrs; /* Writes treated / second */
206148c5f43SAlan Wright /*
207148c5f43SAlan Wright * Utilization of the server
208148c5f43SAlan Wright */
209148c5f43SAlan Wright double si_wpct; /* */
210148c5f43SAlan Wright double si_rpct; /* */
211148c5f43SAlan Wright double si_upct; /* Utilization in % */
212148c5f43SAlan Wright double si_avw; /* Average number of requests waiting */
213148c5f43SAlan Wright double si_avr; /* Average number of requests running */
214148c5f43SAlan Wright double si_wserv; /* Average waiting time */
215148c5f43SAlan Wright double si_rserv; /* Average running time */
216148c5f43SAlan Wright boolean_t si_sat;
217148c5f43SAlan Wright double si_ticks[CPU_TICKS_SENTINEL];
218148c5f43SAlan Wright /*
219148c5f43SAlan Wright * Latency & Throughput per request
220148c5f43SAlan Wright */
2218365a6eaSGordon Ross smbstat_req_info_t si_reqs1[SMBSRV_KS_NREQS1];
2228365a6eaSGordon Ross smbstat_req_info_t si_reqs2[SMBSRV_KS_NREQS2];
223148c5f43SAlan Wright } smbstat_srv_info_t;
224da6c28aaSamw
2256537f381Sas static void smbstat_init(void);
2266537f381Sas static void smbstat_fini(void);
227148c5f43SAlan Wright static void smbstat_kstat_snapshot(void);
228148c5f43SAlan Wright static void smbstat_kstat_process(void);
229148c5f43SAlan Wright static void smbstat_kstat_print(void);
230148c5f43SAlan Wright
231148c5f43SAlan Wright static void smbstat_print_counters(void);
232148c5f43SAlan Wright static void smbstat_print_throughput(void);
233148c5f43SAlan Wright static void smbstat_print_utilization(void);
234148c5f43SAlan Wright static void smbstat_print_requests(void);
235148c5f43SAlan Wright
236148c5f43SAlan Wright static void smbstat_cpu_init(void);
237148c5f43SAlan Wright static void smbstat_cpu_fini(void);
238148c5f43SAlan Wright static smbstat_cpu_snapshot_t *smbstat_cpu_current_snapshot(void);
239148c5f43SAlan Wright static smbstat_cpu_snapshot_t *smbstat_cpu_previous_snapshot(void);
240148c5f43SAlan Wright static void smbstat_cpu_snapshot(void);
241148c5f43SAlan Wright static void smbstat_cpu_process(void);
242148c5f43SAlan Wright
243148c5f43SAlan Wright static void smbstat_wrk_init(void);
244148c5f43SAlan Wright static void smbstat_wrk_fini(void);
245148c5f43SAlan Wright static void smbstat_wrk_snapshot(void);
246148c5f43SAlan Wright static void smbstat_wrk_process(void);
247148c5f43SAlan Wright static smbstat_wrk_snapshot_t *smbstat_wrk_current_snapshot(void);
248148c5f43SAlan Wright
249148c5f43SAlan Wright static void smbstat_srv_init(void);
250148c5f43SAlan Wright static void smbstat_srv_fini(void);
251148c5f43SAlan Wright static void smbstat_srv_snapshot(void);
252148c5f43SAlan Wright static void smbstat_srv_process(void);
253148c5f43SAlan Wright static void smbstat_srv_process_counters(smbstat_srv_snapshot_t *);
254148c5f43SAlan Wright static void smbstat_srv_process_throughput(smbstat_srv_snapshot_t *,
255148c5f43SAlan Wright smbstat_srv_snapshot_t *);
256148c5f43SAlan Wright static void smbstat_srv_process_utilization(smbstat_srv_snapshot_t *,
257148c5f43SAlan Wright smbstat_srv_snapshot_t *);
258148c5f43SAlan Wright static void smbstat_srv_process_requests(smbstat_srv_snapshot_t *,
259148c5f43SAlan Wright smbstat_srv_snapshot_t *);
260a90cf9f2SGordon Ross static void smbstat_srv_process_one_req(smbstat_req_info_t *,
261a90cf9f2SGordon Ross smb_kstat_req_t *, smb_kstat_req_t *, boolean_t);
262a90cf9f2SGordon Ross
263148c5f43SAlan Wright static smbstat_srv_snapshot_t *smbstat_srv_current_snapshot(void);
264148c5f43SAlan Wright static smbstat_srv_snapshot_t *smbstat_srv_previous_snapshot(void);
265148c5f43SAlan Wright
266148c5f43SAlan Wright static void *smbstat_zalloc(size_t);
267148c5f43SAlan Wright static void smbstat_free(void *, size_t);
268da6c28aaSamw static void smbstat_fail(int, char *, ...);
269148c5f43SAlan Wright static void smbstat_snapshot_inc_idx(void);
270f5aec946SToomas Soome static void smbstat_usage(FILE *, int) __NORETURN;
271148c5f43SAlan Wright static uint_t smbstat_strtoi(char const *, char *);
272148c5f43SAlan Wright static double smbstat_hrtime_delta(hrtime_t, hrtime_t);
273148c5f43SAlan Wright static double smbstat_sub_64(uint64_t, uint64_t);
274148c5f43SAlan Wright static void smbstat_req_order(void);
275148c5f43SAlan Wright static double smbstat_zero(double);
276148c5f43SAlan Wright static void smbstat_termio_init(void);
277148c5f43SAlan Wright
278148c5f43SAlan Wright #pragma does_not_return(smbstat_fail, smbstat_usage)
279148c5f43SAlan Wright
280148c5f43SAlan Wright static char *smbstat_cpu_states[CPU_TICKS_SENTINEL] = {
281148c5f43SAlan Wright "cpu_ticks_idle",
282148c5f43SAlan Wright "cpu_ticks_user",
283148c5f43SAlan Wright "cpu_ticks_kernel"
284148c5f43SAlan Wright };
285da6c28aaSamw
286148c5f43SAlan Wright static boolean_t smbstat_opt_a = B_FALSE; /* all */
287148c5f43SAlan Wright static boolean_t smbstat_opt_c = B_FALSE; /* counters */
288148c5f43SAlan Wright static boolean_t smbstat_opt_n = B_FALSE; /* by name */
289148c5f43SAlan Wright static boolean_t smbstat_opt_u = B_FALSE; /* utilization */
290148c5f43SAlan Wright static boolean_t smbstat_opt_t = B_FALSE; /* throughput */
291148c5f43SAlan Wright static boolean_t smbstat_opt_r = B_FALSE; /* requests */
292148c5f43SAlan Wright static boolean_t smbstat_opt_z = B_FALSE; /* non-zero requests */
293da6c28aaSamw
294148c5f43SAlan Wright static uint_t smbstat_interval = 0;
295148c5f43SAlan Wright static long smbstat_nrcpus = 0;
296148c5f43SAlan Wright static kstat_ctl_t *smbstat_ksc = NULL;
297148c5f43SAlan Wright static kstat_t *smbstat_srv_ksp = NULL;
298148c5f43SAlan Wright static kstat_t *smbstat_wrk_ksp = NULL;
299148c5f43SAlan Wright static struct winsize smbstat_ws;
300148c5f43SAlan Wright static uint16_t smbstat_rows = 0;
301148c5f43SAlan Wright
302148c5f43SAlan Wright static int smbstat_snapshot_idx = 0;
303148c5f43SAlan Wright static smbstat_cpu_snapshot_t *smbstat_cpu_snapshots[SMBSTAT_SNAPSHOT_COUNT];
304148c5f43SAlan Wright static smbstat_srv_snapshot_t smbstat_srv_snapshots[SMBSTAT_SNAPSHOT_COUNT];
305148c5f43SAlan Wright static smbstat_wrk_snapshot_t smbstat_wrk_snapshots[SMBSTAT_SNAPSHOT_COUNT];
306148c5f43SAlan Wright static smbstat_srv_info_t smbstat_srv_info;
307148c5f43SAlan Wright
308148c5f43SAlan Wright /*
309148c5f43SAlan Wright * main
310148c5f43SAlan Wright */
311da6c28aaSamw int
main(int argc,char * argv[])312da6c28aaSamw main(int argc, char *argv[])
313da6c28aaSamw {
314148c5f43SAlan Wright int c;
315148c5f43SAlan Wright
316148c5f43SAlan Wright (void) setlocale(LC_ALL, "");
317148c5f43SAlan Wright (void) textdomain(TEXT_DOMAIN);
318da6c28aaSamw
319da6c28aaSamw if (is_system_labeled()) {
320da6c28aaSamw (void) fprintf(stderr,
321da6c28aaSamw gettext("%s: Trusted Extensions not supported.\n"),
322da6c28aaSamw argv[0]);
3238622ec45SGordon Ross return (1);
324da6c28aaSamw }
325da6c28aaSamw
326148c5f43SAlan Wright while ((c = getopt(argc, argv, "achnrtuz")) != EOF) {
327da6c28aaSamw switch (c) {
328148c5f43SAlan Wright case 'a':
329148c5f43SAlan Wright smbstat_opt_a = B_TRUE;
330da6c28aaSamw break;
331148c5f43SAlan Wright case 'n':
332148c5f43SAlan Wright smbstat_opt_n = B_TRUE;
333da6c28aaSamw break;
334148c5f43SAlan Wright case 'u':
335148c5f43SAlan Wright smbstat_opt_u = B_TRUE;
336148c5f43SAlan Wright break;
337148c5f43SAlan Wright case 'c':
338148c5f43SAlan Wright smbstat_opt_c = B_TRUE;
339148c5f43SAlan Wright break;
340148c5f43SAlan Wright case 'r':
341148c5f43SAlan Wright smbstat_opt_r = B_TRUE;
342148c5f43SAlan Wright break;
343148c5f43SAlan Wright case 't':
344148c5f43SAlan Wright smbstat_opt_t = B_TRUE;
345148c5f43SAlan Wright break;
346148c5f43SAlan Wright case 'z':
347148c5f43SAlan Wright smbstat_opt_z = B_TRUE;
348148c5f43SAlan Wright break;
349148c5f43SAlan Wright case 'h':
350148c5f43SAlan Wright smbstat_usage(stdout, 0);
351da6c28aaSamw default:
352148c5f43SAlan Wright smbstat_usage(stderr, 1);
353da6c28aaSamw }
354da6c28aaSamw }
355da6c28aaSamw
356148c5f43SAlan Wright if (!smbstat_opt_u &&
357148c5f43SAlan Wright !smbstat_opt_c &&
358148c5f43SAlan Wright !smbstat_opt_r &&
359148c5f43SAlan Wright !smbstat_opt_t) {
360148c5f43SAlan Wright /* Default options when none is specified. */
361148c5f43SAlan Wright smbstat_opt_u = B_TRUE;
362148c5f43SAlan Wright smbstat_opt_t = B_TRUE;
363da6c28aaSamw }
364da6c28aaSamw
365148c5f43SAlan Wright if (optind < argc) {
366148c5f43SAlan Wright smbstat_interval =
367148c5f43SAlan Wright smbstat_strtoi(argv[optind], "invalid count");
368148c5f43SAlan Wright optind++;
369da6c28aaSamw }
370da6c28aaSamw
371148c5f43SAlan Wright if ((argc - optind) > 1)
372148c5f43SAlan Wright smbstat_usage(stderr, 1);
373148c5f43SAlan Wright
374148c5f43SAlan Wright (void) atexit(smbstat_fini);
375148c5f43SAlan Wright smbstat_init();
376148c5f43SAlan Wright for (;;) {
377148c5f43SAlan Wright smbstat_kstat_snapshot();
378148c5f43SAlan Wright smbstat_kstat_process();
379148c5f43SAlan Wright smbstat_kstat_print();
380148c5f43SAlan Wright if (smbstat_interval == 0)
381148c5f43SAlan Wright break;
382148c5f43SAlan Wright (void) sleep(smbstat_interval);
383148c5f43SAlan Wright smbstat_snapshot_inc_idx();
384148c5f43SAlan Wright }
385da6c28aaSamw return (0);
386da6c28aaSamw }
387da6c28aaSamw
388148c5f43SAlan Wright /*
389148c5f43SAlan Wright * smbstat_init
390148c5f43SAlan Wright *
391148c5f43SAlan Wright * Global initialization.
392148c5f43SAlan Wright */
393148c5f43SAlan Wright static void
smbstat_init(void)394148c5f43SAlan Wright smbstat_init(void)
395148c5f43SAlan Wright {
396148c5f43SAlan Wright if ((smbstat_ksc = kstat_open()) == NULL)
397148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_open(): can't open /dev/kstat"));
398da6c28aaSamw
399148c5f43SAlan Wright smbstat_cpu_init();
400148c5f43SAlan Wright smbstat_srv_init();
401148c5f43SAlan Wright smbstat_wrk_init();
402148c5f43SAlan Wright smbstat_req_order();
403148c5f43SAlan Wright }
404148c5f43SAlan Wright
405148c5f43SAlan Wright /*
406148c5f43SAlan Wright * smbstat_fini
407148c5f43SAlan Wright *
408148c5f43SAlan Wright * Releases the resources smbstat_init() allocated.
409148c5f43SAlan Wright */
410148c5f43SAlan Wright static void
smbstat_fini(void)411148c5f43SAlan Wright smbstat_fini(void)
412da6c28aaSamw {
413148c5f43SAlan Wright smbstat_wrk_fini();
414148c5f43SAlan Wright smbstat_srv_fini();
415148c5f43SAlan Wright smbstat_cpu_fini();
416148c5f43SAlan Wright (void) kstat_close(smbstat_ksc);
417da6c28aaSamw }
418da6c28aaSamw
419148c5f43SAlan Wright /*
420148c5f43SAlan Wright * smbstat_kstat_snapshot
421148c5f43SAlan Wright *
422148c5f43SAlan Wright * Takes a snapshot of the data.
423148c5f43SAlan Wright */
424148c5f43SAlan Wright static void
smbstat_kstat_snapshot(void)425148c5f43SAlan Wright smbstat_kstat_snapshot(void)
426148c5f43SAlan Wright {
427148c5f43SAlan Wright smbstat_cpu_snapshot();
428148c5f43SAlan Wright smbstat_srv_snapshot();
429148c5f43SAlan Wright smbstat_wrk_snapshot();
430148c5f43SAlan Wright }
431148c5f43SAlan Wright
432148c5f43SAlan Wright /*
433148c5f43SAlan Wright * smbstat_kstat_process
434148c5f43SAlan Wright */
435148c5f43SAlan Wright static void
smbstat_kstat_process(void)436148c5f43SAlan Wright smbstat_kstat_process(void)
437148c5f43SAlan Wright {
438148c5f43SAlan Wright smbstat_cpu_process();
439148c5f43SAlan Wright smbstat_srv_process();
440148c5f43SAlan Wright smbstat_wrk_process();
441148c5f43SAlan Wright }
442148c5f43SAlan Wright
443148c5f43SAlan Wright /*
444148c5f43SAlan Wright * smbstat_kstat_print
445148c5f43SAlan Wright *
446148c5f43SAlan Wright * Print the data processed.
447148c5f43SAlan Wright */
448148c5f43SAlan Wright static void
smbstat_kstat_print(void)449148c5f43SAlan Wright smbstat_kstat_print(void)
450148c5f43SAlan Wright {
451148c5f43SAlan Wright smbstat_termio_init();
452148c5f43SAlan Wright smbstat_print_counters();
453148c5f43SAlan Wright smbstat_print_throughput();
454148c5f43SAlan Wright smbstat_print_utilization();
455148c5f43SAlan Wright smbstat_print_requests();
456a90cf9f2SGordon Ross (void) fflush(stdout);
457148c5f43SAlan Wright }
458148c5f43SAlan Wright
459148c5f43SAlan Wright /*
460148c5f43SAlan Wright * smbstat_print_counters
461148c5f43SAlan Wright *
462148c5f43SAlan Wright * Displays the SMB server counters (session, users...).
463148c5f43SAlan Wright */
464148c5f43SAlan Wright static void
smbstat_print_counters(void)465148c5f43SAlan Wright smbstat_print_counters(void)
466148c5f43SAlan Wright {
467148c5f43SAlan Wright if (!smbstat_opt_c)
468148c5f43SAlan Wright return;
469148c5f43SAlan Wright
470148c5f43SAlan Wright if (smbstat_opt_u || smbstat_opt_r || smbstat_opt_t ||
471148c5f43SAlan Wright (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) {
472148c5f43SAlan Wright (void) printf(SMBSRV_COUNTERS_BANNER);
473148c5f43SAlan Wright smbstat_rows = 1;
474148c5f43SAlan Wright }
475148c5f43SAlan Wright
476148c5f43SAlan Wright (void) printf(SMBSRV_COUNTERS_FORMAT,
477148c5f43SAlan Wright smbstat_srv_info.si_nbt_sess,
478148c5f43SAlan Wright smbstat_srv_info.si_tcp_sess,
479148c5f43SAlan Wright smbstat_srv_info.si_users,
480148c5f43SAlan Wright smbstat_srv_info.si_trees,
481148c5f43SAlan Wright smbstat_srv_info.si_files,
482148c5f43SAlan Wright smbstat_srv_info.si_pipes);
483148c5f43SAlan Wright
484148c5f43SAlan Wright ++smbstat_rows;
485148c5f43SAlan Wright }
486148c5f43SAlan Wright /*
487148c5f43SAlan Wright * smbstat_print_throughput
488148c5f43SAlan Wright *
489148c5f43SAlan Wright * Formats the SMB server throughput output.
490148c5f43SAlan Wright */
491148c5f43SAlan Wright static void
smbstat_print_throughput(void)492148c5f43SAlan Wright smbstat_print_throughput(void)
493148c5f43SAlan Wright {
494148c5f43SAlan Wright if (!smbstat_opt_t)
495148c5f43SAlan Wright return;
496148c5f43SAlan Wright
497148c5f43SAlan Wright if (smbstat_opt_u || smbstat_opt_r || smbstat_opt_c ||
498148c5f43SAlan Wright (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) {
499148c5f43SAlan Wright (void) printf(SMBSRV_THROUGHPUT_BANNER);
500148c5f43SAlan Wright smbstat_rows = 1;
501148c5f43SAlan Wright }
502148c5f43SAlan Wright (void) printf(SMBSRV_THROUGHPUT_FORMAT,
503148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rbs),
504148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_tbs),
505148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rqs),
506148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rds),
507148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_wrs));
508148c5f43SAlan Wright
509148c5f43SAlan Wright ++smbstat_rows;
510148c5f43SAlan Wright }
511148c5f43SAlan Wright
512148c5f43SAlan Wright /*
513148c5f43SAlan Wright * smbstat_print_utilization
514148c5f43SAlan Wright */
515148c5f43SAlan Wright static void
smbstat_print_utilization(void)516148c5f43SAlan Wright smbstat_print_utilization(void)
517da6c28aaSamw {
518148c5f43SAlan Wright char *sat;
519148c5f43SAlan Wright if (!smbstat_opt_u)
520148c5f43SAlan Wright return;
521148c5f43SAlan Wright
522148c5f43SAlan Wright if (smbstat_opt_t || smbstat_opt_r || smbstat_opt_c ||
523148c5f43SAlan Wright (smbstat_rows == 0) || (smbstat_rows >= smbstat_ws.ws_row)) {
524148c5f43SAlan Wright (void) printf(SMBSRV_UTILIZATION_BANNER);
525148c5f43SAlan Wright smbstat_rows = 1;
526148c5f43SAlan Wright }
527148c5f43SAlan Wright
528148c5f43SAlan Wright if (smbstat_srv_info.si_sat)
529148c5f43SAlan Wright sat = "yes";
530148c5f43SAlan Wright else
531148c5f43SAlan Wright sat = "no ";
532148c5f43SAlan Wright
533148c5f43SAlan Wright (void) printf(SMBSRV_UTILIZATION_FORMAT,
534148c5f43SAlan Wright smbstat_srv_info.si_avw,
535148c5f43SAlan Wright smbstat_srv_info.si_avr,
536148c5f43SAlan Wright smbstat_srv_info.si_wserv,
537148c5f43SAlan Wright smbstat_srv_info.si_rserv,
538148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_wpct),
539148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_rpct),
540148c5f43SAlan Wright smbstat_zero(smbstat_srv_info.si_upct),
541148c5f43SAlan Wright sat,
542148c5f43SAlan Wright smbstat_srv_info.si_ticks[CPU_TICKS_USER],
543148c5f43SAlan Wright smbstat_srv_info.si_ticks[CPU_TICKS_KERNEL],
544148c5f43SAlan Wright smbstat_srv_info.si_ticks[CPU_TICKS_IDLE]);
545148c5f43SAlan Wright
546148c5f43SAlan Wright ++smbstat_rows;
547da6c28aaSamw }
548da6c28aaSamw
549148c5f43SAlan Wright /*
550148c5f43SAlan Wright * smbstat_print_requests
551148c5f43SAlan Wright */
552da6c28aaSamw static void
smbstat_print_requests(void)553148c5f43SAlan Wright smbstat_print_requests(void)
554da6c28aaSamw {
555148c5f43SAlan Wright smbstat_req_info_t *prq;
556148c5f43SAlan Wright int i;
557da6c28aaSamw
558148c5f43SAlan Wright if (!smbstat_opt_r)
559da6c28aaSamw return;
560da6c28aaSamw
561148c5f43SAlan Wright (void) printf(SMBSRV_REQUESTS_BANNER, " ");
5626537f381Sas
563a90cf9f2SGordon Ross prq = smbstat_srv_info.si_reqs1;
5648365a6eaSGordon Ross for (i = 0; i < SMBSRV_KS_NREQS1; i++) {
565148c5f43SAlan Wright if (!smbstat_opt_a &&
566148c5f43SAlan Wright strncmp(prq[i].ri_name, "Invalid", sizeof ("Invalid")) == 0)
567148c5f43SAlan Wright continue;
5686537f381Sas
569148c5f43SAlan Wright if (!smbstat_opt_z || (prq[i].ri_pct != 0)) {
570148c5f43SAlan Wright (void) printf(SMBSRV_REQUESTS_FORMAT,
571148c5f43SAlan Wright prq[i].ri_name,
572148c5f43SAlan Wright prq[i].ri_opcode,
573148c5f43SAlan Wright smbstat_zero(prq[i].ri_pct),
574148c5f43SAlan Wright smbstat_zero(prq[i].ri_rbs),
575148c5f43SAlan Wright smbstat_zero(prq[i].ri_tbs),
576148c5f43SAlan Wright smbstat_zero(prq[i].ri_rqs),
577148c5f43SAlan Wright prq[i].ri_mean,
578148c5f43SAlan Wright prq[i].ri_stddev);
5796537f381Sas }
580148c5f43SAlan Wright }
581a90cf9f2SGordon Ross
582a90cf9f2SGordon Ross prq = smbstat_srv_info.si_reqs2;
5838365a6eaSGordon Ross for (i = 0; i < SMBSRV_KS_NREQS2; i++) {
584a90cf9f2SGordon Ross if (!smbstat_opt_a && i == SMB2_INVALID_CMD)
585a90cf9f2SGordon Ross continue;
586a90cf9f2SGordon Ross
587a90cf9f2SGordon Ross if (!smbstat_opt_z || (prq[i].ri_pct != 0)) {
588a90cf9f2SGordon Ross (void) printf(SMBSRV_REQUESTS_FORMAT,
589a90cf9f2SGordon Ross prq[i].ri_name,
590a90cf9f2SGordon Ross prq[i].ri_opcode,
591a90cf9f2SGordon Ross smbstat_zero(prq[i].ri_pct),
592a90cf9f2SGordon Ross smbstat_zero(prq[i].ri_rbs),
593a90cf9f2SGordon Ross smbstat_zero(prq[i].ri_tbs),
594a90cf9f2SGordon Ross smbstat_zero(prq[i].ri_rqs),
595a90cf9f2SGordon Ross prq[i].ri_mean,
596a90cf9f2SGordon Ross prq[i].ri_stddev);
597a90cf9f2SGordon Ross }
598a90cf9f2SGordon Ross }
599148c5f43SAlan Wright }
600148c5f43SAlan Wright
601148c5f43SAlan Wright /*
602148c5f43SAlan Wright * smbstat_cpu_init
603148c5f43SAlan Wright */
604148c5f43SAlan Wright static void
smbstat_cpu_init(void)605148c5f43SAlan Wright smbstat_cpu_init(void)
606148c5f43SAlan Wright {
607148c5f43SAlan Wright size_t size;
608148c5f43SAlan Wright int i;
609148c5f43SAlan Wright
610148c5f43SAlan Wright smbstat_nrcpus = sysconf(_SC_CPUID_MAX) + 1;
611148c5f43SAlan Wright size = smbstat_nrcpus * sizeof (smbstat_cpu_snapshot_t);
612148c5f43SAlan Wright
613148c5f43SAlan Wright for (i = 0; i < SMBSTAT_SNAPSHOT_COUNT; i++)
614148c5f43SAlan Wright smbstat_cpu_snapshots[i] = smbstat_zalloc(size);
615148c5f43SAlan Wright }
616148c5f43SAlan Wright
617148c5f43SAlan Wright /*
618148c5f43SAlan Wright * smbstat_cpu_fini
619148c5f43SAlan Wright */
620148c5f43SAlan Wright static void
smbstat_cpu_fini(void)621148c5f43SAlan Wright smbstat_cpu_fini(void)
622148c5f43SAlan Wright {
623148c5f43SAlan Wright size_t size;
624148c5f43SAlan Wright int i;
625148c5f43SAlan Wright
626148c5f43SAlan Wright size = smbstat_nrcpus * sizeof (smbstat_cpu_snapshot_t);
627148c5f43SAlan Wright
628148c5f43SAlan Wright for (i = 0; i < SMBSTAT_SNAPSHOT_COUNT; i++)
629148c5f43SAlan Wright smbstat_free(smbstat_cpu_snapshots[i], size);
630148c5f43SAlan Wright }
631148c5f43SAlan Wright
632148c5f43SAlan Wright /*
633148c5f43SAlan Wright * smbstat_cpu_current_snapshot
634148c5f43SAlan Wright */
635148c5f43SAlan Wright static smbstat_cpu_snapshot_t *
smbstat_cpu_current_snapshot(void)636148c5f43SAlan Wright smbstat_cpu_current_snapshot(void)
637148c5f43SAlan Wright {
638148c5f43SAlan Wright return (smbstat_cpu_snapshots[smbstat_snapshot_idx]);
639148c5f43SAlan Wright }
640148c5f43SAlan Wright
641148c5f43SAlan Wright /*
642148c5f43SAlan Wright * smbstat_cpu_previous_snapshot
643148c5f43SAlan Wright */
644148c5f43SAlan Wright static smbstat_cpu_snapshot_t *
smbstat_cpu_previous_snapshot(void)645148c5f43SAlan Wright smbstat_cpu_previous_snapshot(void)
646148c5f43SAlan Wright {
647148c5f43SAlan Wright int idx;
648148c5f43SAlan Wright
649148c5f43SAlan Wright idx = (smbstat_snapshot_idx - 1) & SMBSTAT_SNAPSHOT_MASK;
650148c5f43SAlan Wright return (smbstat_cpu_snapshots[idx]);
651148c5f43SAlan Wright }
652148c5f43SAlan Wright
653148c5f43SAlan Wright /*
654148c5f43SAlan Wright * smbstat_cpu_snapshot
655148c5f43SAlan Wright */
656148c5f43SAlan Wright static void
smbstat_cpu_snapshot(void)657148c5f43SAlan Wright smbstat_cpu_snapshot(void)
658148c5f43SAlan Wright {
659148c5f43SAlan Wright kstat_t *ksp;
660148c5f43SAlan Wright kstat_named_t *ksn;
661148c5f43SAlan Wright smbstat_cpu_snapshot_t *curr;
662148c5f43SAlan Wright long i;
663148c5f43SAlan Wright int j;
664148c5f43SAlan Wright
665148c5f43SAlan Wright curr = smbstat_cpu_current_snapshot();
666148c5f43SAlan Wright
667148c5f43SAlan Wright for (i = 0; i < smbstat_nrcpus; i++, curr++) {
668148c5f43SAlan Wright curr->cs_id = SMBSTAT_ID_NO_CPU;
669148c5f43SAlan Wright curr->cs_state = p_online(i, P_STATUS);
670148c5f43SAlan Wright /* If no valid CPU is present, move on to the next one */
671*eeabb06cSGordon Ross if (curr->cs_state != P_ONLINE && curr->cs_state != P_NOINTR)
672148c5f43SAlan Wright continue;
673148c5f43SAlan Wright
674148c5f43SAlan Wright curr->cs_id = i;
675148c5f43SAlan Wright
676148c5f43SAlan Wright ksp = kstat_lookup(smbstat_ksc, "cpu", i, "sys");
677148c5f43SAlan Wright if (ksp == NULL)
678148c5f43SAlan Wright smbstat_fail(1,
679148c5f43SAlan Wright gettext("kstat_lookup('cpu sys %d') failed"), i);
680148c5f43SAlan Wright
681148c5f43SAlan Wright if (kstat_read(smbstat_ksc, ksp, NULL) == -1)
682148c5f43SAlan Wright smbstat_fail(1,
683148c5f43SAlan Wright gettext("kstat_read('cpu sys %d') failed"), i);
684148c5f43SAlan Wright
685148c5f43SAlan Wright for (j = 0; j < CPU_TICKS_SENTINEL; j++) {
686148c5f43SAlan Wright ksn = kstat_data_lookup(ksp, smbstat_cpu_states[j]);
687148c5f43SAlan Wright if (ksn == NULL)
688148c5f43SAlan Wright smbstat_fail(1,
689148c5f43SAlan Wright gettext("kstat_data_lookup('%s') failed"),
690148c5f43SAlan Wright smbstat_cpu_states[j]);
691148c5f43SAlan Wright curr->cs_ticks[j] = ksn->value.ui64;
6926537f381Sas }
6936537f381Sas }
694da6c28aaSamw }
695da6c28aaSamw
696148c5f43SAlan Wright /*
697148c5f43SAlan Wright * smbstat_cpu_process
698148c5f43SAlan Wright */
699da6c28aaSamw static void
smbstat_cpu_process(void)700148c5f43SAlan Wright smbstat_cpu_process(void)
701da6c28aaSamw {
702148c5f43SAlan Wright smbstat_cpu_snapshot_t *curr, *prev;
703148c5f43SAlan Wright double total_ticks;
704148c5f43SAlan Wright double agg_ticks[CPU_TICKS_SENTINEL];
705148c5f43SAlan Wright int i, j;
706da6c28aaSamw
707148c5f43SAlan Wright curr = smbstat_cpu_current_snapshot();
708148c5f43SAlan Wright prev = smbstat_cpu_previous_snapshot();
709148c5f43SAlan Wright bzero(agg_ticks, sizeof (agg_ticks));
710148c5f43SAlan Wright total_ticks = 0;
711da6c28aaSamw
712148c5f43SAlan Wright for (i = 0; i < smbstat_nrcpus; i++, curr++, prev++) {
713148c5f43SAlan Wright for (j = 0; j < CPU_TICKS_SENTINEL; j++) {
714148c5f43SAlan Wright agg_ticks[j] += smbstat_sub_64(curr->cs_ticks[j],
715148c5f43SAlan Wright prev->cs_ticks[j]);
716148c5f43SAlan Wright total_ticks += smbstat_sub_64(curr->cs_ticks[j],
717148c5f43SAlan Wright prev->cs_ticks[j]);
718148c5f43SAlan Wright }
719148c5f43SAlan Wright }
720148c5f43SAlan Wright
721148c5f43SAlan Wright for (j = 0; j < CPU_TICKS_SENTINEL; j++)
722148c5f43SAlan Wright smbstat_srv_info.si_ticks[j] =
723148c5f43SAlan Wright (agg_ticks[j] * 100.0) / total_ticks;
724da6c28aaSamw }
725da6c28aaSamw
726148c5f43SAlan Wright /*
727148c5f43SAlan Wright * smbstat_wrk_init
728148c5f43SAlan Wright */
729da6c28aaSamw static void
smbstat_wrk_init(void)730148c5f43SAlan Wright smbstat_wrk_init(void)
731da6c28aaSamw {
732148c5f43SAlan Wright smbstat_wrk_ksp =
733148c5f43SAlan Wright kstat_lookup(smbstat_ksc, "unix", -1, SMBSRV_KSTAT_WORKERS);
734148c5f43SAlan Wright if (smbstat_wrk_ksp == NULL)
735148c5f43SAlan Wright smbstat_fail(1,
736148c5f43SAlan Wright gettext("cannot retrieve smbsrv workers kstat\n"));
737148c5f43SAlan Wright }
7386537f381Sas
739148c5f43SAlan Wright static void
smbstat_wrk_fini(void)740148c5f43SAlan Wright smbstat_wrk_fini(void)
741148c5f43SAlan Wright {
742148c5f43SAlan Wright smbstat_wrk_ksp = NULL;
743148c5f43SAlan Wright }
7446537f381Sas
745148c5f43SAlan Wright /*
746148c5f43SAlan Wright * smbstat_wrk_snapshot
747148c5f43SAlan Wright */
748148c5f43SAlan Wright static void
smbstat_wrk_snapshot(void)749148c5f43SAlan Wright smbstat_wrk_snapshot(void)
750148c5f43SAlan Wright {
751148c5f43SAlan Wright smbstat_wrk_snapshot_t *curr;
752148c5f43SAlan Wright kstat_named_t *kn;
753da6c28aaSamw
754148c5f43SAlan Wright curr = smbstat_wrk_current_snapshot();
755da6c28aaSamw
756148c5f43SAlan Wright if (kstat_read(smbstat_ksc, smbstat_wrk_ksp, NULL) == -1)
757148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"),
758148c5f43SAlan Wright smbstat_wrk_ksp->ks_name);
759148c5f43SAlan Wright
760148c5f43SAlan Wright kn = kstat_data_lookup(smbstat_wrk_ksp, "maxthreads");
761148c5f43SAlan Wright if ((kn == NULL) || (kn->data_type != KSTAT_DATA_UINT64))
762148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"),
763148c5f43SAlan Wright "maxthreads");
764148c5f43SAlan Wright curr->ws_maxthreads = kn->value.ui64;
765148c5f43SAlan Wright
766148c5f43SAlan Wright kn = kstat_data_lookup(smbstat_wrk_ksp, "bnalloc");
767148c5f43SAlan Wright if ((kn == NULL) || (kn->data_type != KSTAT_DATA_UINT64))
768148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"),
769148c5f43SAlan Wright "bnalloc");
770148c5f43SAlan Wright curr->ws_bnalloc = kn->value.ui64;
771da6c28aaSamw }
772da6c28aaSamw
773148c5f43SAlan Wright /*
774148c5f43SAlan Wright * smbstat_wrk_process
775148c5f43SAlan Wright */
7766537f381Sas static void
smbstat_wrk_process(void)777148c5f43SAlan Wright smbstat_wrk_process(void)
7786537f381Sas {
779148c5f43SAlan Wright smbstat_wrk_snapshot_t *curr;
780148c5f43SAlan Wright
781148c5f43SAlan Wright curr = smbstat_wrk_current_snapshot();
782148c5f43SAlan Wright
783a90cf9f2SGordon Ross if (curr->ws_bnalloc >= curr->ws_maxthreads)
784148c5f43SAlan Wright smbstat_srv_info.si_sat = B_TRUE;
785148c5f43SAlan Wright else
786148c5f43SAlan Wright smbstat_srv_info.si_sat = B_FALSE;
7876537f381Sas }
7886537f381Sas
789148c5f43SAlan Wright /*
790148c5f43SAlan Wright * smbstat_wrk_current_snapshot
791148c5f43SAlan Wright */
792148c5f43SAlan Wright static smbstat_wrk_snapshot_t *
smbstat_wrk_current_snapshot(void)793148c5f43SAlan Wright smbstat_wrk_current_snapshot(void)
794148c5f43SAlan Wright {
795148c5f43SAlan Wright return (&smbstat_wrk_snapshots[smbstat_snapshot_idx]);
796148c5f43SAlan Wright }
797148c5f43SAlan Wright
798148c5f43SAlan Wright /*
799148c5f43SAlan Wright * smbstat_srv_init
800148c5f43SAlan Wright */
801148c5f43SAlan Wright static void
smbstat_srv_init(void)802148c5f43SAlan Wright smbstat_srv_init(void)
803148c5f43SAlan Wright {
804148c5f43SAlan Wright smbstat_srv_ksp = kstat_lookup(smbstat_ksc, SMBSRV_KSTAT_MODULE,
805148c5f43SAlan Wright getzoneid(), SMBSRV_KSTAT_STATISTICS);
806148c5f43SAlan Wright if (smbstat_srv_ksp == NULL)
807148c5f43SAlan Wright smbstat_fail(1, gettext("cannot retrieve smbsrv kstat\n"));
808148c5f43SAlan Wright }
809148c5f43SAlan Wright
810148c5f43SAlan Wright /*
811148c5f43SAlan Wright * smbstat_srv_fini
812148c5f43SAlan Wright */
813148c5f43SAlan Wright static void
smbstat_srv_fini(void)814148c5f43SAlan Wright smbstat_srv_fini(void)
815148c5f43SAlan Wright {
816148c5f43SAlan Wright smbstat_srv_ksp = NULL;
817148c5f43SAlan Wright }
818148c5f43SAlan Wright
819148c5f43SAlan Wright /*
820148c5f43SAlan Wright * smbstat_srv_snapshot
821148c5f43SAlan Wright *
822148c5f43SAlan Wright * Take a snapshot of the smbsrv module statistics.
823148c5f43SAlan Wright */
824148c5f43SAlan Wright static void
smbstat_srv_snapshot(void)825148c5f43SAlan Wright smbstat_srv_snapshot(void)
826148c5f43SAlan Wright {
827148c5f43SAlan Wright smbstat_srv_snapshot_t *curr;
828148c5f43SAlan Wright
829148c5f43SAlan Wright curr = smbstat_srv_current_snapshot();
830148c5f43SAlan Wright
831148c5f43SAlan Wright if ((kstat_read(smbstat_ksc, smbstat_srv_ksp, NULL) == -1) ||
832148c5f43SAlan Wright (smbstat_srv_ksp->ks_data_size != sizeof (curr->ss_data)))
833148c5f43SAlan Wright smbstat_fail(1, gettext("kstat_read('%s') failed"),
834148c5f43SAlan Wright smbstat_srv_ksp->ks_name);
835148c5f43SAlan Wright
836148c5f43SAlan Wright curr->ss_snaptime = smbstat_srv_ksp->ks_snaptime;
837148c5f43SAlan Wright bcopy(smbstat_srv_ksp->ks_data, &curr->ss_data, sizeof (curr->ss_data));
838148c5f43SAlan Wright }
839148c5f43SAlan Wright
840148c5f43SAlan Wright /*
841148c5f43SAlan Wright * smbstat_srv_process
842148c5f43SAlan Wright *
843148c5f43SAlan Wright * Processes the snapshot data.
844148c5f43SAlan Wright */
845148c5f43SAlan Wright static void
smbstat_srv_process(void)846148c5f43SAlan Wright smbstat_srv_process(void)
847148c5f43SAlan Wright {
848148c5f43SAlan Wright smbstat_srv_snapshot_t *curr, *prev;
849148c5f43SAlan Wright
850148c5f43SAlan Wright curr = smbstat_srv_current_snapshot();
851148c5f43SAlan Wright prev = smbstat_srv_previous_snapshot();
852148c5f43SAlan Wright
853148c5f43SAlan Wright if (prev->ss_snaptime == 0)
854148c5f43SAlan Wright smbstat_srv_info.si_hretime =
855148c5f43SAlan Wright smbstat_hrtime_delta(curr->ss_data.ks_start_time,
856148c5f43SAlan Wright curr->ss_snaptime);
857148c5f43SAlan Wright else
858148c5f43SAlan Wright smbstat_srv_info.si_hretime =
859148c5f43SAlan Wright smbstat_hrtime_delta(prev->ss_snaptime, curr->ss_snaptime);
860148c5f43SAlan Wright
861148c5f43SAlan Wright smbstat_srv_info.si_etime = smbstat_srv_info.si_hretime / NANOSEC;
862148c5f43SAlan Wright smbstat_srv_info.si_total_nreqs =
863148c5f43SAlan Wright smbstat_sub_64(curr->ss_data.ks_nreq, prev->ss_data.ks_nreq);
864148c5f43SAlan Wright
865148c5f43SAlan Wright if (smbstat_opt_c)
866148c5f43SAlan Wright smbstat_srv_process_counters(curr);
867148c5f43SAlan Wright if (smbstat_opt_t)
868148c5f43SAlan Wright smbstat_srv_process_throughput(curr, prev);
869148c5f43SAlan Wright if (smbstat_opt_u)
870148c5f43SAlan Wright smbstat_srv_process_utilization(curr, prev);
871148c5f43SAlan Wright if (smbstat_opt_r)
872148c5f43SAlan Wright smbstat_srv_process_requests(curr, prev);
873148c5f43SAlan Wright }
874148c5f43SAlan Wright
875148c5f43SAlan Wright /*
876148c5f43SAlan Wright * smbstat_srv_process_counters
877148c5f43SAlan Wright */
878148c5f43SAlan Wright static void
smbstat_srv_process_counters(smbstat_srv_snapshot_t * curr)879148c5f43SAlan Wright smbstat_srv_process_counters(smbstat_srv_snapshot_t *curr)
880148c5f43SAlan Wright {
881148c5f43SAlan Wright smbstat_srv_info.si_nbt_sess = curr->ss_data.ks_nbt_sess;
882148c5f43SAlan Wright smbstat_srv_info.si_tcp_sess = curr->ss_data.ks_tcp_sess;
883148c5f43SAlan Wright smbstat_srv_info.si_users = curr->ss_data.ks_users;
884148c5f43SAlan Wright smbstat_srv_info.si_trees = curr->ss_data.ks_trees;
885148c5f43SAlan Wright smbstat_srv_info.si_files = curr->ss_data.ks_files;
886148c5f43SAlan Wright smbstat_srv_info.si_pipes = curr->ss_data.ks_pipes;
887148c5f43SAlan Wright }
888148c5f43SAlan Wright
889148c5f43SAlan Wright /*
890148c5f43SAlan Wright * smbstat_srv_process_throughput
891148c5f43SAlan Wright *
892148c5f43SAlan Wright * Processes the data relative to the throughput of the smbsrv module and
893148c5f43SAlan Wright * stores the results in the structure smbstat_srv_info.
894148c5f43SAlan Wright */
895148c5f43SAlan Wright static void
smbstat_srv_process_throughput(smbstat_srv_snapshot_t * curr,smbstat_srv_snapshot_t * prev)896148c5f43SAlan Wright smbstat_srv_process_throughput(
897148c5f43SAlan Wright smbstat_srv_snapshot_t *curr,
898148c5f43SAlan Wright smbstat_srv_snapshot_t *prev)
899148c5f43SAlan Wright {
900148c5f43SAlan Wright smbstat_srv_info.si_tbs =
901148c5f43SAlan Wright smbstat_sub_64(curr->ss_data.ks_txb, prev->ss_data.ks_txb);
902148c5f43SAlan Wright smbstat_srv_info.si_tbs /= smbstat_srv_info.si_etime;
903148c5f43SAlan Wright smbstat_srv_info.si_rbs =
904148c5f43SAlan Wright smbstat_sub_64(curr->ss_data.ks_rxb, prev->ss_data.ks_rxb);
905148c5f43SAlan Wright smbstat_srv_info.si_rbs /= smbstat_srv_info.si_etime;
906148c5f43SAlan Wright smbstat_srv_info.si_rqs = smbstat_srv_info.si_total_nreqs;
907148c5f43SAlan Wright smbstat_srv_info.si_rqs /= smbstat_srv_info.si_etime;
908148c5f43SAlan Wright
909148c5f43SAlan Wright smbstat_srv_info.si_rds = smbstat_sub_64(
910a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_READ].kr_nreq,
911a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_READ].kr_nreq);
912a90cf9f2SGordon Ross smbstat_srv_info.si_rds += smbstat_sub_64(
913a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_LOCK_AND_READ].kr_nreq,
914a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_LOCK_AND_READ].kr_nreq);
915148c5f43SAlan Wright smbstat_srv_info.si_rds += smbstat_sub_64(
916a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_READ_RAW].kr_nreq,
917a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_READ_RAW].kr_nreq);
918148c5f43SAlan Wright smbstat_srv_info.si_rds += smbstat_sub_64(
919a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_READ_ANDX].kr_nreq,
920a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_READ_ANDX].kr_nreq);
921148c5f43SAlan Wright smbstat_srv_info.si_rds += smbstat_sub_64(
922a90cf9f2SGordon Ross curr->ss_data.ks_reqs2[SMB2_READ].kr_nreq,
923a90cf9f2SGordon Ross prev->ss_data.ks_reqs2[SMB2_READ].kr_nreq);
924148c5f43SAlan Wright smbstat_srv_info.si_rds /= smbstat_srv_info.si_etime;
925148c5f43SAlan Wright
926148c5f43SAlan Wright smbstat_srv_info.si_wrs = smbstat_sub_64(
927a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE].kr_nreq,
928a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE].kr_nreq);
929148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64(
930a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE_AND_UNLOCK].kr_nreq,
931a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE_AND_UNLOCK].kr_nreq);
932148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64(
933a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE_RAW].kr_nreq,
934a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE_RAW].kr_nreq);
935148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64(
936a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE_AND_CLOSE].kr_nreq,
937a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE_AND_CLOSE].kr_nreq);
938148c5f43SAlan Wright smbstat_srv_info.si_wrs += smbstat_sub_64(
939a90cf9f2SGordon Ross curr->ss_data.ks_reqs1[SMB_COM_WRITE_ANDX].kr_nreq,
940a90cf9f2SGordon Ross prev->ss_data.ks_reqs1[SMB_COM_WRITE_ANDX].kr_nreq);
941a90cf9f2SGordon Ross smbstat_srv_info.si_wrs += smbstat_sub_64(
942a90cf9f2SGordon Ross curr->ss_data.ks_reqs2[SMB2_WRITE].kr_nreq,
943a90cf9f2SGordon Ross prev->ss_data.ks_reqs2[SMB2_WRITE].kr_nreq);
944148c5f43SAlan Wright smbstat_srv_info.si_wrs /= smbstat_srv_info.si_etime;
945148c5f43SAlan Wright }
946148c5f43SAlan Wright
947148c5f43SAlan Wright /*
948148c5f43SAlan Wright * smbstat_srv_process_utilization
949148c5f43SAlan Wright *
950148c5f43SAlan Wright * Processes the data relative to the utilization of the smbsrv module and
951148c5f43SAlan Wright * stores the results in the structure smbstat_srv_info.
952148c5f43SAlan Wright */
953148c5f43SAlan Wright static void
smbstat_srv_process_utilization(smbstat_srv_snapshot_t * curr,smbstat_srv_snapshot_t * prev)954148c5f43SAlan Wright smbstat_srv_process_utilization(
955148c5f43SAlan Wright smbstat_srv_snapshot_t *curr,
956148c5f43SAlan Wright smbstat_srv_snapshot_t *prev)
957148c5f43SAlan Wright {
958148c5f43SAlan Wright double tw_delta, tr_delta;
959148c5f43SAlan Wright double w_delta, r_delta;
960148c5f43SAlan Wright double tps, rqs;
961148c5f43SAlan Wright
962148c5f43SAlan Wright w_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_wlentime,
963148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_wlentime);
964148c5f43SAlan Wright r_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_rlentime,
965148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_rlentime);
966148c5f43SAlan Wright tw_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_wtime,
967148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_wtime);
968148c5f43SAlan Wright tr_delta = smbstat_hrtime_delta(prev->ss_data.ks_utilization.ku_rtime,
969148c5f43SAlan Wright curr->ss_data.ks_utilization.ku_rtime);
970148c5f43SAlan Wright rqs = smbstat_srv_info.si_total_nreqs / smbstat_srv_info.si_etime;
971148c5f43SAlan Wright
972148c5f43SAlan Wright /* Average number of requests waiting */
973148c5f43SAlan Wright if (w_delta != 0)
974148c5f43SAlan Wright smbstat_srv_info.si_avw = w_delta / smbstat_srv_info.si_hretime;
975148c5f43SAlan Wright else
976148c5f43SAlan Wright smbstat_srv_info.si_avw = 0.0;
977148c5f43SAlan Wright
978148c5f43SAlan Wright /* Average number of request running */
979148c5f43SAlan Wright if (r_delta != 0)
980148c5f43SAlan Wright smbstat_srv_info.si_avr = r_delta / smbstat_srv_info.si_hretime;
981148c5f43SAlan Wright else
982148c5f43SAlan Wright smbstat_srv_info.si_avr = 0.0;
983148c5f43SAlan Wright
984148c5f43SAlan Wright /* Utilization */
985148c5f43SAlan Wright smbstat_srv_info.si_upct =
986148c5f43SAlan Wright (smbstat_srv_info.si_avr / curr->ss_data.ks_maxreqs) * 100;
987148c5f43SAlan Wright
988148c5f43SAlan Wright /* Average wait service time in milliseconds */
989148c5f43SAlan Wright smbstat_srv_info.si_rserv = 0.0;
990148c5f43SAlan Wright smbstat_srv_info.si_wserv = 0.0;
991148c5f43SAlan Wright if (rqs > 0.0 &&
992148c5f43SAlan Wright (smbstat_srv_info.si_avw != 0.0 ||
993148c5f43SAlan Wright smbstat_srv_info.si_avr != 0.0)) {
994148c5f43SAlan Wright tps = 1 / rqs;
995148c5f43SAlan Wright if (smbstat_srv_info.si_avw != 0.0)
996148c5f43SAlan Wright smbstat_srv_info.si_wserv =
997148c5f43SAlan Wright smbstat_srv_info.si_avw * tps;
998148c5f43SAlan Wright if (smbstat_srv_info.si_avr != 0.0)
999148c5f43SAlan Wright smbstat_srv_info.si_rserv =
1000148c5f43SAlan Wright smbstat_srv_info.si_avr * tps;
1001148c5f43SAlan Wright }
1002148c5f43SAlan Wright
1003148c5f43SAlan Wright /* % of time there is a transaction waiting for service */
1004148c5f43SAlan Wright if (tw_delta != 0) {
1005148c5f43SAlan Wright smbstat_srv_info.si_wpct = tw_delta;
1006148c5f43SAlan Wright smbstat_srv_info.si_wpct /= smbstat_srv_info.si_hretime;
1007148c5f43SAlan Wright smbstat_srv_info.si_wpct *= 100.0;
1008148c5f43SAlan Wright } else {
1009148c5f43SAlan Wright smbstat_srv_info.si_wpct = 0.0;
1010148c5f43SAlan Wright }
1011148c5f43SAlan Wright
1012148c5f43SAlan Wright /* % of time there is a transaction running */
1013148c5f43SAlan Wright if (tr_delta != 0) {
1014148c5f43SAlan Wright smbstat_srv_info.si_rpct = tr_delta;
1015148c5f43SAlan Wright smbstat_srv_info.si_rpct /= smbstat_srv_info.si_hretime;
1016148c5f43SAlan Wright smbstat_srv_info.si_rpct *= 100.0;
1017148c5f43SAlan Wright } else {
1018148c5f43SAlan Wright smbstat_srv_info.si_rpct = 0.0;
1019da6c28aaSamw }
1020da6c28aaSamw }
1021da6c28aaSamw
1022148c5f43SAlan Wright /*
1023148c5f43SAlan Wright * smbstat_srv_process_requests
1024148c5f43SAlan Wright *
1025148c5f43SAlan Wright * Processes the data relative to the SMB requests and stores the results in
1026148c5f43SAlan Wright * the structure smbstat_srv_info.
1027148c5f43SAlan Wright */
1028da6c28aaSamw static void
smbstat_srv_process_requests(smbstat_srv_snapshot_t * curr,smbstat_srv_snapshot_t * prev)1029148c5f43SAlan Wright smbstat_srv_process_requests(
1030148c5f43SAlan Wright smbstat_srv_snapshot_t *curr,
1031148c5f43SAlan Wright smbstat_srv_snapshot_t *prev)
1032da6c28aaSamw {
1033148c5f43SAlan Wright smbstat_req_info_t *info;
1034a90cf9f2SGordon Ross smb_kstat_req_t *curr_req;
1035a90cf9f2SGordon Ross smb_kstat_req_t *prev_req;
1036148c5f43SAlan Wright int i, idx;
1037a90cf9f2SGordon Ross boolean_t firstcall = (prev->ss_snaptime == 0);
1038da6c28aaSamw
10398365a6eaSGordon Ross for (i = 0; i < SMBSRV_KS_NREQS1; i++) {
1040a90cf9f2SGordon Ross info = &smbstat_srv_info.si_reqs1[i];
10415015ecc3SGordon Ross idx = info->ri_opcode;
10428365a6eaSGordon Ross if (idx >= SMBSRV_KS_NREQS1)
10435015ecc3SGordon Ross continue;
1044a90cf9f2SGordon Ross curr_req = &curr->ss_data.ks_reqs1[idx];
1045a90cf9f2SGordon Ross prev_req = &prev->ss_data.ks_reqs1[idx];
1046a90cf9f2SGordon Ross smbstat_srv_process_one_req(
1047a90cf9f2SGordon Ross info, curr_req, prev_req, firstcall);
1048a90cf9f2SGordon Ross }
1049a90cf9f2SGordon Ross
10508365a6eaSGordon Ross for (i = 0; i < SMBSRV_KS_NREQS2; i++) {
1051a90cf9f2SGordon Ross info = &smbstat_srv_info.si_reqs2[i];
10525015ecc3SGordon Ross idx = info->ri_opcode;
10538365a6eaSGordon Ross if (idx >= SMBSRV_KS_NREQS2)
10545015ecc3SGordon Ross continue;
10555015ecc3SGordon Ross curr_req = &curr->ss_data.ks_reqs2[idx];
10565015ecc3SGordon Ross prev_req = &prev->ss_data.ks_reqs2[idx];
1057a90cf9f2SGordon Ross smbstat_srv_process_one_req(
1058a90cf9f2SGordon Ross info, curr_req, prev_req, firstcall);
1059a90cf9f2SGordon Ross }
1060a90cf9f2SGordon Ross }
1061a90cf9f2SGordon Ross
1062a90cf9f2SGordon Ross static void
smbstat_srv_process_one_req(smbstat_req_info_t * info,smb_kstat_req_t * curr_req,smb_kstat_req_t * prev_req,boolean_t firstcall)1063a90cf9f2SGordon Ross smbstat_srv_process_one_req(
1064a90cf9f2SGordon Ross smbstat_req_info_t *info,
1065a90cf9f2SGordon Ross smb_kstat_req_t *curr_req,
1066a90cf9f2SGordon Ross smb_kstat_req_t *prev_req,
1067a90cf9f2SGordon Ross boolean_t firstcall)
1068a90cf9f2SGordon Ross {
1069a90cf9f2SGordon Ross double nrqs;
1070a90cf9f2SGordon Ross
1071a90cf9f2SGordon Ross nrqs = smbstat_sub_64(curr_req->kr_nreq,
1072a90cf9f2SGordon Ross prev_req->kr_nreq);
1073a90cf9f2SGordon Ross
1074a90cf9f2SGordon Ross info->ri_rqs = nrqs / smbstat_srv_info.si_etime;
1075a90cf9f2SGordon Ross
1076a90cf9f2SGordon Ross info->ri_rbs = smbstat_sub_64(
1077a90cf9f2SGordon Ross curr_req->kr_rxb,
1078a90cf9f2SGordon Ross prev_req->kr_rxb) /
1079a90cf9f2SGordon Ross smbstat_srv_info.si_etime;
1080a90cf9f2SGordon Ross
1081a90cf9f2SGordon Ross info->ri_tbs = smbstat_sub_64(
1082a90cf9f2SGordon Ross curr_req->kr_txb,
1083a90cf9f2SGordon Ross prev_req->kr_txb) /
1084a90cf9f2SGordon Ross smbstat_srv_info.si_etime;
1085a90cf9f2SGordon Ross
1086a90cf9f2SGordon Ross info->ri_pct = nrqs * 100;
1087a90cf9f2SGordon Ross if (smbstat_srv_info.si_total_nreqs > 0)
1088a90cf9f2SGordon Ross info->ri_pct /= smbstat_srv_info.si_total_nreqs;
1089a90cf9f2SGordon Ross
1090a90cf9f2SGordon Ross if (firstcall) {
1091a90cf9f2SGordon Ross /* First time. Take the aggregate */
1092a90cf9f2SGordon Ross info->ri_stddev =
1093a90cf9f2SGordon Ross curr_req->kr_a_stddev;
1094a90cf9f2SGordon Ross info->ri_mean = curr_req->kr_a_mean;
1095a90cf9f2SGordon Ross } else {
1096a90cf9f2SGordon Ross /* Take the differential */
1097a90cf9f2SGordon Ross info->ri_stddev =
1098a90cf9f2SGordon Ross curr_req->kr_d_stddev;
1099a90cf9f2SGordon Ross info->ri_mean = curr_req->kr_d_mean;
1100a90cf9f2SGordon Ross }
1101a90cf9f2SGordon Ross if (nrqs > 0) {
1102a90cf9f2SGordon Ross info->ri_stddev /= nrqs;
1103a90cf9f2SGordon Ross info->ri_stddev = sqrt(info->ri_stddev);
1104a90cf9f2SGordon Ross } else {
1105a90cf9f2SGordon Ross info->ri_stddev = 0;
1106da6c28aaSamw }
1107a90cf9f2SGordon Ross info->ri_stddev /= NANOSEC;
1108a90cf9f2SGordon Ross info->ri_mean /= NANOSEC;
1109da6c28aaSamw }
1110da6c28aaSamw
1111a90cf9f2SGordon Ross
1112148c5f43SAlan Wright /*
1113148c5f43SAlan Wright * smbstat_srv_current_snapshot
1114148c5f43SAlan Wright *
1115148c5f43SAlan Wright * Returns the current snapshot.
1116148c5f43SAlan Wright */
1117148c5f43SAlan Wright static smbstat_srv_snapshot_t *
smbstat_srv_current_snapshot(void)1118148c5f43SAlan Wright smbstat_srv_current_snapshot(void)
1119148c5f43SAlan Wright {
1120148c5f43SAlan Wright return (&smbstat_srv_snapshots[smbstat_snapshot_idx]);
1121148c5f43SAlan Wright }
1122148c5f43SAlan Wright
1123148c5f43SAlan Wright /*
1124148c5f43SAlan Wright * smbstat_srv_previous_snapshot
1125148c5f43SAlan Wright *
1126148c5f43SAlan Wright * Returns the previous snapshot.
1127148c5f43SAlan Wright */
1128148c5f43SAlan Wright static smbstat_srv_snapshot_t *
smbstat_srv_previous_snapshot(void)1129148c5f43SAlan Wright smbstat_srv_previous_snapshot(void)
1130148c5f43SAlan Wright {
1131148c5f43SAlan Wright int idx;
1132148c5f43SAlan Wright
1133148c5f43SAlan Wright idx = (smbstat_snapshot_idx - 1) & SMBSTAT_SNAPSHOT_MASK;
1134148c5f43SAlan Wright return (&smbstat_srv_snapshots[idx]);
1135148c5f43SAlan Wright }
1136148c5f43SAlan Wright
1137148c5f43SAlan Wright /*
1138148c5f43SAlan Wright * smbstat_usage
1139148c5f43SAlan Wright *
1140148c5f43SAlan Wright * Prints out a help message.
1141148c5f43SAlan Wright */
1142da6c28aaSamw static void
smbstat_usage(FILE * fd,int exit_code)1143148c5f43SAlan Wright smbstat_usage(FILE *fd, int exit_code)
1144da6c28aaSamw {
1145148c5f43SAlan Wright (void) fprintf(fd, gettext(SMBSTAT_HELP));
1146148c5f43SAlan Wright exit(exit_code);
1147da6c28aaSamw }
1148da6c28aaSamw
1149148c5f43SAlan Wright /*
1150148c5f43SAlan Wright * smbstat_fail
1151148c5f43SAlan Wright *
1152148c5f43SAlan Wright * Prints out to stderr an error message and exits the process.
1153148c5f43SAlan Wright */
1154da6c28aaSamw static void
smbstat_fail(int do_perror,char * message,...)1155da6c28aaSamw smbstat_fail(int do_perror, char *message, ...)
1156da6c28aaSamw {
1157da6c28aaSamw va_list args;
1158da6c28aaSamw
1159da6c28aaSamw va_start(args, message);
1160da6c28aaSamw (void) fprintf(stderr, gettext("smbstat: "));
1161da6c28aaSamw /* LINTED E_SEC_PRINTF_VAR_FMT */
1162da6c28aaSamw (void) vfprintf(stderr, message, args);
1163da6c28aaSamw va_end(args);
1164da6c28aaSamw if (do_perror)
1165da6c28aaSamw (void) fprintf(stderr, ": %s", strerror(errno));
1166da6c28aaSamw (void) fprintf(stderr, "\n");
1167da6c28aaSamw exit(1);
1168da6c28aaSamw }
1169da6c28aaSamw
1170148c5f43SAlan Wright /*
1171148c5f43SAlan Wright * smbstat_sub_64
1172148c5f43SAlan Wright *
1173148c5f43SAlan Wright * Substract 2 uint64_t and returns a double.
1174148c5f43SAlan Wright */
1175148c5f43SAlan Wright static double
smbstat_sub_64(uint64_t a,uint64_t b)1176148c5f43SAlan Wright smbstat_sub_64(uint64_t a, uint64_t b)
1177da6c28aaSamw {
1178148c5f43SAlan Wright return ((double)(a - b));
1179148c5f43SAlan Wright }
1180da6c28aaSamw
1181148c5f43SAlan Wright /*
1182148c5f43SAlan Wright * smbstat_zero
1183148c5f43SAlan Wright *
1184148c5f43SAlan Wright * Returns zero if the value passed in is less than 1.
1185148c5f43SAlan Wright */
1186148c5f43SAlan Wright static double
smbstat_zero(double value)1187148c5f43SAlan Wright smbstat_zero(double value)
1188148c5f43SAlan Wright {
1189148c5f43SAlan Wright if (value < 1)
1190148c5f43SAlan Wright value = 0;
1191148c5f43SAlan Wright return (value);
1192148c5f43SAlan Wright }
1193148c5f43SAlan Wright
1194148c5f43SAlan Wright /*
1195148c5f43SAlan Wright * smbstat_strtoi
1196148c5f43SAlan Wright *
1197148c5f43SAlan Wright * Converts a string representing an integer value into its binary value.
1198148c5f43SAlan Wright * If the conversion fails this routine exits the process.
1199148c5f43SAlan Wright */
1200148c5f43SAlan Wright static uint_t
smbstat_strtoi(char const * val,char * errmsg)1201148c5f43SAlan Wright smbstat_strtoi(char const *val, char *errmsg)
1202148c5f43SAlan Wright {
1203148c5f43SAlan Wright char *end;
1204148c5f43SAlan Wright long tmp;
1205148c5f43SAlan Wright
1206148c5f43SAlan Wright errno = 0;
1207148c5f43SAlan Wright tmp = strtol(val, &end, 10);
1208148c5f43SAlan Wright if (*end != '\0' || errno)
1209148c5f43SAlan Wright smbstat_fail(1, "%s %s", errmsg, val);
1210148c5f43SAlan Wright return ((uint_t)tmp);
1211148c5f43SAlan Wright }
1212148c5f43SAlan Wright
1213148c5f43SAlan Wright /*
1214148c5f43SAlan Wright * smbstat_termio_init
1215148c5f43SAlan Wright *
1216148c5f43SAlan Wright * Determines the size of the terminal associated with the process.
1217148c5f43SAlan Wright */
1218148c5f43SAlan Wright static void
smbstat_termio_init(void)1219148c5f43SAlan Wright smbstat_termio_init(void)
1220148c5f43SAlan Wright {
1221148c5f43SAlan Wright char *envp;
1222148c5f43SAlan Wright
1223148c5f43SAlan Wright if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &smbstat_ws) != -1) {
1224148c5f43SAlan Wright if (smbstat_ws.ws_row == 0) {
1225148c5f43SAlan Wright envp = getenv("LINES");
1226148c5f43SAlan Wright if (envp != NULL)
1227148c5f43SAlan Wright smbstat_ws.ws_row = atoi(envp);
1228148c5f43SAlan Wright }
1229148c5f43SAlan Wright
1230148c5f43SAlan Wright if (smbstat_ws.ws_col == 0) {
1231148c5f43SAlan Wright envp = getenv("COLUMNS");
1232148c5f43SAlan Wright if (envp != NULL)
1233148c5f43SAlan Wright smbstat_ws.ws_row = atoi(envp);
1234148c5f43SAlan Wright }
1235148c5f43SAlan Wright }
1236148c5f43SAlan Wright if (smbstat_ws.ws_col == 0)
1237148c5f43SAlan Wright smbstat_ws.ws_col = 80;
1238148c5f43SAlan Wright if (smbstat_ws.ws_row == 0)
1239148c5f43SAlan Wright smbstat_ws.ws_row = 25;
1240148c5f43SAlan Wright }
1241148c5f43SAlan Wright
1242148c5f43SAlan Wright /*
1243148c5f43SAlan Wright * smbstat_snapshot_idx_inc
1244148c5f43SAlan Wright *
1245148c5f43SAlan Wright * Increments the snapshot index.
1246148c5f43SAlan Wright */
1247148c5f43SAlan Wright static void
smbstat_snapshot_inc_idx(void)1248148c5f43SAlan Wright smbstat_snapshot_inc_idx(void)
1249148c5f43SAlan Wright {
1250148c5f43SAlan Wright smbstat_snapshot_idx++;
1251148c5f43SAlan Wright smbstat_snapshot_idx &= SMBSTAT_SNAPSHOT_MASK;
1252da6c28aaSamw }
1253da6c28aaSamw
1254da6c28aaSamw /*
1255148c5f43SAlan Wright * smbstat_req_cmp_name
1256148c5f43SAlan Wright *
1257148c5f43SAlan Wright * Call back function passed to qsort() when the list of requests must be sorted
1258148c5f43SAlan Wright * by name.
1259da6c28aaSamw */
1260148c5f43SAlan Wright static int
smbstat_req_cmp_name(const void * obj1,const void * obj2)1261148c5f43SAlan Wright smbstat_req_cmp_name(const void *obj1, const void *obj2)
1262da6c28aaSamw {
1263148c5f43SAlan Wright return (strncasecmp(
1264148c5f43SAlan Wright ((smbstat_req_info_t *)obj1)->ri_name,
1265148c5f43SAlan Wright ((smbstat_req_info_t *)obj2)->ri_name,
1266148c5f43SAlan Wright sizeof (((smbstat_req_info_t *)obj2)->ri_name)));
1267da6c28aaSamw }
1268da6c28aaSamw
1269148c5f43SAlan Wright /*
1270148c5f43SAlan Wright * smbstat_req_order
1271148c5f43SAlan Wright *
1272148c5f43SAlan Wright * Snapshots the smbsrv module statistics once to get the name of the requests.
1273148c5f43SAlan Wright * The request list is smbstat_srv_info is then sorted by name or by code
1274148c5f43SAlan Wright * depending on the boolean smbstat_opt_a.
1275148c5f43SAlan Wright * The function should be called once during initialization.
1276148c5f43SAlan Wright */
1277148c5f43SAlan Wright static void
smbstat_req_order(void)1278148c5f43SAlan Wright smbstat_req_order(void)
1279148c5f43SAlan Wright {
1280a90cf9f2SGordon Ross smbstat_srv_snapshot_t *ss;
1281148c5f43SAlan Wright smbstat_req_info_t *info;
1282148c5f43SAlan Wright smb_kstat_req_t *reqs;
1283148c5f43SAlan Wright int i;
1284148c5f43SAlan Wright
1285148c5f43SAlan Wright smbstat_srv_snapshot();
1286a90cf9f2SGordon Ross ss = smbstat_srv_current_snapshot();
1287148c5f43SAlan Wright
1288a90cf9f2SGordon Ross reqs = ss->ss_data.ks_reqs1;
1289a90cf9f2SGordon Ross info = smbstat_srv_info.si_reqs1;
12908365a6eaSGordon Ross for (i = 0; i < SMBSRV_KS_NREQS1; i++) {
1291148c5f43SAlan Wright (void) strlcpy(info[i].ri_name, reqs[i].kr_name,
1292148c5f43SAlan Wright sizeof (reqs[i].kr_name));
1293148c5f43SAlan Wright info[i].ri_opcode = i;
1294148c5f43SAlan Wright }
1295148c5f43SAlan Wright if (smbstat_opt_n)
12968365a6eaSGordon Ross qsort(info, SMBSRV_KS_NREQS1, sizeof (smbstat_req_info_t),
1297148c5f43SAlan Wright smbstat_req_cmp_name);
1298a90cf9f2SGordon Ross
1299a90cf9f2SGordon Ross reqs = ss->ss_data.ks_reqs2;
1300a90cf9f2SGordon Ross info = smbstat_srv_info.si_reqs2;
13018365a6eaSGordon Ross for (i = 0; i < SMBSRV_KS_NREQS2; i++) {
1302a90cf9f2SGordon Ross (void) strlcpy(info[i].ri_name, reqs[i].kr_name,
1303a90cf9f2SGordon Ross sizeof (reqs[i].kr_name));
1304a90cf9f2SGordon Ross info[i].ri_opcode = i;
1305a90cf9f2SGordon Ross }
1306a90cf9f2SGordon Ross if (smbstat_opt_n)
13078365a6eaSGordon Ross qsort(info, SMBSRV_KS_NREQS2, sizeof (smbstat_req_info_t),
1308a90cf9f2SGordon Ross smbstat_req_cmp_name);
1309148c5f43SAlan Wright }
1310148c5f43SAlan Wright
1311148c5f43SAlan Wright /*
1312148c5f43SAlan Wright * Return the number of ticks delta between two hrtime_t
1313148c5f43SAlan Wright * values. Attempt to cater for various kinds of overflow
1314148c5f43SAlan Wright * in hrtime_t - no matter how improbable.
1315148c5f43SAlan Wright */
1316148c5f43SAlan Wright static double
smbstat_hrtime_delta(hrtime_t old,hrtime_t new)1317148c5f43SAlan Wright smbstat_hrtime_delta(hrtime_t old, hrtime_t new)
1318148c5f43SAlan Wright {
1319148c5f43SAlan Wright uint64_t del;
1320148c5f43SAlan Wright
1321148c5f43SAlan Wright if ((new >= old) && (old >= 0L))
1322148c5f43SAlan Wright return ((double)(new - old));
1323148c5f43SAlan Wright /*
1324148c5f43SAlan Wright * We've overflowed the positive portion of an hrtime_t.
1325148c5f43SAlan Wright */
1326148c5f43SAlan Wright if (new < 0L) {
1327148c5f43SAlan Wright /*
1328148c5f43SAlan Wright * The new value is negative. Handle the case where the old
1329148c5f43SAlan Wright * value is positive or negative.
1330148c5f43SAlan Wright */
1331148c5f43SAlan Wright uint64_t n1;
1332148c5f43SAlan Wright uint64_t o1;
1333148c5f43SAlan Wright
1334148c5f43SAlan Wright n1 = -new;
1335148c5f43SAlan Wright if (old > 0L)
1336148c5f43SAlan Wright return ((double)(n1 - old));
1337148c5f43SAlan Wright
1338148c5f43SAlan Wright o1 = -old;
1339148c5f43SAlan Wright del = n1 - o1;
1340148c5f43SAlan Wright return ((double)del);
1341148c5f43SAlan Wright }
1342148c5f43SAlan Wright
1343148c5f43SAlan Wright /*
1344148c5f43SAlan Wright * Either we've just gone from being negative to positive *or* the last
1345148c5f43SAlan Wright * entry was positive and the new entry is also positive but *less* than
1346148c5f43SAlan Wright * the old entry. This implies we waited quite a few days on a very fast
1347148c5f43SAlan Wright * system between displays.
1348148c5f43SAlan Wright */
1349148c5f43SAlan Wright if (old < 0L) {
1350148c5f43SAlan Wright uint64_t o2;
1351148c5f43SAlan Wright o2 = -old;
1352148c5f43SAlan Wright del = UINT64_MAX - o2;
1353148c5f43SAlan Wright } else {
1354148c5f43SAlan Wright del = UINT64_MAX - old;
1355148c5f43SAlan Wright }
1356148c5f43SAlan Wright del += new;
1357148c5f43SAlan Wright return ((double)del);
1358148c5f43SAlan Wright }
1359148c5f43SAlan Wright
1360148c5f43SAlan Wright static void *
smbstat_zalloc(size_t size)1361148c5f43SAlan Wright smbstat_zalloc(size_t size)
1362148c5f43SAlan Wright {
1363148c5f43SAlan Wright void *ptr;
1364148c5f43SAlan Wright
1365148c5f43SAlan Wright ptr = umem_zalloc(size, UMEM_DEFAULT);
1366148c5f43SAlan Wright if (ptr == NULL)
1367148c5f43SAlan Wright smbstat_fail(1, gettext("out of memory"));
1368148c5f43SAlan Wright return (ptr);
1369148c5f43SAlan Wright }
1370148c5f43SAlan Wright
1371148c5f43SAlan Wright static void
smbstat_free(void * ptr,size_t size)1372148c5f43SAlan Wright smbstat_free(void *ptr, size_t size)
1373da6c28aaSamw {
1374148c5f43SAlan Wright umem_free(ptr, size);
1375da6c28aaSamw }
1376