Annotation of src/usr.bin/vmstat/dkstats.c, Revision 1.32
1.32 ! chl 1: /* $OpenBSD: dkstats.c,v 1.31 2007/10/23 07:35:58 chl 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:
1.10 angelos 36: #include <sys/param.h>
1.1 tholo 37: #include <sys/dkstat.h>
38: #include <sys/time.h>
39: #include <sys/disk.h>
1.10 angelos 40: #include <sys/sysctl.h>
41: #include <sys/tty.h>
1.1 tholo 42:
43: #include <err.h>
44: #include <fcntl.h>
45: #include <kvm.h>
46: #include <limits.h>
47: #include <nlist.h>
48: #include <stdio.h>
49: #include <stdlib.h>
50: #include <string.h>
51: #include <unistd.h>
52: #include "dkstats.h"
53:
1.16 deraadt 54: #if !defined(NOKVM)
1.1 tholo 55: static struct nlist namelist[] = {
1.18 deraadt 56: #define X_TK_NIN 0 /* sysctl */
57: { "_tk_nin" },
58: #define X_TK_NOUT 1 /* sysctl */
59: { "_tk_nout" },
60: #define X_CP_TIME 2 /* sysctl */
61: { "_cp_time" },
62: #define X_HZ 3 /* sysctl */
63: { "_hz" },
64: #define X_STATHZ 4 /* sysctl */
1.1 tholo 65: { "_stathz" },
1.18 deraadt 66: #define X_DISK_COUNT 5 /* sysctl */
67: { "_disk_count" },
68: #define X_DISKLIST 6 /* sysctl */
69: { "_disklist" },
1.1 tholo 70: { NULL },
71: };
1.16 deraadt 72: #define KVM_ERROR(_string) { \
73: warnx("%s", (_string)); \
74: errx(1, "%s", kvm_geterr(kd)); \
75: }
76:
77: /*
1.30 deraadt 78: * Dereference the namelist pointer `v' and fill in the local copy
1.16 deraadt 79: * 'p' which is of size 's'.
80: */
81: #define deref_nl(v, p, s) deref_kptr((void *)namelist[(v)].n_value, (p), (s));
82: static void deref_kptr(void *, void *, size_t);
83: #endif /* !defined(NOKVM) */
1.1 tholo 84:
85: /* Structures to hold the statistics. */
86: struct _disk cur, last;
87:
88: /* Kernel pointers: nlistf and memf defined in calling program. */
1.19 deraadt 89: #if !defined(NOKVM)
1.20 deraadt 90: extern kvm_t *kd;
1.19 deraadt 91: #endif
1.1 tholo 92: extern char *nlistf;
93: extern char *memf;
94:
1.19 deraadt 95: #if !defined(NOKVM)
1.1 tholo 96: /* Pointer to list of disks. */
97: static struct disk *dk_drivehead = NULL;
1.19 deraadt 98: #endif
1.1 tholo 99:
100: /* Backward compatibility references. */
1.30 deraadt 101: int dk_ndrive = 0;
1.1 tholo 102: int *dk_select;
103: char **dr_name;
104:
105: /* Missing from <sys/time.h> */
1.16 deraadt 106: #define timerset(tvp, uvp) \
107: ((uvp)->tv_sec = (tvp)->tv_sec); \
108: ((uvp)->tv_usec = (tvp)->tv_usec)
109:
110: #define SWAP(fld) tmp = cur.fld; \
111: cur.fld -= last.fld; \
112: last.fld = tmp
1.1 tholo 113:
114: /*
115: * Take the delta between the present values and the last recorded
116: * values, storing the present values in the 'last' structure, and
117: * the delta values in the 'cur' structure.
118: */
119: void
1.21 deraadt 120: dkswap(void)
1.1 tholo 121: {
122: u_int64_t tmp;
123: int i;
124:
1.22 tdeval 125: for (i = 0; i < cur.dk_ndrive; i++) {
1.1 tholo 126: struct timeval tmp_timer;
127:
128: if (!cur.dk_select[i])
129: continue;
130:
131: /* Delta Values. */
1.24 tedu 132: SWAP(dk_rxfer[i]);
133: SWAP(dk_wxfer[i]);
1.1 tholo 134: SWAP(dk_seek[i]);
1.24 tedu 135: SWAP(dk_rbytes[i]);
136: SWAP(dk_wbytes[i]);
1.1 tholo 137:
138: /* Delta Time. */
139: timerclear(&tmp_timer);
140: timerset(&(cur.dk_time[i]), &tmp_timer);
141: timersub(&tmp_timer, &(last.dk_time[i]), &(cur.dk_time[i]));
142: timerclear(&(last.dk_time[i]));
143: timerset(&tmp_timer, &(last.dk_time[i]));
144: }
145: for (i = 0; i < CPUSTATES; i++) {
1.29 deraadt 146: long ltmp;
147:
148: ltmp = cur.cp_time[i];
149: cur.cp_time[i] -= last.cp_time[i];
150: last.cp_time[i] = ltmp;
1.1 tholo 151: }
152: SWAP(tk_nin);
153: SWAP(tk_nout);
154:
155: #undef SWAP
156: }
157:
158: /*
1.30 deraadt 159: * Read the disk statistics for each disk in the disk list.
1.1 tholo 160: * Also collect statistics for tty i/o and cpu ticks.
161: */
162: void
1.21 deraadt 163: dkreadstats(void)
1.1 tholo 164: {
1.19 deraadt 165: #if !defined(NOKVM)
1.1 tholo 166: struct disk cur_disk, *p;
1.19 deraadt 167: #endif
1.22 tdeval 168: int i, j, mib[3];
1.10 angelos 169: size_t size;
1.22 tdeval 170: char *disknames, *name, *bufpp, **dk_name;
1.13 angelos 171: struct diskstats *q;
1.1 tholo 172:
1.22 tdeval 173: last.dk_ndrive = cur.dk_ndrive;
174:
1.10 angelos 175: if (nlistf == NULL && memf == NULL) {
1.22 tdeval 176: /* Get the number of attached drives. */
177: mib[0] = CTL_HW;
178: mib[1] = HW_DISKCOUNT;
179: size = sizeof(dk_ndrive);
180: if (sysctl(mib, 2, &dk_ndrive, &size, NULL, 0) < 0 ) {
181: warn("could not read hw.diskcount");
182: dk_ndrive = 0;
183: }
184:
185: if (cur.dk_ndrive != dk_ndrive) {
186: /* Re-read the disk names. */
1.29 deraadt 187: dk_name = calloc((size_t)dk_ndrive, sizeof(char *));
1.22 tdeval 188: if (dk_name == NULL)
189: err(1, NULL);
190: mib[0] = CTL_HW;
191: mib[1] = HW_DISKNAMES;
192: size = 0;
193: if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
194: err(1, "can't get hw.disknames");
195: disknames = malloc(size);
196: if (disknames == NULL)
197: err(1, NULL);
198: if (sysctl(mib, 2, disknames, &size, NULL, 0) < 0)
199: err(1, "can't get hw.disknames");
200: bufpp = disknames;
1.23 millert 201: for (i = 0; i < dk_ndrive && (name = strsep(&bufpp, ",")) != NULL; i++)
202: dk_name[i] = name;
1.22 tdeval 203: disknames = cur.dk_name[0]; /* To free old names. */
204:
205: if (dk_ndrive < cur.dk_ndrive) {
206: for (i = 0, j = 0; i < dk_ndrive; i++, j++) {
207: while (j < cur.dk_ndrive &&
208: strcmp(cur.dk_name[j], dk_name[i]))
209: j++;
210: if (i == j) continue;
211:
212: if (j >= cur.dk_ndrive) {
213: cur.dk_select[i] = 1;
1.24 tedu 214: last.dk_rxfer[i] = 0;
215: last.dk_wxfer[i] = 0;
1.22 tdeval 216: last.dk_seek[i] = 0;
1.24 tedu 217: last.dk_rbytes[i] = 0;
218: last.dk_wbytes[i] = 0;
1.22 tdeval 219: bzero(&last.dk_time[i],
220: sizeof(struct timeval));
221: continue;
222: }
223:
224: cur.dk_select[i] = cur.dk_select[j];
1.24 tedu 225: last.dk_rxfer[i] = last.dk_rxfer[j];
226: last.dk_wxfer[i] = last.dk_wxfer[j];
1.22 tdeval 227: last.dk_seek[i] = last.dk_seek[j];
1.24 tedu 228: last.dk_rbytes[i] = last.dk_rbytes[j];
229: last.dk_wbytes[i] = last.dk_wbytes[j];
1.22 tdeval 230: last.dk_time[i] = last.dk_time[j];
231: }
232:
233: cur.dk_select = realloc(cur.dk_select,
234: dk_ndrive * sizeof(*cur.dk_select));
1.24 tedu 235: cur.dk_rxfer = realloc(cur.dk_rxfer,
236: dk_ndrive * sizeof(*cur.dk_rxfer));
237: cur.dk_wxfer = realloc(cur.dk_wxfer,
238: dk_ndrive * sizeof(*cur.dk_wxfer));
1.22 tdeval 239: cur.dk_seek = realloc(cur.dk_seek,
240: dk_ndrive * sizeof(*cur.dk_seek));
1.24 tedu 241: cur.dk_rbytes = realloc(cur.dk_rbytes,
242: dk_ndrive * sizeof(*cur.dk_rbytes));
243: cur.dk_wbytes = realloc(cur.dk_wbytes,
244: dk_ndrive * sizeof(*cur.dk_wbytes));
1.22 tdeval 245: cur.dk_time = realloc(cur.dk_time,
246: dk_ndrive * sizeof(*cur.dk_time));
1.24 tedu 247: last.dk_rxfer = realloc(last.dk_rxfer,
248: dk_ndrive * sizeof(*last.dk_rxfer));
1.25 millert 249: last.dk_wxfer = realloc(last.dk_wxfer,
250: dk_ndrive * sizeof(*last.dk_wxfer));
1.22 tdeval 251: last.dk_seek = realloc(last.dk_seek,
252: dk_ndrive * sizeof(*last.dk_seek));
1.24 tedu 253: last.dk_rbytes = realloc(last.dk_rbytes,
254: dk_ndrive * sizeof(*last.dk_rbytes));
255: last.dk_wbytes = realloc(last.dk_wbytes,
256: dk_ndrive * sizeof(*last.dk_wbytes));
1.22 tdeval 257: last.dk_time = realloc(last.dk_time,
258: dk_ndrive * sizeof(*last.dk_time));
1.32 ! chl 259:
! 260: if (!cur.dk_select || !cur.dk_rxfer ||
! 261: !cur.dk_wxfer || !cur.dk_seek ||
! 262: !cur.dk_rbytes || !cur.dk_wbytes ||
! 263: !cur.dk_time || !last.dk_rxfer ||
! 264: !last.dk_wxfer || !last.dk_seek ||
! 265: !last.dk_rbytes || !last.dk_wbytes ||
! 266: !last.dk_time)
! 267: errx(1, "Memory allocation failure.");
1.22 tdeval 268: } else {
269: cur.dk_select = realloc(cur.dk_select,
270: dk_ndrive * sizeof(*cur.dk_select));
1.24 tedu 271: cur.dk_rxfer = realloc(cur.dk_rxfer,
272: dk_ndrive * sizeof(*cur.dk_rxfer));
273: cur.dk_wxfer = realloc(cur.dk_wxfer,
274: dk_ndrive * sizeof(*cur.dk_wxfer));
1.22 tdeval 275: cur.dk_seek = realloc(cur.dk_seek,
276: dk_ndrive * sizeof(*cur.dk_seek));
1.24 tedu 277: cur.dk_rbytes = realloc(cur.dk_rbytes,
278: dk_ndrive * sizeof(*cur.dk_rbytes));
279: cur.dk_wbytes = realloc(cur.dk_wbytes,
280: dk_ndrive * sizeof(*cur.dk_wbytes));
1.22 tdeval 281: cur.dk_time = realloc(cur.dk_time,
282: dk_ndrive * sizeof(*cur.dk_time));
1.24 tedu 283: last.dk_rxfer = realloc(last.dk_rxfer,
284: dk_ndrive * sizeof(*last.dk_rxfer));
285: last.dk_wxfer = realloc(last.dk_wxfer,
286: dk_ndrive * sizeof(*last.dk_wxfer));
1.22 tdeval 287: last.dk_seek = realloc(last.dk_seek,
288: dk_ndrive * sizeof(*last.dk_seek));
1.24 tedu 289: last.dk_rbytes = realloc(last.dk_rbytes,
290: dk_ndrive * sizeof(*last.dk_rbytes));
291: last.dk_wbytes = realloc(last.dk_wbytes,
292: dk_ndrive * sizeof(*last.dk_wbytes));
1.22 tdeval 293: last.dk_time = realloc(last.dk_time,
294: dk_ndrive * sizeof(*last.dk_time));
1.32 ! chl 295:
! 296: if (!cur.dk_select || !cur.dk_rxfer ||
! 297: !cur.dk_wxfer || !cur.dk_seek ||
! 298: !cur.dk_rbytes || !cur.dk_wbytes ||
! 299: !cur.dk_time || !last.dk_rxfer ||
! 300: !last.dk_wxfer || !last.dk_seek ||
! 301: !last.dk_rbytes || !last.dk_wbytes ||
! 302: !last.dk_time)
! 303: errx(1, "Memory allocation failure.");
1.22 tdeval 304:
305: for (i = dk_ndrive - 1, j = cur.dk_ndrive - 1;
306: i >= 0; i--) {
307:
308: if (j < 0 ||
309: strcmp(cur.dk_name[j], dk_name[i]))
310: {
311: cur.dk_select[i] = 1;
1.24 tedu 312: last.dk_rxfer[i] = 0;
313: last.dk_wxfer[i] = 0;
1.22 tdeval 314: last.dk_seek[i] = 0;
1.24 tedu 315: last.dk_rbytes[i] = 0;
316: last.dk_wbytes[i] = 0;
1.22 tdeval 317: bzero(&last.dk_time[i],
318: sizeof(struct timeval));
319: continue;
320: }
321:
322: if (i > j) {
323: cur.dk_select[i] =
324: cur.dk_select[j];
1.24 tedu 325: last.dk_rxfer[i] =
326: last.dk_rxfer[j];
327: last.dk_wxfer[i] =
328: last.dk_wxfer[j];
1.22 tdeval 329: last.dk_seek[i] =
330: last.dk_seek[j];
1.24 tedu 331: last.dk_rbytes[i] =
332: last.dk_rbytes[j];
333: last.dk_wbytes[i] =
334: last.dk_wbytes[j];
1.22 tdeval 335: last.dk_time[i] =
336: last.dk_time[j];
337: }
338: j--;
339: }
340: }
341:
342: cur.dk_ndrive = dk_ndrive;
343: free(disknames);
344: cur.dk_name = dk_name;
345: dr_name = cur.dk_name;
346: dk_select = cur.dk_select;
347: }
348:
349: size = cur.dk_ndrive * sizeof(struct diskstats);
1.10 angelos 350: mib[0] = CTL_HW;
351: mib[1] = HW_DISKSTATS;
1.13 angelos 352: q = malloc(size);
353: if (q == NULL)
1.10 angelos 354: err(1, NULL);
1.13 angelos 355: if (sysctl(mib, 2, q, &size, NULL, 0) < 0) {
1.22 tdeval 356: #ifdef DEBUG
1.10 angelos 357: warn("could not read hw.diskstats");
1.22 tdeval 358: #endif /* DEBUG */
359: bzero(q, cur.dk_ndrive * sizeof(struct diskstats));
1.10 angelos 360: }
361:
1.22 tdeval 362: for (i = 0; i < cur.dk_ndrive; i++) {
1.24 tedu 363: cur.dk_rxfer[i] = q[i].ds_rxfer;
364: cur.dk_wxfer[i] = q[i].ds_wxfer;
1.13 angelos 365: cur.dk_seek[i] = q[i].ds_seek;
1.24 tedu 366: cur.dk_rbytes[i] = q[i].ds_rbytes;
367: cur.dk_wbytes[i] = q[i].ds_wbytes;
1.13 angelos 368: timerset(&(q[i].ds_time), &(cur.dk_time[i]));
1.10 angelos 369: }
1.14 deraadt 370: free(q);
1.10 angelos 371:
1.30 deraadt 372: size = sizeof(cur.cp_time);
1.10 angelos 373: mib[0] = CTL_KERN;
374: mib[1] = KERN_CPTIME;
375: if (sysctl(mib, 2, cur.cp_time, &size, NULL, 0) < 0) {
1.11 angelos 376: warn("could not read kern.cp_time");
1.10 angelos 377: bzero(cur.cp_time, sizeof(cur.cp_time));
378: }
379: size = sizeof(cur.tk_nin);
380: mib[0] = CTL_KERN;
381: mib[1] = KERN_TTY;
382: mib[2] = KERN_TTY_TKNIN;
383: if (sysctl(mib, 3, &cur.tk_nin, &size, NULL, 0) < 0) {
1.11 angelos 384: warn("could not read kern.tty.tk_nin");
1.10 angelos 385: cur.tk_nin = 0;
386: }
387: size = sizeof(cur.tk_nin);
388: mib[0] = CTL_KERN;
389: mib[1] = KERN_TTY;
390: mib[2] = KERN_TTY_TKNOUT;
391: if (sysctl(mib, 3, &cur.tk_nout, &size, NULL, 0) < 0) {
1.11 angelos 392: warn("could not read kern.tty.tk_nout");
1.10 angelos 393: cur.tk_nout = 0;
394: }
395: } else {
1.16 deraadt 396: #if !defined(NOKVM)
1.10 angelos 397: p = dk_drivehead;
398:
1.22 tdeval 399: for (i = 0; i < cur.dk_ndrive; i++) {
1.10 angelos 400: deref_kptr(p, &cur_disk, sizeof(cur_disk));
1.24 tedu 401: cur.dk_rxfer[i] = cur_disk.dk_rxfer;
402: cur.dk_wxfer[i] = cur_disk.dk_wxfer;
1.10 angelos 403: cur.dk_seek[i] = cur_disk.dk_seek;
1.24 tedu 404: cur.dk_rbytes[i] = cur_disk.dk_rbytes;
405: cur.dk_wbytes[i] = cur_disk.dk_wbytes;
1.10 angelos 406: timerset(&(cur_disk.dk_time), &(cur.dk_time[i]));
1.27 otto 407: p = TAILQ_NEXT(&cur_disk, dk_link);
1.10 angelos 408: }
409: deref_nl(X_CP_TIME, cur.cp_time, sizeof(cur.cp_time));
410: deref_nl(X_TK_NIN, &cur.tk_nin, sizeof(cur.tk_nin));
411: deref_nl(X_TK_NOUT, &cur.tk_nout, sizeof(cur.tk_nout));
1.16 deraadt 412: #endif /* !defined(NOKVM) */
1.1 tholo 413: }
414: }
415:
416: /*
417: * Perform all of the initialization and memory allocation needed to
418: * track disk statistics.
419: */
420: int
1.28 otto 421: dkinit(int sel)
1.1 tholo 422: {
1.19 deraadt 423: #if !defined(NOKVM)
1.1 tholo 424: struct disklist_head disk_head;
425: struct disk cur_disk, *p;
426: char errbuf[_POSIX2_LINE_MAX];
1.19 deraadt 427: #endif
1.1 tholo 428: static int once = 0;
429: extern int hz;
1.10 angelos 430: int i, mib[2];
431: size_t size;
432: struct clockinfo clkinfo;
433: char *disknames, *name, *bufpp;
1.26 djm 434: gid_t gid;
1.1 tholo 435:
436: if (once)
437: return(1);
438:
1.26 djm 439: gid = getgid();
1.10 angelos 440: if (nlistf != NULL || memf != NULL) {
1.16 deraadt 441: #if !defined(NOKVM)
1.26 djm 442: if (memf != NULL)
443: if (setresgid(gid, gid, gid) == -1)
444: err(1, "setresgid");
1.20 deraadt 445:
1.10 angelos 446: /* Open the kernel. */
1.20 deraadt 447: if (kd == NULL &&
448: (kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY,
1.10 angelos 449: errbuf)) == NULL)
450: errx(1, "kvm_openfiles: %s", errbuf);
1.20 deraadt 451:
1.26 djm 452: if (memf == NULL)
453: if (setresgid(gid, gid, gid) == -1)
454: err(1, "setresgid");
1.10 angelos 455:
456: /* Obtain the namelist symbols from the kernel. */
457: if (kvm_nlist(kd, namelist))
458: KVM_ERROR("kvm_nlist failed to read symbols.");
459:
460: /* Get the number of attached drives. */
1.22 tdeval 461: deref_nl(X_DISK_COUNT, &cur.dk_ndrive, sizeof(cur.dk_ndrive));
1.10 angelos 462:
1.22 tdeval 463: if (cur.dk_ndrive < 0)
464: errx(1, "invalid _disk_count %d.", cur.dk_ndrive);
1.10 angelos 465:
1.1 tholo 466: /* Get a pointer to the first disk. */
467: deref_nl(X_DISKLIST, &disk_head, sizeof(disk_head));
1.27 otto 468: dk_drivehead = TAILQ_FIRST(&disk_head);
1.10 angelos 469:
470: /* Get ticks per second. */
471: deref_nl(X_STATHZ, &hz, sizeof(hz));
472: if (!hz)
473: deref_nl(X_HZ, &hz, sizeof(hz));
1.16 deraadt 474: #endif /* !defined(NOKVM) */
1.10 angelos 475: } else {
476: /* Get the number of attached drives. */
477: mib[0] = CTL_HW;
478: mib[1] = HW_DISKCOUNT;
1.22 tdeval 479: size = sizeof(cur.dk_ndrive);
480: if (sysctl(mib, 2, &cur.dk_ndrive, &size, NULL, 0) < 0 ) {
1.11 angelos 481: warn("could not read hw.diskcount");
1.22 tdeval 482: cur.dk_ndrive = 0;
1.10 angelos 483: }
484:
485: /* Get ticks per second. */
486: mib[0] = CTL_KERN;
487: mib[1] = KERN_CLOCKRATE;
488: size = sizeof(clkinfo);
489: if (sysctl(mib, 2, &clkinfo, &size, NULL, 0) < 0) {
1.11 angelos 490: warn("could not read kern.clockrate");
1.10 angelos 491: hz = 0;
492: } else
493: hz = clkinfo.stathz;
1.1 tholo 494: }
495:
496: /* allocate space for the statistics */
1.29 deraadt 497: cur.dk_time = calloc((size_t)cur.dk_ndrive, sizeof(struct timeval));
498: cur.dk_rxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
499: cur.dk_wxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
500: cur.dk_seek = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
501: cur.dk_rbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
502: cur.dk_wbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
1.31 chl 503: cur.dk_select = calloc((size_t)cur.dk_ndrive, sizeof(int));
504: cur.dk_name = calloc((size_t)cur.dk_ndrive, sizeof(char *));
1.29 deraadt 505: last.dk_time = calloc((size_t)cur.dk_ndrive, sizeof(struct timeval));
506: last.dk_rxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
507: last.dk_wxfer = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
508: last.dk_seek = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
509: last.dk_rbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
510: last.dk_wbytes = calloc((size_t)cur.dk_ndrive, sizeof(u_int64_t));
1.30 deraadt 511:
1.24 tedu 512: if (!cur.dk_time || !cur.dk_rxfer || !cur.dk_wxfer || !cur.dk_seek ||
1.31 chl 513: !cur.dk_rbytes || !cur.dk_wbytes || !cur.dk_select ||
514: !cur.dk_name || !last.dk_time || !last.dk_rxfer ||
515: !last.dk_wxfer || !last.dk_seek || !last.dk_rbytes ||
516: !last.dk_wbytes)
1.1 tholo 517: errx(1, "Memory allocation failure.");
518:
519: /* Set up the compatibility interfaces. */
1.22 tdeval 520: dk_ndrive = cur.dk_ndrive;
1.1 tholo 521: dk_select = cur.dk_select;
522: dr_name = cur.dk_name;
523:
1.22 tdeval 524: /* Read the disk names and set initial selection. */
1.10 angelos 525: if (nlistf == NULL && memf == NULL) {
526: mib[0] = CTL_HW;
527: mib[1] = HW_DISKNAMES;
528: size = 0;
529: if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
530: err(1, "can't get hw.disknames");
1.12 angelos 531: disknames = malloc(size);
1.10 angelos 532: if (disknames == NULL)
533: err(1, NULL);
534: if (sysctl(mib, 2, disknames, &size, NULL, 0) < 0)
535: err(1, "can't get hw.disknames");
536: bufpp = disknames;
1.23 millert 537: for (i = 0; i < dk_ndrive && (name = strsep(&bufpp, ",")) != NULL; i++) {
538: cur.dk_name[i] = name;
1.28 otto 539: cur.dk_select[i] = sel;
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:
559: /* Never do this initalization again. */
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.1 tholo 576: bzero(buf, sizeof(buf));
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) */