Annotation of src/usr.bin/vmstat/dkstats.c, Revision 1.39
1.39 ! tb 1: /* $OpenBSD: dkstats.c,v 1.38 2015/12/24 03:25:08 mmcc 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:
104: /* Missing from <sys/time.h> */
1.16 deraadt 105: #define timerset(tvp, uvp) \
106: ((uvp)->tv_sec = (tvp)->tv_sec); \
107: ((uvp)->tv_usec = (tvp)->tv_usec)
108:
109: #define SWAP(fld) tmp = cur.fld; \
110: cur.fld -= last.fld; \
111: last.fld = tmp
1.1 tholo 112:
113: /*
114: * Take the delta between the present values and the last recorded
115: * values, storing the present values in the 'last' structure, and
116: * the delta values in the 'cur' structure.
117: */
118: void
1.21 deraadt 119: dkswap(void)
1.1 tholo 120: {
121: u_int64_t tmp;
122: int i;
123:
1.22 tdeval 124: for (i = 0; i < cur.dk_ndrive; i++) {
1.1 tholo 125: struct timeval tmp_timer;
126:
127: if (!cur.dk_select[i])
128: continue;
129:
130: /* Delta Values. */
1.24 tedu 131: SWAP(dk_rxfer[i]);
132: SWAP(dk_wxfer[i]);
1.1 tholo 133: SWAP(dk_seek[i]);
1.24 tedu 134: SWAP(dk_rbytes[i]);
135: SWAP(dk_wbytes[i]);
1.1 tholo 136:
137: /* Delta Time. */
138: timerclear(&tmp_timer);
139: timerset(&(cur.dk_time[i]), &tmp_timer);
140: timersub(&tmp_timer, &(last.dk_time[i]), &(cur.dk_time[i]));
141: timerclear(&(last.dk_time[i]));
142: timerset(&tmp_timer, &(last.dk_time[i]));
143: }
144: for (i = 0; i < CPUSTATES; i++) {
1.29 deraadt 145: long ltmp;
146:
147: ltmp = cur.cp_time[i];
148: cur.cp_time[i] -= last.cp_time[i];
149: last.cp_time[i] = ltmp;
1.1 tholo 150: }
151: SWAP(tk_nin);
152: SWAP(tk_nout);
153:
154: #undef SWAP
155: }
156:
157: /*
1.30 deraadt 158: * Read the disk statistics for each disk in the disk list.
1.1 tholo 159: * Also collect statistics for tty i/o and cpu ticks.
160: */
161: void
1.21 deraadt 162: dkreadstats(void)
1.1 tholo 163: {
1.19 deraadt 164: #if !defined(NOKVM)
1.1 tholo 165: struct disk cur_disk, *p;
1.19 deraadt 166: #endif
1.22 tdeval 167: int i, j, mib[3];
1.10 angelos 168: size_t size;
1.22 tdeval 169: char *disknames, *name, *bufpp, **dk_name;
1.13 angelos 170: struct diskstats *q;
1.1 tholo 171:
1.22 tdeval 172: last.dk_ndrive = cur.dk_ndrive;
173:
1.10 angelos 174: if (nlistf == NULL && memf == NULL) {
1.22 tdeval 175: /* Get the number of attached drives. */
176: mib[0] = CTL_HW;
177: mib[1] = HW_DISKCOUNT;
178: size = sizeof(dk_ndrive);
179: if (sysctl(mib, 2, &dk_ndrive, &size, NULL, 0) < 0 ) {
180: warn("could not read hw.diskcount");
181: dk_ndrive = 0;
182: }
183:
184: if (cur.dk_ndrive != dk_ndrive) {
185: /* Re-read the disk names. */
1.29 deraadt 186: dk_name = calloc((size_t)dk_ndrive, sizeof(char *));
1.22 tdeval 187: if (dk_name == NULL)
188: err(1, NULL);
189: mib[0] = CTL_HW;
190: mib[1] = HW_DISKNAMES;
191: size = 0;
192: if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
193: err(1, "can't get hw.disknames");
194: disknames = malloc(size);
195: if (disknames == NULL)
196: err(1, NULL);
197: if (sysctl(mib, 2, disknames, &size, NULL, 0) < 0)
198: err(1, "can't get hw.disknames");
199: bufpp = disknames;
1.35 deraadt 200: for (i = 0; i < dk_ndrive &&
201: (name = strsep(&bufpp, ",")) != NULL; i++)
1.23 millert 202: dk_name[i] = name;
1.35 deraadt 203: for (i = 0; i < dk_ndrive; i++) {
204: char *p = strchr(dk_name[i], ':');
205: if (p)
206: *p = '\0';
207: }
1.22 tdeval 208: disknames = cur.dk_name[0]; /* To free old names. */
209:
210: if (dk_ndrive < cur.dk_ndrive) {
211: for (i = 0, j = 0; i < dk_ndrive; i++, j++) {
212: while (j < cur.dk_ndrive &&
213: strcmp(cur.dk_name[j], dk_name[i]))
214: j++;
215: if (i == j) continue;
216:
217: if (j >= cur.dk_ndrive) {
218: cur.dk_select[i] = 1;
1.24 tedu 219: last.dk_rxfer[i] = 0;
220: last.dk_wxfer[i] = 0;
1.22 tdeval 221: last.dk_seek[i] = 0;
1.24 tedu 222: last.dk_rbytes[i] = 0;
223: last.dk_wbytes[i] = 0;
1.38 mmcc 224: memset(&last.dk_time[i], 0,
1.22 tdeval 225: sizeof(struct timeval));
226: continue;
227: }
228:
229: cur.dk_select[i] = cur.dk_select[j];
1.24 tedu 230: last.dk_rxfer[i] = last.dk_rxfer[j];
231: last.dk_wxfer[i] = last.dk_wxfer[j];
1.22 tdeval 232: last.dk_seek[i] = last.dk_seek[j];
1.24 tedu 233: last.dk_rbytes[i] = last.dk_rbytes[j];
234: last.dk_wbytes[i] = last.dk_wbytes[j];
1.22 tdeval 235: last.dk_time[i] = last.dk_time[j];
236: }
237:
1.39 ! tb 238: cur.dk_select = reallocarray(cur.dk_select,
! 239: dk_ndrive, sizeof(*cur.dk_select));
! 240: cur.dk_rxfer = reallocarray(cur.dk_rxfer,
! 241: dk_ndrive, sizeof(*cur.dk_rxfer));
! 242: cur.dk_wxfer = reallocarray(cur.dk_wxfer,
! 243: dk_ndrive, sizeof(*cur.dk_wxfer));
! 244: cur.dk_seek = reallocarray(cur.dk_seek,
! 245: dk_ndrive, sizeof(*cur.dk_seek));
! 246: cur.dk_rbytes = reallocarray(cur.dk_rbytes,
! 247: dk_ndrive, sizeof(*cur.dk_rbytes));
! 248: cur.dk_wbytes = reallocarray(cur.dk_wbytes,
! 249: dk_ndrive, sizeof(*cur.dk_wbytes));
! 250: cur.dk_time = reallocarray(cur.dk_time,
! 251: dk_ndrive, sizeof(*cur.dk_time));
! 252: last.dk_rxfer = reallocarray(last.dk_rxfer,
! 253: dk_ndrive, sizeof(*last.dk_rxfer));
! 254: last.dk_wxfer = reallocarray(last.dk_wxfer,
! 255: dk_ndrive, sizeof(*last.dk_wxfer));
! 256: last.dk_seek = reallocarray(last.dk_seek,
! 257: dk_ndrive, sizeof(*last.dk_seek));
! 258: last.dk_rbytes = reallocarray(last.dk_rbytes,
! 259: dk_ndrive, sizeof(*last.dk_rbytes));
! 260: last.dk_wbytes = reallocarray(last.dk_wbytes,
! 261: dk_ndrive, sizeof(*last.dk_wbytes));
! 262: last.dk_time = reallocarray(last.dk_time,
! 263: dk_ndrive, sizeof(*last.dk_time));
1.32 chl 264:
265: if (!cur.dk_select || !cur.dk_rxfer ||
266: !cur.dk_wxfer || !cur.dk_seek ||
267: !cur.dk_rbytes || !cur.dk_wbytes ||
268: !cur.dk_time || !last.dk_rxfer ||
269: !last.dk_wxfer || !last.dk_seek ||
270: !last.dk_rbytes || !last.dk_wbytes ||
271: !last.dk_time)
272: errx(1, "Memory allocation failure.");
1.22 tdeval 273: } else {
1.39 ! tb 274: cur.dk_select = reallocarray(cur.dk_select,
! 275: dk_ndrive, sizeof(*cur.dk_select));
! 276: cur.dk_rxfer = reallocarray(cur.dk_rxfer,
! 277: dk_ndrive, sizeof(*cur.dk_rxfer));
! 278: cur.dk_wxfer = reallocarray(cur.dk_wxfer,
! 279: dk_ndrive, sizeof(*cur.dk_wxfer));
! 280: cur.dk_seek = reallocarray(cur.dk_seek,
! 281: dk_ndrive, sizeof(*cur.dk_seek));
! 282: cur.dk_rbytes = reallocarray(cur.dk_rbytes,
! 283: dk_ndrive, sizeof(*cur.dk_rbytes));
! 284: cur.dk_wbytes = reallocarray(cur.dk_wbytes,
! 285: dk_ndrive, sizeof(*cur.dk_wbytes));
! 286: cur.dk_time = reallocarray(cur.dk_time,
! 287: dk_ndrive, sizeof(*cur.dk_time));
! 288: last.dk_rxfer = reallocarray(last.dk_rxfer,
! 289: dk_ndrive, sizeof(*last.dk_rxfer));
! 290: last.dk_wxfer = reallocarray(last.dk_wxfer,
! 291: dk_ndrive, sizeof(*last.dk_wxfer));
! 292: last.dk_seek = reallocarray(last.dk_seek,
! 293: dk_ndrive, sizeof(*last.dk_seek));
! 294: last.dk_rbytes = reallocarray(last.dk_rbytes,
! 295: dk_ndrive, sizeof(*last.dk_rbytes));
! 296: last.dk_wbytes = reallocarray(last.dk_wbytes,
! 297: dk_ndrive, sizeof(*last.dk_wbytes));
! 298: last.dk_time = reallocarray(last.dk_time,
! 299: dk_ndrive, sizeof(*last.dk_time));
1.32 chl 300:
301: if (!cur.dk_select || !cur.dk_rxfer ||
302: !cur.dk_wxfer || !cur.dk_seek ||
303: !cur.dk_rbytes || !cur.dk_wbytes ||
304: !cur.dk_time || !last.dk_rxfer ||
305: !last.dk_wxfer || !last.dk_seek ||
306: !last.dk_rbytes || !last.dk_wbytes ||
307: !last.dk_time)
308: errx(1, "Memory allocation failure.");
1.22 tdeval 309:
310: for (i = dk_ndrive - 1, j = cur.dk_ndrive - 1;
311: i >= 0; i--) {
312:
313: if (j < 0 ||
314: strcmp(cur.dk_name[j], dk_name[i]))
315: {
316: cur.dk_select[i] = 1;
1.24 tedu 317: last.dk_rxfer[i] = 0;
318: last.dk_wxfer[i] = 0;
1.22 tdeval 319: last.dk_seek[i] = 0;
1.24 tedu 320: last.dk_rbytes[i] = 0;
321: last.dk_wbytes[i] = 0;
1.38 mmcc 322: memset(&last.dk_time[i], 0,
1.22 tdeval 323: sizeof(struct timeval));
324: continue;
325: }
326:
327: if (i > j) {
328: cur.dk_select[i] =
329: cur.dk_select[j];
1.24 tedu 330: last.dk_rxfer[i] =
331: last.dk_rxfer[j];
332: last.dk_wxfer[i] =
333: last.dk_wxfer[j];
1.22 tdeval 334: last.dk_seek[i] =
335: last.dk_seek[j];
1.24 tedu 336: last.dk_rbytes[i] =
337: last.dk_rbytes[j];
338: last.dk_wbytes[i] =
339: last.dk_wbytes[j];
1.22 tdeval 340: last.dk_time[i] =
341: last.dk_time[j];
342: }
343: j--;
344: }
345: }
346:
347: cur.dk_ndrive = dk_ndrive;
348: free(disknames);
349: cur.dk_name = dk_name;
350: dr_name = cur.dk_name;
351: dk_select = cur.dk_select;
352: }
353:
354: size = cur.dk_ndrive * sizeof(struct diskstats);
1.10 angelos 355: mib[0] = CTL_HW;
356: mib[1] = HW_DISKSTATS;
1.13 angelos 357: q = malloc(size);
358: if (q == NULL)
1.10 angelos 359: err(1, NULL);
1.13 angelos 360: if (sysctl(mib, 2, q, &size, NULL, 0) < 0) {
1.22 tdeval 361: #ifdef DEBUG
1.10 angelos 362: warn("could not read hw.diskstats");
1.22 tdeval 363: #endif /* DEBUG */
1.38 mmcc 364: memset(q, 0, cur.dk_ndrive * sizeof(struct diskstats));
1.10 angelos 365: }
366:
1.22 tdeval 367: for (i = 0; i < cur.dk_ndrive; i++) {
1.24 tedu 368: cur.dk_rxfer[i] = q[i].ds_rxfer;
369: cur.dk_wxfer[i] = q[i].ds_wxfer;
1.13 angelos 370: cur.dk_seek[i] = q[i].ds_seek;
1.24 tedu 371: cur.dk_rbytes[i] = q[i].ds_rbytes;
372: cur.dk_wbytes[i] = q[i].ds_wbytes;
1.13 angelos 373: timerset(&(q[i].ds_time), &(cur.dk_time[i]));
1.10 angelos 374: }
1.14 deraadt 375: free(q);
1.10 angelos 376:
1.30 deraadt 377: size = sizeof(cur.cp_time);
1.10 angelos 378: mib[0] = CTL_KERN;
379: mib[1] = KERN_CPTIME;
380: if (sysctl(mib, 2, cur.cp_time, &size, NULL, 0) < 0) {
1.11 angelos 381: warn("could not read kern.cp_time");
1.38 mmcc 382: memset(cur.cp_time, 0, sizeof(cur.cp_time));
1.10 angelos 383: }
384: size = sizeof(cur.tk_nin);
385: mib[0] = CTL_KERN;
386: mib[1] = KERN_TTY;
387: mib[2] = KERN_TTY_TKNIN;
388: if (sysctl(mib, 3, &cur.tk_nin, &size, NULL, 0) < 0) {
1.11 angelos 389: warn("could not read kern.tty.tk_nin");
1.10 angelos 390: cur.tk_nin = 0;
391: }
392: size = sizeof(cur.tk_nin);
393: mib[0] = CTL_KERN;
394: mib[1] = KERN_TTY;
395: mib[2] = KERN_TTY_TKNOUT;
396: if (sysctl(mib, 3, &cur.tk_nout, &size, NULL, 0) < 0) {
1.11 angelos 397: warn("could not read kern.tty.tk_nout");
1.10 angelos 398: cur.tk_nout = 0;
399: }
400: } else {
1.16 deraadt 401: #if !defined(NOKVM)
1.10 angelos 402: p = dk_drivehead;
403:
1.22 tdeval 404: for (i = 0; i < cur.dk_ndrive; i++) {
1.10 angelos 405: deref_kptr(p, &cur_disk, sizeof(cur_disk));
1.24 tedu 406: cur.dk_rxfer[i] = cur_disk.dk_rxfer;
407: cur.dk_wxfer[i] = cur_disk.dk_wxfer;
1.10 angelos 408: cur.dk_seek[i] = cur_disk.dk_seek;
1.24 tedu 409: cur.dk_rbytes[i] = cur_disk.dk_rbytes;
410: cur.dk_wbytes[i] = cur_disk.dk_wbytes;
1.10 angelos 411: timerset(&(cur_disk.dk_time), &(cur.dk_time[i]));
1.27 otto 412: p = TAILQ_NEXT(&cur_disk, dk_link);
1.10 angelos 413: }
414: deref_nl(X_CP_TIME, cur.cp_time, sizeof(cur.cp_time));
415: deref_nl(X_TK_NIN, &cur.tk_nin, sizeof(cur.tk_nin));
416: deref_nl(X_TK_NOUT, &cur.tk_nout, sizeof(cur.tk_nout));
1.16 deraadt 417: #endif /* !defined(NOKVM) */
1.1 tholo 418: }
419: }
420:
421: /*
422: * Perform all of the initialization and memory allocation needed to
423: * track disk statistics.
424: */
425: int
1.28 otto 426: dkinit(int sel)
1.1 tholo 427: {
1.19 deraadt 428: #if !defined(NOKVM)
1.1 tholo 429: struct disklist_head disk_head;
430: struct disk cur_disk, *p;
431: char errbuf[_POSIX2_LINE_MAX];
1.19 deraadt 432: #endif
1.1 tholo 433: static int once = 0;
434: extern int hz;
1.10 angelos 435: int i, mib[2];
436: size_t size;
437: struct clockinfo clkinfo;
438: char *disknames, *name, *bufpp;
1.1 tholo 439:
440: if (once)
441: return(1);
442:
1.10 angelos 443: if (nlistf != NULL || memf != NULL) {
1.16 deraadt 444: #if !defined(NOKVM)
1.10 angelos 445: /* Open the kernel. */
1.20 deraadt 446: if (kd == NULL &&
447: (kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY,
1.10 angelos 448: errbuf)) == NULL)
449: errx(1, "kvm_openfiles: %s", errbuf);
450:
451: /* Obtain the namelist symbols from the kernel. */
452: if (kvm_nlist(kd, namelist))
453: KVM_ERROR("kvm_nlist failed to read symbols.");
454:
455: /* Get the number of attached drives. */
1.22 tdeval 456: deref_nl(X_DISK_COUNT, &cur.dk_ndrive, sizeof(cur.dk_ndrive));
1.10 angelos 457:
1.22 tdeval 458: if (cur.dk_ndrive < 0)
459: errx(1, "invalid _disk_count %d.", cur.dk_ndrive);
1.10 angelos 460:
1.1 tholo 461: /* Get a pointer to the first disk. */
462: deref_nl(X_DISKLIST, &disk_head, sizeof(disk_head));
1.27 otto 463: dk_drivehead = TAILQ_FIRST(&disk_head);
1.10 angelos 464:
465: /* Get ticks per second. */
466: deref_nl(X_STATHZ, &hz, sizeof(hz));
467: if (!hz)
468: deref_nl(X_HZ, &hz, sizeof(hz));
1.16 deraadt 469: #endif /* !defined(NOKVM) */
1.10 angelos 470: } else {
471: /* Get the number of attached drives. */
472: mib[0] = CTL_HW;
473: mib[1] = HW_DISKCOUNT;
1.22 tdeval 474: size = sizeof(cur.dk_ndrive);
475: if (sysctl(mib, 2, &cur.dk_ndrive, &size, NULL, 0) < 0 ) {
1.11 angelos 476: warn("could not read hw.diskcount");
1.22 tdeval 477: cur.dk_ndrive = 0;
1.10 angelos 478: }
479:
480: /* Get ticks per second. */
481: mib[0] = CTL_KERN;
482: mib[1] = KERN_CLOCKRATE;
483: size = sizeof(clkinfo);
484: if (sysctl(mib, 2, &clkinfo, &size, NULL, 0) < 0) {
1.11 angelos 485: warn("could not read kern.clockrate");
1.10 angelos 486: hz = 0;
487: } else
488: hz = clkinfo.stathz;
1.1 tholo 489: }
490:
491: /* allocate space for the statistics */
1.29 deraadt 492: cur.dk_time = calloc((size_t)cur.dk_ndrive, sizeof(struct timeval));
493: cur.dk_rxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
494: cur.dk_wxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
495: cur.dk_seek = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
496: cur.dk_rbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
497: cur.dk_wbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
1.31 chl 498: cur.dk_select = calloc((size_t)cur.dk_ndrive, sizeof(int));
499: cur.dk_name = calloc((size_t)cur.dk_ndrive, sizeof(char *));
1.29 deraadt 500: last.dk_time = calloc((size_t)cur.dk_ndrive, sizeof(struct timeval));
501: last.dk_rxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
502: last.dk_wxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
503: last.dk_seek = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
504: last.dk_rbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
505: last.dk_wbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
1.30 deraadt 506:
1.24 tedu 507: if (!cur.dk_time || !cur.dk_rxfer || !cur.dk_wxfer || !cur.dk_seek ||
1.31 chl 508: !cur.dk_rbytes || !cur.dk_wbytes || !cur.dk_select ||
509: !cur.dk_name || !last.dk_time || !last.dk_rxfer ||
510: !last.dk_wxfer || !last.dk_seek || !last.dk_rbytes ||
511: !last.dk_wbytes)
1.1 tholo 512: errx(1, "Memory allocation failure.");
513:
514: /* Set up the compatibility interfaces. */
1.22 tdeval 515: dk_ndrive = cur.dk_ndrive;
1.1 tholo 516: dk_select = cur.dk_select;
517: dr_name = cur.dk_name;
518:
1.22 tdeval 519: /* Read the disk names and set initial selection. */
1.10 angelos 520: if (nlistf == NULL && memf == NULL) {
521: mib[0] = CTL_HW;
522: mib[1] = HW_DISKNAMES;
523: size = 0;
524: if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
525: err(1, "can't get hw.disknames");
1.12 angelos 526: disknames = malloc(size);
1.10 angelos 527: if (disknames == NULL)
528: err(1, NULL);
529: if (sysctl(mib, 2, disknames, &size, NULL, 0) < 0)
530: err(1, "can't get hw.disknames");
531: bufpp = disknames;
1.23 millert 532: for (i = 0; i < dk_ndrive && (name = strsep(&bufpp, ",")) != NULL; i++) {
533: cur.dk_name[i] = name;
1.28 otto 534: cur.dk_select[i] = sel;
1.35 deraadt 535: }
536: for (i = 0; i < dk_ndrive; i++) {
537: char *p = strchr(cur.dk_name[i], ':');
538: if (p)
539: *p = '\0';
1.10 angelos 540: }
541: } else {
1.16 deraadt 542: #if !defined(NOKVM)
1.10 angelos 543: p = dk_drivehead;
1.22 tdeval 544: for (i = 0; i < cur.dk_ndrive; i++) {
1.10 angelos 545: char buf[10];
1.16 deraadt 546:
1.10 angelos 547: deref_kptr(p, &cur_disk, sizeof(cur_disk));
548: deref_kptr(cur_disk.dk_name, buf, sizeof(buf));
549: cur.dk_name[i] = strdup(buf);
550: if (!cur.dk_name[i])
551: errx(1, "Memory allocation failure.");
1.28 otto 552: cur.dk_select[i] = sel;
1.1 tholo 553:
1.27 otto 554: p = TAILQ_NEXT(&cur_disk, dk_link);
1.10 angelos 555: }
1.16 deraadt 556: #endif /* !defined(NOKVM) */
1.1 tholo 557: }
558:
1.33 martynas 559: /* Never do this initialization again. */
1.1 tholo 560: once = 1;
561: return(1);
562: }
563:
1.16 deraadt 564: #if !defined(NOKVM)
1.1 tholo 565: /*
1.30 deraadt 566: * Dereference the kernel pointer `kptr' and fill in the local copy
1.1 tholo 567: * pointed to by `ptr'. The storage space must be pre-allocated,
568: * and the size of the copy passed in `len'.
569: */
570: static void
1.21 deraadt 571: deref_kptr(void *kptr, void *ptr, size_t len)
1.1 tholo 572: {
573: char buf[128];
574:
1.6 art 575: if (kvm_read(kd, (u_long)kptr, ptr, len) != len) {
1.38 mmcc 576: memset(buf, 0, sizeof(buf));
1.1 tholo 577: snprintf(buf, (sizeof(buf) - 1),
1.2 deraadt 578: "can't dereference kptr 0x%lx", (u_long)kptr);
1.1 tholo 579: KVM_ERROR(buf);
580: }
581: }
1.17 drahn 582: #endif /* !defined(NOKVM) */