Annotation of src/usr.bin/vmstat/dkstats.c, Revision 1.42
1.42 ! cheloha 1: /* $OpenBSD: dkstats.c,v 1.41 2019/06/28 13:35:05 deraadt Exp $ */
1.2 deraadt 2: /* $NetBSD: dkstats.c,v 1.1 1996/05/10 23:19:27 thorpej Exp $ */
1.1 tholo 3:
4: /*
1.2 deraadt 5: * Copyright (c) 1996 John M. Vinopal
1.1 tholo 6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed for the NetBSD Project
19: * by John M. Vinopal.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #include <sys/time.h>
37: #include <sys/disk.h>
1.36 miod 38: #include <sys/sched.h>
1.10 angelos 39: #include <sys/sysctl.h>
40: #include <sys/tty.h>
1.1 tholo 41:
42: #include <err.h>
43: #include <fcntl.h>
44: #include <kvm.h>
45: #include <limits.h>
46: #include <nlist.h>
47: #include <stdio.h>
48: #include <stdlib.h>
49: #include <string.h>
50: #include <unistd.h>
51: #include "dkstats.h"
52:
1.16 deraadt 53: #if !defined(NOKVM)
1.1 tholo 54: static struct nlist namelist[] = {
1.18 deraadt 55: #define X_TK_NIN 0 /* sysctl */
56: { "_tk_nin" },
57: #define X_TK_NOUT 1 /* sysctl */
58: { "_tk_nout" },
59: #define X_CP_TIME 2 /* sysctl */
60: { "_cp_time" },
61: #define X_HZ 3 /* sysctl */
62: { "_hz" },
63: #define X_STATHZ 4 /* sysctl */
1.1 tholo 64: { "_stathz" },
1.18 deraadt 65: #define X_DISK_COUNT 5 /* sysctl */
66: { "_disk_count" },
67: #define X_DISKLIST 6 /* sysctl */
68: { "_disklist" },
1.1 tholo 69: { NULL },
70: };
1.16 deraadt 71: #define KVM_ERROR(_string) { \
72: warnx("%s", (_string)); \
73: errx(1, "%s", kvm_geterr(kd)); \
74: }
75:
76: /*
1.30 deraadt 77: * Dereference the namelist pointer `v' and fill in the local copy
1.16 deraadt 78: * 'p' which is of size 's'.
79: */
80: #define deref_nl(v, p, s) deref_kptr((void *)namelist[(v)].n_value, (p), (s));
81: static void deref_kptr(void *, void *, size_t);
82: #endif /* !defined(NOKVM) */
1.1 tholo 83:
84: /* Structures to hold the statistics. */
85: struct _disk cur, last;
86:
87: /* Kernel pointers: nlistf and memf defined in calling program. */
1.19 deraadt 88: #if !defined(NOKVM)
1.20 deraadt 89: extern kvm_t *kd;
1.19 deraadt 90: #endif
1.1 tholo 91: extern char *nlistf;
92: extern char *memf;
93:
1.19 deraadt 94: #if !defined(NOKVM)
1.1 tholo 95: /* Pointer to list of disks. */
96: static struct disk *dk_drivehead = NULL;
1.19 deraadt 97: #endif
1.1 tholo 98:
99: /* Backward compatibility references. */
1.30 deraadt 100: int dk_ndrive = 0;
1.1 tholo 101: int *dk_select;
102: char **dr_name;
103:
1.16 deraadt 104: #define SWAP(fld) tmp = cur.fld; \
105: cur.fld -= last.fld; \
106: last.fld = tmp
1.1 tholo 107:
108: /*
109: * Take the delta between the present values and the last recorded
110: * values, storing the present values in the 'last' structure, and
111: * the delta values in the 'cur' structure.
112: */
113: void
1.21 deraadt 114: dkswap(void)
1.1 tholo 115: {
116: u_int64_t tmp;
117: int i;
118:
1.22 tdeval 119: for (i = 0; i < cur.dk_ndrive; i++) {
1.1 tholo 120: struct timeval tmp_timer;
121:
122: if (!cur.dk_select[i])
123: continue;
124:
125: /* Delta Values. */
1.24 tedu 126: SWAP(dk_rxfer[i]);
127: SWAP(dk_wxfer[i]);
1.1 tholo 128: SWAP(dk_seek[i]);
1.24 tedu 129: SWAP(dk_rbytes[i]);
130: SWAP(dk_wbytes[i]);
1.1 tholo 131:
132: /* Delta Time. */
1.42 ! cheloha 133: tmp_timer = cur.dk_time[i];
! 134: timersub(&tmp_timer, &last.dk_time[i], &cur.dk_time[i]);
! 135: last.dk_time[i] = tmp_timer;
1.1 tholo 136: }
137: for (i = 0; i < CPUSTATES; i++) {
1.29 deraadt 138: long ltmp;
139:
140: ltmp = cur.cp_time[i];
141: cur.cp_time[i] -= last.cp_time[i];
142: last.cp_time[i] = ltmp;
1.1 tholo 143: }
144: SWAP(tk_nin);
145: SWAP(tk_nout);
146:
147: #undef SWAP
148: }
149:
150: /*
1.30 deraadt 151: * Read the disk statistics for each disk in the disk list.
1.1 tholo 152: * Also collect statistics for tty i/o and cpu ticks.
153: */
154: void
1.21 deraadt 155: dkreadstats(void)
1.1 tholo 156: {
1.19 deraadt 157: #if !defined(NOKVM)
1.1 tholo 158: struct disk cur_disk, *p;
1.19 deraadt 159: #endif
1.22 tdeval 160: int i, j, mib[3];
1.10 angelos 161: size_t size;
1.22 tdeval 162: char *disknames, *name, *bufpp, **dk_name;
1.13 angelos 163: struct diskstats *q;
1.1 tholo 164:
1.22 tdeval 165: last.dk_ndrive = cur.dk_ndrive;
166:
1.10 angelos 167: if (nlistf == NULL && memf == NULL) {
1.22 tdeval 168: /* Get the number of attached drives. */
169: mib[0] = CTL_HW;
170: mib[1] = HW_DISKCOUNT;
171: size = sizeof(dk_ndrive);
1.41 deraadt 172: if (sysctl(mib, 2, &dk_ndrive, &size, NULL, 0) == -1 ) {
1.22 tdeval 173: warn("could not read hw.diskcount");
174: dk_ndrive = 0;
175: }
176:
177: if (cur.dk_ndrive != dk_ndrive) {
178: /* Re-read the disk names. */
1.29 deraadt 179: dk_name = calloc((size_t)dk_ndrive, sizeof(char *));
1.22 tdeval 180: if (dk_name == NULL)
181: err(1, NULL);
182: mib[0] = CTL_HW;
183: mib[1] = HW_DISKNAMES;
184: size = 0;
1.41 deraadt 185: if (sysctl(mib, 2, NULL, &size, NULL, 0) == -1)
1.22 tdeval 186: err(1, "can't get hw.disknames");
187: disknames = malloc(size);
188: if (disknames == NULL)
189: err(1, NULL);
1.41 deraadt 190: if (sysctl(mib, 2, disknames, &size, NULL, 0) == -1)
1.22 tdeval 191: err(1, "can't get hw.disknames");
192: bufpp = disknames;
1.35 deraadt 193: for (i = 0; i < dk_ndrive &&
194: (name = strsep(&bufpp, ",")) != NULL; i++)
1.23 millert 195: dk_name[i] = name;
1.35 deraadt 196: for (i = 0; i < dk_ndrive; i++) {
1.40 tedu 197: char *ep = strchr(dk_name[i], ':');
198: if (ep)
199: *ep = '\0';
1.35 deraadt 200: }
1.22 tdeval 201: disknames = cur.dk_name[0]; /* To free old names. */
202:
203: if (dk_ndrive < cur.dk_ndrive) {
204: for (i = 0, j = 0; i < dk_ndrive; i++, j++) {
205: while (j < cur.dk_ndrive &&
206: strcmp(cur.dk_name[j], dk_name[i]))
207: j++;
208: if (i == j) continue;
209:
210: if (j >= cur.dk_ndrive) {
211: cur.dk_select[i] = 1;
1.24 tedu 212: last.dk_rxfer[i] = 0;
213: last.dk_wxfer[i] = 0;
1.22 tdeval 214: last.dk_seek[i] = 0;
1.24 tedu 215: last.dk_rbytes[i] = 0;
216: last.dk_wbytes[i] = 0;
1.38 mmcc 217: memset(&last.dk_time[i], 0,
1.22 tdeval 218: sizeof(struct timeval));
219: continue;
220: }
221:
222: cur.dk_select[i] = cur.dk_select[j];
1.24 tedu 223: last.dk_rxfer[i] = last.dk_rxfer[j];
224: last.dk_wxfer[i] = last.dk_wxfer[j];
1.22 tdeval 225: last.dk_seek[i] = last.dk_seek[j];
1.24 tedu 226: last.dk_rbytes[i] = last.dk_rbytes[j];
227: last.dk_wbytes[i] = last.dk_wbytes[j];
1.22 tdeval 228: last.dk_time[i] = last.dk_time[j];
229: }
230:
1.39 tb 231: cur.dk_select = reallocarray(cur.dk_select,
232: dk_ndrive, sizeof(*cur.dk_select));
233: cur.dk_rxfer = reallocarray(cur.dk_rxfer,
234: dk_ndrive, sizeof(*cur.dk_rxfer));
235: cur.dk_wxfer = reallocarray(cur.dk_wxfer,
236: dk_ndrive, sizeof(*cur.dk_wxfer));
237: cur.dk_seek = reallocarray(cur.dk_seek,
238: dk_ndrive, sizeof(*cur.dk_seek));
239: cur.dk_rbytes = reallocarray(cur.dk_rbytes,
240: dk_ndrive, sizeof(*cur.dk_rbytes));
241: cur.dk_wbytes = reallocarray(cur.dk_wbytes,
242: dk_ndrive, sizeof(*cur.dk_wbytes));
243: cur.dk_time = reallocarray(cur.dk_time,
244: dk_ndrive, sizeof(*cur.dk_time));
245: last.dk_rxfer = reallocarray(last.dk_rxfer,
246: dk_ndrive, sizeof(*last.dk_rxfer));
247: last.dk_wxfer = reallocarray(last.dk_wxfer,
248: dk_ndrive, sizeof(*last.dk_wxfer));
249: last.dk_seek = reallocarray(last.dk_seek,
250: dk_ndrive, sizeof(*last.dk_seek));
251: last.dk_rbytes = reallocarray(last.dk_rbytes,
252: dk_ndrive, sizeof(*last.dk_rbytes));
253: last.dk_wbytes = reallocarray(last.dk_wbytes,
254: dk_ndrive, sizeof(*last.dk_wbytes));
255: last.dk_time = reallocarray(last.dk_time,
256: dk_ndrive, sizeof(*last.dk_time));
1.32 chl 257:
258: if (!cur.dk_select || !cur.dk_rxfer ||
259: !cur.dk_wxfer || !cur.dk_seek ||
260: !cur.dk_rbytes || !cur.dk_wbytes ||
261: !cur.dk_time || !last.dk_rxfer ||
262: !last.dk_wxfer || !last.dk_seek ||
263: !last.dk_rbytes || !last.dk_wbytes ||
264: !last.dk_time)
265: errx(1, "Memory allocation failure.");
1.22 tdeval 266: } else {
1.39 tb 267: cur.dk_select = reallocarray(cur.dk_select,
268: dk_ndrive, sizeof(*cur.dk_select));
269: cur.dk_rxfer = reallocarray(cur.dk_rxfer,
270: dk_ndrive, sizeof(*cur.dk_rxfer));
271: cur.dk_wxfer = reallocarray(cur.dk_wxfer,
272: dk_ndrive, sizeof(*cur.dk_wxfer));
273: cur.dk_seek = reallocarray(cur.dk_seek,
274: dk_ndrive, sizeof(*cur.dk_seek));
275: cur.dk_rbytes = reallocarray(cur.dk_rbytes,
276: dk_ndrive, sizeof(*cur.dk_rbytes));
277: cur.dk_wbytes = reallocarray(cur.dk_wbytes,
278: dk_ndrive, sizeof(*cur.dk_wbytes));
279: cur.dk_time = reallocarray(cur.dk_time,
280: dk_ndrive, sizeof(*cur.dk_time));
281: last.dk_rxfer = reallocarray(last.dk_rxfer,
282: dk_ndrive, sizeof(*last.dk_rxfer));
283: last.dk_wxfer = reallocarray(last.dk_wxfer,
284: dk_ndrive, sizeof(*last.dk_wxfer));
285: last.dk_seek = reallocarray(last.dk_seek,
286: dk_ndrive, sizeof(*last.dk_seek));
287: last.dk_rbytes = reallocarray(last.dk_rbytes,
288: dk_ndrive, sizeof(*last.dk_rbytes));
289: last.dk_wbytes = reallocarray(last.dk_wbytes,
290: dk_ndrive, sizeof(*last.dk_wbytes));
291: last.dk_time = reallocarray(last.dk_time,
292: dk_ndrive, sizeof(*last.dk_time));
1.32 chl 293:
294: if (!cur.dk_select || !cur.dk_rxfer ||
295: !cur.dk_wxfer || !cur.dk_seek ||
296: !cur.dk_rbytes || !cur.dk_wbytes ||
297: !cur.dk_time || !last.dk_rxfer ||
298: !last.dk_wxfer || !last.dk_seek ||
299: !last.dk_rbytes || !last.dk_wbytes ||
300: !last.dk_time)
301: errx(1, "Memory allocation failure.");
1.22 tdeval 302:
303: for (i = dk_ndrive - 1, j = cur.dk_ndrive - 1;
304: i >= 0; i--) {
305:
306: if (j < 0 ||
307: strcmp(cur.dk_name[j], dk_name[i]))
308: {
309: cur.dk_select[i] = 1;
1.24 tedu 310: last.dk_rxfer[i] = 0;
311: last.dk_wxfer[i] = 0;
1.22 tdeval 312: last.dk_seek[i] = 0;
1.24 tedu 313: last.dk_rbytes[i] = 0;
314: last.dk_wbytes[i] = 0;
1.38 mmcc 315: memset(&last.dk_time[i], 0,
1.22 tdeval 316: sizeof(struct timeval));
317: continue;
318: }
319:
320: if (i > j) {
321: cur.dk_select[i] =
322: cur.dk_select[j];
1.24 tedu 323: last.dk_rxfer[i] =
324: last.dk_rxfer[j];
325: last.dk_wxfer[i] =
326: last.dk_wxfer[j];
1.22 tdeval 327: last.dk_seek[i] =
328: last.dk_seek[j];
1.24 tedu 329: last.dk_rbytes[i] =
330: last.dk_rbytes[j];
331: last.dk_wbytes[i] =
332: last.dk_wbytes[j];
1.22 tdeval 333: last.dk_time[i] =
334: last.dk_time[j];
335: }
336: j--;
337: }
338: }
339:
340: cur.dk_ndrive = dk_ndrive;
341: free(disknames);
342: cur.dk_name = dk_name;
343: dr_name = cur.dk_name;
344: dk_select = cur.dk_select;
345: }
346:
347: size = cur.dk_ndrive * sizeof(struct diskstats);
1.10 angelos 348: mib[0] = CTL_HW;
349: mib[1] = HW_DISKSTATS;
1.13 angelos 350: q = malloc(size);
351: if (q == NULL)
1.10 angelos 352: err(1, NULL);
1.41 deraadt 353: if (sysctl(mib, 2, q, &size, NULL, 0) == -1) {
1.22 tdeval 354: #ifdef DEBUG
1.10 angelos 355: warn("could not read hw.diskstats");
1.22 tdeval 356: #endif /* DEBUG */
1.38 mmcc 357: memset(q, 0, cur.dk_ndrive * sizeof(struct diskstats));
1.10 angelos 358: }
359:
1.22 tdeval 360: for (i = 0; i < cur.dk_ndrive; i++) {
1.24 tedu 361: cur.dk_rxfer[i] = q[i].ds_rxfer;
362: cur.dk_wxfer[i] = q[i].ds_wxfer;
1.13 angelos 363: cur.dk_seek[i] = q[i].ds_seek;
1.24 tedu 364: cur.dk_rbytes[i] = q[i].ds_rbytes;
365: cur.dk_wbytes[i] = q[i].ds_wbytes;
1.42 ! cheloha 366: cur.dk_time[i] = q[i].ds_time;
1.10 angelos 367: }
1.14 deraadt 368: free(q);
1.10 angelos 369:
1.30 deraadt 370: size = sizeof(cur.cp_time);
1.10 angelos 371: mib[0] = CTL_KERN;
372: mib[1] = KERN_CPTIME;
1.41 deraadt 373: if (sysctl(mib, 2, cur.cp_time, &size, NULL, 0) == -1) {
1.11 angelos 374: warn("could not read kern.cp_time");
1.38 mmcc 375: memset(cur.cp_time, 0, sizeof(cur.cp_time));
1.10 angelos 376: }
377: size = sizeof(cur.tk_nin);
378: mib[0] = CTL_KERN;
379: mib[1] = KERN_TTY;
380: mib[2] = KERN_TTY_TKNIN;
1.41 deraadt 381: if (sysctl(mib, 3, &cur.tk_nin, &size, NULL, 0) == -1) {
1.11 angelos 382: warn("could not read kern.tty.tk_nin");
1.10 angelos 383: cur.tk_nin = 0;
384: }
385: size = sizeof(cur.tk_nin);
386: mib[0] = CTL_KERN;
387: mib[1] = KERN_TTY;
388: mib[2] = KERN_TTY_TKNOUT;
1.41 deraadt 389: if (sysctl(mib, 3, &cur.tk_nout, &size, NULL, 0) == -1) {
1.11 angelos 390: warn("could not read kern.tty.tk_nout");
1.10 angelos 391: cur.tk_nout = 0;
392: }
393: } else {
1.16 deraadt 394: #if !defined(NOKVM)
1.10 angelos 395: p = dk_drivehead;
396:
1.22 tdeval 397: for (i = 0; i < cur.dk_ndrive; i++) {
1.10 angelos 398: deref_kptr(p, &cur_disk, sizeof(cur_disk));
1.24 tedu 399: cur.dk_rxfer[i] = cur_disk.dk_rxfer;
400: cur.dk_wxfer[i] = cur_disk.dk_wxfer;
1.10 angelos 401: cur.dk_seek[i] = cur_disk.dk_seek;
1.24 tedu 402: cur.dk_rbytes[i] = cur_disk.dk_rbytes;
403: cur.dk_wbytes[i] = cur_disk.dk_wbytes;
1.42 ! cheloha 404: cur.dk_time[i] = cur_disk.dk_time;
1.27 otto 405: p = TAILQ_NEXT(&cur_disk, dk_link);
1.10 angelos 406: }
407: deref_nl(X_CP_TIME, cur.cp_time, sizeof(cur.cp_time));
408: deref_nl(X_TK_NIN, &cur.tk_nin, sizeof(cur.tk_nin));
409: deref_nl(X_TK_NOUT, &cur.tk_nout, sizeof(cur.tk_nout));
1.16 deraadt 410: #endif /* !defined(NOKVM) */
1.1 tholo 411: }
412: }
413:
414: /*
415: * Perform all of the initialization and memory allocation needed to
416: * track disk statistics.
417: */
418: int
1.28 otto 419: dkinit(int sel)
1.1 tholo 420: {
1.19 deraadt 421: #if !defined(NOKVM)
1.1 tholo 422: struct disklist_head disk_head;
423: struct disk cur_disk, *p;
424: char errbuf[_POSIX2_LINE_MAX];
1.19 deraadt 425: #endif
1.1 tholo 426: static int once = 0;
427: extern int hz;
1.10 angelos 428: int i, mib[2];
429: size_t size;
430: struct clockinfo clkinfo;
431: char *disknames, *name, *bufpp;
1.1 tholo 432:
433: if (once)
434: return(1);
435:
1.10 angelos 436: if (nlistf != NULL || memf != NULL) {
1.16 deraadt 437: #if !defined(NOKVM)
1.10 angelos 438: /* Open the kernel. */
1.20 deraadt 439: if (kd == NULL &&
440: (kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY,
1.10 angelos 441: errbuf)) == NULL)
442: errx(1, "kvm_openfiles: %s", errbuf);
443:
444: /* Obtain the namelist symbols from the kernel. */
445: if (kvm_nlist(kd, namelist))
446: KVM_ERROR("kvm_nlist failed to read symbols.");
447:
448: /* Get the number of attached drives. */
1.22 tdeval 449: deref_nl(X_DISK_COUNT, &cur.dk_ndrive, sizeof(cur.dk_ndrive));
1.10 angelos 450:
1.22 tdeval 451: if (cur.dk_ndrive < 0)
452: errx(1, "invalid _disk_count %d.", cur.dk_ndrive);
1.10 angelos 453:
1.1 tholo 454: /* Get a pointer to the first disk. */
455: deref_nl(X_DISKLIST, &disk_head, sizeof(disk_head));
1.27 otto 456: dk_drivehead = TAILQ_FIRST(&disk_head);
1.10 angelos 457:
458: /* Get ticks per second. */
459: deref_nl(X_STATHZ, &hz, sizeof(hz));
460: if (!hz)
461: deref_nl(X_HZ, &hz, sizeof(hz));
1.16 deraadt 462: #endif /* !defined(NOKVM) */
1.10 angelos 463: } else {
464: /* Get the number of attached drives. */
465: mib[0] = CTL_HW;
466: mib[1] = HW_DISKCOUNT;
1.22 tdeval 467: size = sizeof(cur.dk_ndrive);
1.41 deraadt 468: if (sysctl(mib, 2, &cur.dk_ndrive, &size, NULL, 0) == -1 ) {
1.11 angelos 469: warn("could not read hw.diskcount");
1.22 tdeval 470: cur.dk_ndrive = 0;
1.10 angelos 471: }
472:
473: /* Get ticks per second. */
474: mib[0] = CTL_KERN;
475: mib[1] = KERN_CLOCKRATE;
476: size = sizeof(clkinfo);
1.41 deraadt 477: if (sysctl(mib, 2, &clkinfo, &size, NULL, 0) == -1) {
1.11 angelos 478: warn("could not read kern.clockrate");
1.10 angelos 479: hz = 0;
480: } else
481: hz = clkinfo.stathz;
1.1 tholo 482: }
483:
484: /* allocate space for the statistics */
1.29 deraadt 485: cur.dk_time = calloc((size_t)cur.dk_ndrive, sizeof(struct timeval));
486: cur.dk_rxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
487: cur.dk_wxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
488: cur.dk_seek = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
489: cur.dk_rbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
490: cur.dk_wbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
1.31 chl 491: cur.dk_select = calloc((size_t)cur.dk_ndrive, sizeof(int));
492: cur.dk_name = calloc((size_t)cur.dk_ndrive, sizeof(char *));
1.29 deraadt 493: last.dk_time = calloc((size_t)cur.dk_ndrive, sizeof(struct timeval));
494: last.dk_rxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
495: last.dk_wxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
496: last.dk_seek = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
497: last.dk_rbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
498: last.dk_wbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
1.30 deraadt 499:
1.24 tedu 500: if (!cur.dk_time || !cur.dk_rxfer || !cur.dk_wxfer || !cur.dk_seek ||
1.31 chl 501: !cur.dk_rbytes || !cur.dk_wbytes || !cur.dk_select ||
502: !cur.dk_name || !last.dk_time || !last.dk_rxfer ||
503: !last.dk_wxfer || !last.dk_seek || !last.dk_rbytes ||
504: !last.dk_wbytes)
1.1 tholo 505: errx(1, "Memory allocation failure.");
506:
507: /* Set up the compatibility interfaces. */
1.22 tdeval 508: dk_ndrive = cur.dk_ndrive;
1.1 tholo 509: dk_select = cur.dk_select;
510: dr_name = cur.dk_name;
511:
1.22 tdeval 512: /* Read the disk names and set initial selection. */
1.10 angelos 513: if (nlistf == NULL && memf == NULL) {
514: mib[0] = CTL_HW;
515: mib[1] = HW_DISKNAMES;
516: size = 0;
1.41 deraadt 517: if (sysctl(mib, 2, NULL, &size, NULL, 0) == -1)
1.10 angelos 518: err(1, "can't get hw.disknames");
1.12 angelos 519: disknames = malloc(size);
1.10 angelos 520: if (disknames == NULL)
521: err(1, NULL);
1.41 deraadt 522: if (sysctl(mib, 2, disknames, &size, NULL, 0) == -1)
1.10 angelos 523: err(1, "can't get hw.disknames");
524: bufpp = disknames;
1.23 millert 525: for (i = 0; i < dk_ndrive && (name = strsep(&bufpp, ",")) != NULL; i++) {
526: cur.dk_name[i] = name;
1.28 otto 527: cur.dk_select[i] = sel;
1.35 deraadt 528: }
529: for (i = 0; i < dk_ndrive; i++) {
1.40 tedu 530: char *ep = strchr(cur.dk_name[i], ':');
531: if (ep)
532: *ep = '\0';
1.10 angelos 533: }
534: } else {
1.16 deraadt 535: #if !defined(NOKVM)
1.10 angelos 536: p = dk_drivehead;
1.22 tdeval 537: for (i = 0; i < cur.dk_ndrive; i++) {
1.10 angelos 538: char buf[10];
1.16 deraadt 539:
1.10 angelos 540: deref_kptr(p, &cur_disk, sizeof(cur_disk));
541: deref_kptr(cur_disk.dk_name, buf, sizeof(buf));
542: cur.dk_name[i] = strdup(buf);
543: if (!cur.dk_name[i])
544: errx(1, "Memory allocation failure.");
1.28 otto 545: cur.dk_select[i] = sel;
1.1 tholo 546:
1.27 otto 547: p = TAILQ_NEXT(&cur_disk, dk_link);
1.10 angelos 548: }
1.16 deraadt 549: #endif /* !defined(NOKVM) */
1.1 tholo 550: }
551:
1.33 martynas 552: /* Never do this initialization again. */
1.1 tholo 553: once = 1;
554: return(1);
555: }
556:
1.16 deraadt 557: #if !defined(NOKVM)
1.1 tholo 558: /*
1.30 deraadt 559: * Dereference the kernel pointer `kptr' and fill in the local copy
1.1 tholo 560: * pointed to by `ptr'. The storage space must be pre-allocated,
561: * and the size of the copy passed in `len'.
562: */
563: static void
1.21 deraadt 564: deref_kptr(void *kptr, void *ptr, size_t len)
1.1 tholo 565: {
566: char buf[128];
567:
1.6 art 568: if (kvm_read(kd, (u_long)kptr, ptr, len) != len) {
1.38 mmcc 569: memset(buf, 0, sizeof(buf));
1.1 tholo 570: snprintf(buf, (sizeof(buf) - 1),
1.2 deraadt 571: "can't dereference kptr 0x%lx", (u_long)kptr);
1.1 tholo 572: KVM_ERROR(buf);
573: }
574: }
1.17 drahn 575: #endif /* !defined(NOKVM) */