4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
36 #include <sys/types.h>
38 #include <sys/nsctl/sdbc_ioctl.h>
39 #include <sys/unistat/spcs_s_u.h>
40 #include <sys/nsctl/sd_bcache.h>
41 #include <sys/nsctl/sd_conf.h>
43 extern void total_display(void);
44 extern void display_cache(void);
45 extern void wrefresh_file(WINDOW
*, int);
46 extern int is_dirty(void);
47 extern int dual_stats(void);
49 void setup_ranges(char *);
51 extern int zero_nic(void);
54 #define USEC_INIT() usec_ptr = (unsigned int *)timer_init()
55 #define USEC_READ() (*usec_ptr)
57 #define USEC_INIT() USEC_START()
59 static struct timeval Usec_time
;
60 static int Usec_started
= 0;
62 extern int higher(int);
63 extern int is_dirty();
64 extern int dual_stats();
65 extern void total_display();
66 extern void display_cache();
67 extern void wrefresh_file(WINDOW
*, int);
68 void setup_ranges(char *);
74 #pragma does_not_return(quit, leave)
76 int sdbc_max_devices
= 0;
82 (void) gettimeofday(&Usec_time
, NULL
);
94 (void) gettimeofday(&tv
, NULL
);
95 return (unsigned)((tv
.tv_sec
- Usec_time
.tv_sec
) * 1000000
96 + (tv
.tv_usec
- Usec_time
.tv_usec
));
100 int rev_flag
= 0; /* Reverse video flag */
101 int bold_flg
= 0; /* Bold flag */
102 int under_flg
= 0; /* Underline flag */
103 int errflg
= 0; /* Error flag */
104 int node_sw
= 0; /* Per node switch */
105 int toggle_total_sw
= 0;
106 int mirror_sw
= 0; /* Dual copy switch */
109 int delay
= 1; /* Display delay (seconds) */
114 int Elapsed_Time
= 0;
117 static int had_r_option
= 0;
118 int logfd
= -1; /* screen output logging */
119 extern int range_num
;
121 extern int dual_screen
;
128 _sd_stats_t
*cs_prev
;
129 _sd_stats_t
*cs_persec
;
135 extern range_t ranges
[];
139 sd_stats_lintmain(int argc
, char *argv
[])
142 main(int argc
, char *argv
[])
145 spcs_s_info_t ustats
;
148 char *errmessage
, *ch
;
150 int count
= 0, dflag
= 0;
151 int fd
= fileno(stdin
);
155 if (strcmp(argv
[0], "sd_stats") != 0)
156 errmessage
= getenv("SD_STATS_USAGE");
158 if (errmessage
== NULL
)
159 errmessage
= gettext("Usage: sd_stats [-Mz] "
160 "[-d delay_time] [-l logfile] [-r range]");
162 if (SDBC_IOCTL(SDBC_MAXFILES
, &sdbc_max_devices
,
163 0, 0, 0, 0, &ustats
) == SPCS_S_ERROR
) {
164 if (ustats
) { /* if SPCS_S_ERROR */
165 spcs_s_report(ustats
, stderr
);
166 spcs_s_ufree(&ustats
);
168 (void) fprintf(stderr
, gettext("cannot get maxfiles\n"));
171 on_off
= calloc(sdbc_max_devices
, sizeof (int));
172 dual_on_off
= calloc(sdbc_max_devices
, sizeof (int));
173 updates_prev
= calloc(sdbc_max_devices
, sizeof (int));
174 samples
= calloc(sdbc_max_devices
, sizeof (int));
175 rate_prev
= calloc(sdbc_max_devices
, sizeof (double));
176 cs_cur
= malloc(sizeof (_sd_stats_t
) +
177 (sdbc_max_devices
- 1) * sizeof (_sd_shared_t
));
178 cs_prev
= malloc(sizeof (_sd_stats_t
) +
179 (sdbc_max_devices
- 1) * sizeof (_sd_shared_t
));
180 cs_persec
= malloc(sizeof (_sd_stats_t
) +
181 (sdbc_max_devices
- 1) * sizeof (_sd_shared_t
));
184 if (!on_off
|| !dual_on_off
|| !updates_prev
|| !samples
||
185 !rate_prev
|| !cs_cur
|| !cs_prev
|| !cs_persec
|| !range
) {
186 (void) fprintf(stderr
, gettext("no free memory\n"));
192 while ((c
= getopt(argc
, argv
, "DMzd:l:r:h")) != EOF
) {
198 delay
= atoi(optarg
);
200 while (*ch
!= '\0') {
208 logfd
= open(optarg
, O_CREAT
|O_WRONLY
|O_TRUNC
, 0644);
213 while (*ch
!= '\0') {
214 if ((!isdigit(*ch
)) && (*ch
!= ',') &&
222 range
= realloc((char *)range
,
223 (strlen(range
) + strlen(optarg
) + 1)
227 (void) strcat(range
, ",");
228 (void) strcat(range
, optarg
);
233 if (SDBC_IOCTL(SDBC_ZAP_STATS
, 0, 0, 0, 0, 0,
234 &ustats
) == SPCS_S_ERROR
) {
236 spcs_s_report(ustats
, stderr
);
237 spcs_s_ufree(&ustats
);
260 (void) fprintf(stderr
, "%s\n", errmessage
);
264 (void) fprintf(stderr
, "%s\n", errmessage
);
275 * A few curses routines to setup screen and tty interface
290 (void) sigset(SIGPIPE
, leave
);
291 (void) sigset(SIGINT
, leave
);
292 (void) sigset(SIGQUIT
, leave
);
293 (void) signal(SIGFPE
, leave
);
294 (void) signal(SIGSEGV
, leave
);
297 currtime
= USEC_READ();
300 * Wait one second before reading the new values
308 currtime
= USEC_READ();
311 * If less that 1 second, force it to one second
313 if ((period
= (currtime
- lasttime
) / 1000000) <= 0)
317 * Calculate new per/period values for statistics
319 Elapsed_Time
+= period
;
322 * Display new statistics
327 if (dual_stats() < 0)
329 } else if (toggle_total_sw
)
336 if (logfd
> -1) wrefresh_file(stdscr
, logfd
);
339 FD_SET(fd
, &readfds
);
343 if (select(fd
+ 1, &readfds
, (fd_set
*)0, (fd_set
*)0,
346 if ((c
= getch()) == EOF
) {
355 #pragma error_messages(off, E_STATEMENT_NOT_REACHED)
357 #pragma error_messages(default, E_STATEMENT_NOT_REACHED)
363 spcs_s_info_t ustats
;
366 case 'b' : /* ctrl b or b -- scroll backward */
369 if (mirror_sw
== 1) {
379 case 'f' : /* ctrl f or f -- scroll forward */
382 if (mirror_sw
== 1) {
395 toggle_total_sw
^= 1;
414 (void) clearok(stdscr
, TRUE
);
420 (void) attroff(A_BOLD
);
423 (void) attron(A_BOLD
);
430 (void) attroff(A_REVERSE
);
433 (void) attron(A_REVERSE
);
438 if (SDBC_IOCTL(SDBC_ZAP_STATS
, 0, 0, 0, 0, 0,
439 &ustats
) == SPCS_S_ERROR
) {
441 spcs_s_report(ustats
, stderr
);
442 spcs_s_ufree(&ustats
);
449 mirror_sw
= mirror_sw
? 0 : 1;
461 * Print sample count in upper left corner
463 (void) mvprintw(0, 0, "SAMPLE %-8d", count
);
466 * Get time and print it in upper right corner
468 tim
= time((time_t *)0);
469 (void) mvprintw(0, 79 - 10, "%-8.8s\n", &(ctime(&tim
)[11]));
476 (void) sigignore(SIGPIPE
);
477 (void) sigignore(SIGALRM
);
479 (void) move(LINES
, 0);
481 if (logfd
> -1) wrefresh_file(stdscr
, logfd
);
494 setup_ranges(char *range
)
498 char prev_chr
= '\0';
500 int after_got_colon
= 0;
502 int after_got_comma
= 0;
506 if (range
== NULL
|| (strlen(range
) == 0)) {
507 ranges
[range_num
].lb
= 0;
508 ranges
[range_num
].ub
= sdbc_max_devices
- 1;
514 while ((chr1
= (range
[ndx
++])) != '\0') {
526 number
= number
*10 + (chr1
- '0');
534 default: /* ignore any unknown characters */
537 if (got_comma
&& after_got_colon
) {
540 if (number
>= sdbc_max_devices
)
541 number
= sdbc_max_devices
- 1;
542 ranges
[range_num
].lb
= prev_num
;
543 ranges
[range_num
].ub
= number
;
544 if (range_num
== 99) break;
547 } else if (got_colon
&& after_got_comma
) {
551 if (number
>= sdbc_max_devices
)
552 number
= sdbc_max_devices
- 1;
555 } else if (got_colon
) {
558 if ((prev_chr
!= '\0') && (prev_chr
!= ':')) {
559 if (number
>= sdbc_max_devices
)
560 number
= sdbc_max_devices
- 1;
564 } else if (got_comma
) {
568 if (number
>= sdbc_max_devices
)
569 number
= sdbc_max_devices
-1;
570 if ((prev_chr
!= '\0') && (prev_chr
!= ',')) {
571 ranges
[range_num
].lb
= number
;
572 ranges
[range_num
].ub
= number
;
573 if (range_num
== 99) break;
580 if (number
>= sdbc_max_devices
)
581 number
= sdbc_max_devices
- 1;
582 if (after_got_colon
) {
583 ranges
[range_num
].lb
= prev_num
;
584 ranges
[range_num
].ub
= number
;
586 if ((after_got_comma
) && (prev_chr
== ','))
589 ranges
[range_num
].lb
= number
;
590 ranges
[range_num
].ub
= number
;