net-snmp sun mods install: make sure destdirs exist
[unleashed-userland.git] / components / sysutils / net-snmp / sun / agent / modules / healthMonitor / kr_iostat.c
blob1b6a54295ddb03fac36f17b8d8654f1466d5b858
1 /*
2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
4 * U.S. Government Rights - Commercial software. Government users are subject
5 * to the Sun Microsystems, Inc. standard license agreement and applicable
6 * provisions of the FAR and its supplements.
9 * This distribution may include materials developed by third parties. Sun,
10 * Sun Microsystems, the Sun logo and Solaris are trademarks or registered
11 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdarg.h>
20 #include <ctype.h>
21 #include <unistd.h>
22 #include <memory.h>
23 #include <string.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <signal.h>
27 #include <kstat.h>
28 #include <stropts.h>
29 #include <poll.h>
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <sys/sysinfo.h>
34 #include <sys/stat.h>
36 kstat_ctl_t *kc; /* libkstat cookie */
37 static int ncpus = -1;
38 typedef struct cpuinfo {
39 kstat_t *cs_kstat;
40 cpu_stat_t cs_old;
41 cpu_stat_t cs_new;
42 } cpuinfo_t;
44 static cpuinfo_t *cpulist = NULL;
46 #define DELTA(i, x) (cpulist[i].cs_new.x - cpulist[i].cs_old.x)
48 static kstat_t **cpu_stat_list = NULL;
49 static cpu_stat_t *cpu_stat_data = NULL;
51 #define DISK_OLD 0x0001
52 #define DISK_NEW 0x0002
53 #define DISK_EXTENDED 0x0004
54 #define DISK_ERRORS 0x0008
55 #define DISK_EXTENDED_ERRORS 0x0010
56 #define DISK_NORMAL (DISK_OLD | DISK_NEW)
58 #define DISK_IO_MASK (DISK_OLD | DISK_NEW | DISK_EXTENDED)
59 #define DISK_ERROR_MASK (DISK_ERRORS | DISK_EXTENDED_ERRORS)
60 #define PRINT_VERTICAL (DISK_ERROR_MASK | DISK_EXTENDED)
62 #define REPRINT 19
65 * Name and print priority of each supported ks_class.
67 #define IO_CLASS_DISK 0
68 #define IO_CLASS_PARTITION 0
69 #define IO_CLASS_TAPE 1
70 #define IO_CLASS_NFS 2
72 struct io_class {
73 char *class_name;
74 int class_priority;
78 #undef printf
79 #undef putchar
80 /*ARGSUSED*/
81 int printf(const char *bar, ...) { return 1; }
82 /*ARGSUSED*/
83 int putchar(int bar){return 1;}
85 static int reentrant = 0;
88 * I've had some strange behavior with "refreshMode = async".
90 #define REENTRANT_BEGIN() { \
91 if (reentrant != 0) \
92 reentrant++; \
95 #define REENTRANT_END() { \
96 reentrant--; \
99 static struct io_class io_class[] = {
100 { "disk", IO_CLASS_DISK},
101 { "partition", IO_CLASS_PARTITION},
102 { NULL, 0}
105 struct diskinfo {
106 struct diskinfo *next;
107 kstat_t *ks;
108 kstat_io_t new_kios, old_kios;
109 int selected;
110 int class;
111 char *device_name;
112 kstat_t *disk_errs; /* pointer to the disk's error kstats */
115 #define DISK_GIGABYTE 1000000000.0
117 static void *dl = 0; /* for device name lookup */
118 extern void *build_disk_list(void *);
119 extern char *lookup_ks_name(char *, void *);
121 #define NULLDISK (struct diskinfo *)0
122 static struct diskinfo zerodisk;
123 static struct diskinfo *firstdisk = NULLDISK;
124 static struct diskinfo *lastdisk = NULLDISK;
125 static struct diskinfo *snip = NULLDISK;
126 static int refreshDiskdetail=0;
127 static int refreshDisksrv=0;
129 static cpu_stat_t old_cpu_stat, new_cpu_stat;
131 #define DISK_DELTA(x) (disk->new_kios.x - disk->old_kios.x)
133 #define CPU_DELTA(x) (new_cpu_stat.x - old_cpu_stat.x)
136 #define PRINT_TTY_DATA(sys, time) \
137 (void) printf(" %3.0f %4.0f",\
138 (float)CPU_DELTA(sys.rawch) / time, \
139 (float)CPU_DELTA(sys.outch) / time);
141 #define PRINT_CPU_DATA(sys, pcnt) \
142 (void) printf(" %2.0f %2.0f %2.0f %2.0f", \
143 CPU_DELTA(sys.cpu[CPU_USER]) * pcnt, \
144 CPU_DELTA(sys.cpu[CPU_KERNEL]) * pcnt, \
145 CPU_DELTA(sys.cpu[CPU_WAIT]) * pcnt, \
146 CPU_DELTA(sys.cpu[CPU_IDLE]) * pcnt);
148 #define PRINT_CPU_HDR1 (void) printf("%12s", "cpu");
149 #define PRINT_CPU_HDR2 (void) printf(" us sy wt id");
150 #define PRINT_TTY_HDR1 (void) printf("%9s", "tty");
151 #define PRINT_TTY_HDR2 (void) printf(" tin tout");
152 #define PRINT_ERR_HDR (void) printf(" ---- errors --- ");
154 static char *cmdname = "iostat";
156 static int do_disk = 0;
157 static int do_cpu = 0;
158 static int do_interval = 0;
159 static int do_partitions = 0; /* collect per-partition stats */
160 static int do_partitions_only = 0; /* collect per-partition stats only */
161 /* no per-device stats for disks */
162 static int do_conversions = 0; /* display disks as cXtYdZ */
163 static int do_megabytes = 0; /* display data in MB/sec */
164 #define DEFAULT_LIMIT 4
165 static int limit = 0; /* limit for drive display */
166 static int ndrives = 0;
168 struct disk_selection {
169 struct disk_selection *next;
170 char ks_name[KSTAT_STRLEN];
173 static struct disk_selection *disk_selections = (struct disk_selection *)NULL;
175 static void show_disk(struct diskinfo *disk, double *rps, double *wps, double *tps, double *krps, double *kwps, double *kps, double *avw, double *avr, double *w_pct, double *r_pct, double *wserv, double *rserv, double *serv);
176 static void cpu_stat_init(void);
178 static int cpu_stat_load(int);
180 static void fail(int, char *, ...);
181 static void safe_zalloc(void **, int, int);
182 static void init_disks(void);
183 static void select_disks(void);
184 static int diskinfo_load(void);
185 static void init_disk_errors(void);
186 static void find_disk(kstat_t *);
188 /* static struct diskinfo *disk; */
189 int first_time = 1;
191 void
192 initialize_everything()
194 if ((kc = kstat_open()) == NULL)
195 return;
196 do_disk |= DISK_EXTENDED /* | DISK_OLD */;
197 do_conversions = 1;
198 do_cpu = 1;
201 * Choose drives to be displayed. Priority
202 * goes to (in order) drives supplied as arguments,
203 * then any other active drives that fit.
205 struct disk_selection **dsp = &disk_selections;
206 *dsp = (struct disk_selection *)NULL;
208 cpu_stat_init();
209 init_disks();
210 #if 0
211 for (disk = firstdisk; disk; disk->next) {
212 number_of_disks++;
214 #endif
215 /* disk = firstdisk; */
216 first_time = 0;
219 int update_kstat_chain(int cpu_save_old_flag)
221 int ret;
223 ret=kstat_chain_update(kc);
224 if (ret == 0) { /* no change */
225 cpu_stat_load(cpu_save_old_flag);
226 diskinfo_load();
227 return 0;
228 } else if (ret > 0) { /* changed */
229 cpu_stat_init();
230 init_disks();
231 if (cpu_stat_load(cpu_save_old_flag)) {
232 return -1;
234 if (diskinfo_load()) {
235 return -1;
237 return 0;
238 } else { /* error */
239 return -1;
243 /* Get Adaptive mutex summary and number of cpus for the system */
245 krgetsmtx(ulong *smtx, int *num_cpus)
247 int i, c, hz, ticks;
248 ulong mutex;
249 double etime, percent;
250 etime = 0;
251 mutex = 0;
253 if ((first_time) || (!kc))
254 initialize_everything();
256 while (update_kstat_chain(1) == -1);
258 /* while (kstat_chain_update(kc) || cpu_stat_load(1)) {
259 (void) cpu_stat_init();
264 hz = sysconf(_SC_CLK_TCK);
265 for (c = 0; c < ncpus; c++) {
266 ticks = 0;
267 for (i = 0; i < CPU_STATES; i++)
268 ticks += DELTA(c, cpu_sysinfo.cpu[i]);
269 etime = (double)ticks / hz;
270 if (etime == 0.0)
271 etime = 1.0;
272 percent = 100.0 / etime / hz;
273 mutex += (int) (DELTA(c, cpu_sysinfo.mutex_adenters) / etime);
275 *num_cpus = ncpus;
276 *smtx = mutex;
278 return 0;
282 krgetcpudetail (cpu_stat_t **cpus, int *num_cpus)
284 REENTRANT_BEGIN();
285 if ((first_time) || (!kc))
286 initialize_everything();
288 while (update_kstat_chain(0) == -1) {
289 /* DPRINTF("ERROR: kstat_chain_update \n");
290 DFFLUSH(stdout);*/
293 *cpus = cpu_stat_data;
294 *num_cpus = ncpus;
295 REENTRANT_END();
296 return 0;
299 /* returns 0 if more disks remain, 1 if the last disk, < 0 on error */
301 krgetdiskdetail(char *name, char *alias, double *rps, double *wps, double *tps, double *krps, double *kwps, double *kps, double *avw, double *avr)
303 double w_pct, r_pct, wserv, rserv, serv;
304 static struct diskinfo *disk = NULL;
306 REENTRANT_BEGIN();
309 if (disk==NULL) disk=firstdisk;
310 if ((first_time) || (!kc)) {
311 initialize_everything();
312 disk=firstdisk;
316 if (refreshDiskdetail) {
317 disk=firstdisk;
318 refreshDiskdetail=0;
321 if (disk == firstdisk) {
322 while (update_kstat_chain(0) == -1) {
323 /* DPRINTF("ERROR: diskdetail - kstat_chain_update \n");
324 DFFLUSH(stdout);*/
328 if (disk) {
329 if (disk->selected) {
330 show_disk(disk, rps, wps, tps, krps, kwps, kps, avw, avr, &w_pct, &r_pct, &wserv, &rserv, &serv);
331 strcpy(name, disk->ks->ks_name);
332 if (disk->device_name != NULL)
333 strcpy(alias, disk->device_name);
334 else
335 strcpy(alias, disk->ks->ks_name);
337 else {
339 disk = disk->next;
341 REENTRANT_END();
342 if (disk == NULL) {
343 disk = firstdisk;
344 return 1;
346 return(0);
349 /* returns 0 if more disks remain, 1 if the last disk, < 0 on error */
351 krgetdisksrv(char *name, char *alias, double *w_pct, double *r_pct, double *wserv, double *rserv, double *serv)
353 static struct diskinfo *disk = NULL;
354 double rps, wps, tps, krps, kwps, kps, avw, avr;
358 if (disk==NULL) disk=firstdisk;
360 if (refreshDisksrv) {
361 disk=firstdisk;
362 refreshDisksrv=0;
364 if (disk) {
365 if (disk->selected) {
366 show_disk(disk, &rps, &wps, &tps, &krps, &kwps, &kps, &avw, &avr, w_pct, r_pct, wserv, rserv, serv);
367 strcpy(name, disk->ks->ks_name);
368 if (disk->device_name != NULL)
369 strcpy(alias, disk->device_name);
370 else
371 strcpy(alias, disk->ks->ks_name);
373 else {
374 /*ddlPrintf(DDL_ERROR, "krgetdisksrv - skipping %s\n", disk->device_name ? disk->device_name : disk->ks->ks_name);*/
376 disk = disk->next;
378 if (disk == NULL) {
379 disk = firstdisk;
380 return 1;
383 return(0);
386 static void
387 show_disk(struct diskinfo *disk, double *Rps, double *Wps, double *Tps, double *Krps, double *Kwps, double *Kps, double *Avw, double *Avr, double *W_pct, double *R_pct, double *Wserv, double *Rserv, double *Serv)
389 double rps, wps, tps, krps, kwps, kps, avw, avr, w_pct, r_pct;
390 double wserv, rserv, serv;
391 double iosize; /* kb/sec or MB/sec */
392 double etime, hr_etime;
394 hr_etime = (double)DISK_DELTA(wlastupdate);
395 if (hr_etime == 0.0)
396 hr_etime = (double)NANOSEC;
397 etime = hr_etime / (double)NANOSEC;
399 rps = (double)DISK_DELTA(reads) / etime;
400 /* reads per second */
402 wps = (double)DISK_DELTA(writes) / etime;
403 /* writes per second */
405 tps = rps + wps;
406 /* transactions per second */
409 * report throughput as either kb/sec or MB/sec
411 if (!do_megabytes) {
412 iosize = 1024.0;
413 } else {
414 iosize = 1048576.0;
416 krps = (double)DISK_DELTA(nread) / etime / iosize;
417 /* block reads per second */
419 kwps = (double)DISK_DELTA(nwritten) / etime / iosize;
420 /* blocks written per second */
422 kps = krps + kwps;
423 /* blocks transferred per second */
425 avw = (double)DISK_DELTA(wlentime) / hr_etime;
426 /* average number of transactions waiting */
428 avr = (double)DISK_DELTA(rlentime) / hr_etime;
429 /* average number of transactions running */
431 wserv = tps > 0 ? (avw / tps) * 1000.0 : 0.0;
432 /* average wait service time in milliseconds */
434 rserv = tps > 0 ? (avr / tps) * 1000.0 : 0.0;
435 /* average run service time in milliseconds */
437 serv = tps > 0 ? ((avw + avr) / tps) * 1000.0 : 0.0;
438 /* average service time in milliseconds */
440 w_pct = (double)DISK_DELTA(wtime) / hr_etime * 100.0;
441 /* % of time there is a transaction waiting for service */
443 r_pct = (double)DISK_DELTA(rtime) / hr_etime * 100.0;
444 /* % of time there is a transaction running */
446 if (do_interval) {
447 rps *= etime;
448 wps *= etime;
449 tps *= etime;
450 krps *= etime;
451 kwps *= etime;
452 kps *= etime;
455 *Rps = rps;
456 *Wps = wps;
457 *Tps = tps;
458 *Krps = krps;
459 *Kwps = kwps;
460 *Kps = kps;
461 *Avw = avw;
462 *Avr = avr;
463 *W_pct = w_pct;
464 *R_pct = r_pct;
465 *Wserv = wserv;
466 *Rserv = rserv;
467 *Serv = serv;
471 * Get list of cpu_stat KIDs for subsequent cpu_stat_load operations.
474 static void
475 cpu_stat_init(void)
477 kstat_t *ksp;
478 int tmp_ncpus;
479 int i;
480 int nb_cpus;
482 tmp_ncpus = 0;
483 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
484 if (strncmp(ksp->ks_name, "cpu_stat", 8) == 0) {
485 tmp_ncpus++;
486 if (kstat_read(kc, ksp, NULL) == -1) {
487 /* ddlPrintf(DDL_ERROR, "cpu_stat_init - kstat_read() failed for cpu:%s\n", ksp->ks_name);*/
493 safe_zalloc((void **) &cpulist, tmp_ncpus * sizeof (cpuinfo_t), 1);
494 safe_zalloc((void **)&cpu_stat_list, tmp_ncpus * sizeof (kstat_t *), 1);
495 safe_zalloc((void *)&cpu_stat_data, tmp_ncpus * sizeof (cpu_stat_t), 1);
497 ncpus = 0;
498 nb_cpus = 0;
499 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
500 if (strncmp(ksp->ks_name, "cpu_stat", 8) == 0) {
501 if (kstat_read(kc, ksp, NULL) != -1) {
502 cpu_stat_list[ncpus++] = ksp;
503 } else {
504 /* ddlPrintf(DDL_ERROR, "cpu_stat_init - kstat_read() failed for cpu:%s\n", ksp->ks_name); */
508 if (strcmp(ksp->ks_module, "cpu_stat") != 0)
509 continue;
511 * insertion sort by CPU id
513 for (i = nb_cpus - 1; i >= 0; i--) {
514 if (cpulist[i].cs_kstat->ks_instance < ksp->ks_instance)
515 break;
516 cpulist[i + 1].cs_kstat = cpulist[i].cs_kstat;
518 cpulist[i + 1].cs_kstat = ksp;
519 nb_cpus++;
523 (void) memset(&new_cpu_stat, 0, sizeof (cpu_stat_t));
525 if ( ncpus != tmp_ncpus ) {
526 /* ddlPrintf(DDL_ERROR, "cpu_stat_init - kstat_read() for some cpu failed, Passed :ncpus=%d Total :tmp_ncpus=%d\n", ncpus, tmp_ncpus); */
531 static int
532 cpu_stat_load(int save_old_flag)
534 int i, j;
535 uint *np, *tp;
537 if (save_old_flag)
538 old_cpu_stat = new_cpu_stat;
539 (void) memset(&new_cpu_stat, 0, sizeof (cpu_stat_t));
541 /* Sum across all cpus */
542 for (i = 0; i < ncpus; i++) {
543 cpulist[i].cs_old = cpulist[i].cs_new;
544 if (kstat_read(kc, cpulist[i].cs_kstat,
545 (void *) &cpulist[i].cs_new) == -1)
546 return (1);
548 if (kstat_read(kc, cpu_stat_list[i], (void *)&cpu_stat_data[i]) == -1) {
549 /* ddlPrintf(DDL_ERROR, "cpu_stat_load - kstat_read() failed for cpu:%s\n", cpu_stat_list[i]->ks_name); */
550 return (1);
552 np = (uint *)&new_cpu_stat.cpu_sysinfo;
553 tp = (uint *)&(cpu_stat_data[i].cpu_sysinfo);
554 for (j = 0; j < sizeof (cpu_sysinfo_t); j += sizeof (uint_t))
555 *np++ += *tp++;
556 np = (uint *)&new_cpu_stat.cpu_vminfo;
557 tp = (uint *)&(cpu_stat_data[i].cpu_vminfo);
558 for (j = 0; j < sizeof (cpu_vminfo_t); j += sizeof (uint_t))
559 *np++ += *tp++;
561 return (0);
564 static void
565 fail(int do_perror, char *message, ...)
567 va_list args;
569 va_start(args, message);
570 (void) fprintf(stderr, "%s: ", cmdname);
571 (void) vfprintf(stderr, message, args);
572 va_end(args);
573 if (do_perror)
574 (void) fprintf(stderr, ": %s", strerror(errno));
575 (void) fprintf(stderr, "\n");
576 exit(2);
579 static void
580 safe_zalloc(void **ptr, int size, int free_first)
582 if (free_first && *ptr != NULL)
583 free(*ptr);
584 if ((*ptr = (void *)malloc(size)) == NULL)
585 fail(1, "malloc failed");
586 (void) memset(*ptr, 0, size);
591 * Sort based on ks_class, ks_module, ks_instance, ks_name
593 static int
594 kscmp(struct diskinfo *ks1, struct diskinfo *ks2)
596 int cmp;
598 cmp = ks1->class - ks2->class;
599 if (cmp != 0)
600 return (cmp);
602 cmp = strcmp(ks1->ks->ks_module, ks2->ks->ks_module);
603 if (cmp != 0)
604 return (cmp);
605 cmp = ks1->ks->ks_instance - ks2->ks->ks_instance;
606 if (cmp != 0)
607 return (cmp);
609 if (ks1->device_name && ks2->device_name)
610 return (strcmp(ks1->device_name, ks2->device_name));
611 else
612 return (strcmp(ks1->ks->ks_name, ks2->ks->ks_name));
615 static void
616 init_disks(void)
618 struct diskinfo *disk, *prevdisk, *comp;
619 kstat_t *ksp;
620 static int first = 1;
622 refreshDiskdetail=1;
623 refreshDisksrv=1;
625 if (do_conversions)
626 dl = (void *)build_disk_list(dl);
628 if(first) {
629 zerodisk.next = NULLDISK;
630 first = 0;
633 disk = &zerodisk;
636 * Patch the snip in the diskinfo list (see below)
638 if (snip)
639 lastdisk->next = snip;
641 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
642 int i;
644 if (ksp->ks_type != KSTAT_TYPE_IO)
645 continue;
647 for (i = 0; io_class[i].class_name != NULL; i++) {
648 if (strcmp(ksp->ks_class, io_class[i].class_name) == 0)
649 break;
651 if (io_class[i].class_name == NULL)
652 continue;
654 if (do_partitions_only &&
655 (strcmp(ksp->ks_class, "disk") == 0))
656 continue;
658 if (!do_partitions && !do_partitions_only &&
659 (strcmp(ksp->ks_class, "partition") == 0))
660 continue;
661 if (!strcmp(ksp->ks_name, "fd0"))
662 continue;
664 prevdisk = disk;
665 if (disk->next)
666 disk = disk->next;
667 else {
668 safe_zalloc((void **)&disk->next,
669 sizeof (struct diskinfo), 0);
670 disk = disk->next;
671 disk->next = NULLDISK;
673 disk->ks = ksp;
674 (void) memset((void *)&disk->new_kios, 0, sizeof (kstat_io_t));
675 disk->new_kios.wlastupdate = disk->ks->ks_crtime;
676 disk->new_kios.rlastupdate = disk->ks->ks_crtime;
678 if (do_conversions && dl) {
679 if (!strcmp(ksp->ks_class, "nfs") == 0)
680 disk->device_name =
681 lookup_ks_name(ksp->ks_name, dl);
682 } else {
683 disk->device_name = (char *)0;
686 disk->disk_errs = (kstat_t *)NULL;
687 disk->class = io_class[i].class_priority;
690 * Insertion sort on (ks_class, ks_module, ks_instance, ks_name)
692 comp = &zerodisk;
693 while (kscmp(disk, comp->next) > 0)
694 comp = comp->next;
695 if (prevdisk != comp) {
696 prevdisk->next = disk->next;
697 disk->next = comp->next;
698 comp->next = disk;
699 disk = prevdisk;
703 * Put a snip in the linked list of diskinfos. The idea:
704 * If there was a state change such that now there are fewer
705 * disks, we snip the list and retain the tail, rather than
706 * freeing it. At the next state change, we clip the tail back on.
707 * This prevents a lot of malloc/free activity, and it's simpler.
709 lastdisk = disk;
710 snip = disk->next;
711 disk->next = NULLDISK;
713 firstdisk = zerodisk.next;
714 select_disks();
716 if (do_disk & DISK_ERROR_MASK)
717 init_disk_errors();
720 static void
721 select_disks(void)
723 struct diskinfo *disk;
724 struct disk_selection *ds;
726 ndrives = 0;
727 for (disk = firstdisk; disk; disk = disk->next) {
728 disk->selected = 0;
729 for (ds = disk_selections; ds; ds = ds->next) {
730 if (strcmp(disk->ks->ks_name, ds->ks_name) == 0) {
731 disk->selected = 1;
732 ndrives++;
733 break;
737 for (disk = firstdisk; disk; disk = disk->next) {
738 if (disk->selected)
739 continue;
740 if (limit && ndrives >= limit)
741 break;
742 disk->selected = 1;
743 ndrives++;
747 static int
748 diskinfo_load(void)
750 struct diskinfo *disk;
752 for (disk = firstdisk; disk; disk = disk->next) {
753 if (disk->selected) {
754 disk->old_kios = disk->new_kios;
755 if (kstat_read(kc, disk->ks,
756 (void *)&disk->new_kios) == -1)
757 return (1);
758 if (disk->disk_errs) {
759 if (kstat_read(kc, disk->disk_errs, NULL) == -1) {
760 return (1);
765 return (0);
767 static void
768 init_disk_errors()
770 kstat_t *ksp;
772 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
773 if ((ksp->ks_type == KSTAT_TYPE_NAMED) &&
774 (strncmp(ksp->ks_class, "device_error", 12) == 0)) {
775 find_disk(ksp);
779 static void
780 find_disk(ksp)
781 kstat_t *ksp;
783 struct diskinfo *disk;
784 char kstat_name[KSTAT_STRLEN];
785 char *dname = kstat_name;
786 char *ename = ksp->ks_name;
788 while (*ename != ',') {
789 *dname = *ename;
790 dname++;
791 ename++;
793 *dname = '\0';
795 for (disk = firstdisk; disk; disk = disk->next) {
796 if (disk->selected) {
797 if (strcmp(disk->ks->ks_name, kstat_name) == 0) {
798 disk->disk_errs = ksp;
799 return;