Module Name: src Committed By: joerg Date: Mon Jun 2 19:29:00 UTC 2014
Modified Files: src/usr.bin/vmstat: drvstats.c Log Message: Drop kvm-based access for driver statistics. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/usr.bin/vmstat/drvstats.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/vmstat/drvstats.c diff -u src/usr.bin/vmstat/drvstats.c:1.6 src/usr.bin/vmstat/drvstats.c:1.7 --- src/usr.bin/vmstat/drvstats.c:1.6 Tue Nov 13 14:09:58 2012 +++ src/usr.bin/vmstat/drvstats.c Mon Jun 2 19:29:00 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: drvstats.c,v 1.6 2012/11/13 14:09:58 chs Exp $ */ +/* $NetBSD: drvstats.c,v 1.7 2014/06/02 19:29:00 joerg Exp $ */ /* * Copyright (c) 1996 John M. Vinopal @@ -49,29 +49,9 @@ #include <unistd.h> #include "drvstats.h" -static struct nlist namelist[] = { -#define X_TK_NIN 0 - { .n_name = "_tk_nin" }, /* tty characters in */ -#define X_TK_NOUT 1 - { .n_name = "_tk_nout" }, /* tty characters out */ -#define X_HZ 2 - { .n_name = "_hz" }, /* ticks per second */ -#define X_STATHZ 3 - { .n_name = "_stathz" }, -#define X_DRIVE_COUNT 4 - { .n_name = "_iostat_count" }, /* number of drives */ -#define X_DRIVELIST 5 - { .n_name = "_iostatlist" }, /* TAILQ of drives */ - { .n_name = NULL }, -}; - /* Structures to hold the statistics. */ struct _drive cur, last; -/* Kernel pointers: nlistf and memf defined in calling program. */ -static kvm_t *kd = NULL; -extern char *nlistf; -extern char *memf; extern int hz; /* Pointer to list of drives. */ @@ -84,27 +64,12 @@ size_t ndrive = 0; int *drv_select; char **dr_name; -#define KVM_ERROR(_string) do { \ - warnx("%s", (_string)); \ - errx(1, "%s", kvm_geterr(kd)); \ -} while (/* CONSTCOND */0) - -/* - * Dereference the namelist pointer `v' and fill in the local copy - * 'p' which is of size 's'. - */ -#define deref_nl(v, p, s) do { \ - deref_kptr((void *)namelist[(v)].n_value, (p), (s)); \ -} while (/* CONSTCOND */0) - /* Missing from <sys/time.h> */ #define timerset(tvp, uvp) do { \ ((uvp)->tv_sec = (tvp)->tv_sec); \ ((uvp)->tv_usec = (tvp)->tv_usec); \ } while (/* CONSTCOND */0) -static void deref_kptr(void *, void *, size_t); - /* * Take the delta between the present values and the last recorded * values, storing the present values in the 'last' structure, and @@ -183,70 +148,47 @@ cpuswap(void) void drvreadstats(void) { - struct io_stats cur_drive, *p; + struct io_stats *p; size_t size, i; int mib[3]; p = iostathead; - if (memf == NULL) { - mib[0] = CTL_HW; - mib[1] = HW_IOSTATS; - mib[2] = sizeof(struct io_sysctl); - - size = ndrive * sizeof(struct io_sysctl); - if (sysctl(mib, 3, drives, &size, NULL, 0) < 0) - err(1, "sysctl hw.iostats failed"); - for (i = 0; i < ndrive; i++) { - cur.rxfer[i] = drives[i].rxfer; - cur.wxfer[i] = drives[i].wxfer; - cur.seek[i] = drives[i].seek; - cur.rbytes[i] = drives[i].rbytes; - cur.wbytes[i] = drives[i].wbytes; - cur.time[i].tv_sec = drives[i].time_sec; - cur.time[i].tv_usec = drives[i].time_usec; - } + mib[0] = CTL_HW; + mib[1] = HW_IOSTATS; + mib[2] = sizeof(struct io_sysctl); + + size = ndrive * sizeof(struct io_sysctl); + if (sysctl(mib, 3, drives, &size, NULL, 0) < 0) + err(1, "sysctl hw.iostats failed"); + for (i = 0; i < ndrive; i++) { + cur.rxfer[i] = drives[i].rxfer; + cur.wxfer[i] = drives[i].wxfer; + cur.seek[i] = drives[i].seek; + cur.rbytes[i] = drives[i].rbytes; + cur.wbytes[i] = drives[i].wbytes; + cur.time[i].tv_sec = drives[i].time_sec; + cur.time[i].tv_usec = drives[i].time_usec; + } mib[0] = CTL_KERN; - mib[1] = KERN_TKSTAT; - mib[2] = KERN_TKSTAT_NIN; - size = sizeof(cur.tk_nin); - if (sysctl(mib, 3, &cur.tk_nin, &size, NULL, 0) < 0) - cur.tk_nin = 0; - - mib[2] = KERN_TKSTAT_NOUT; - size = sizeof(cur.tk_nout); - if (sysctl(mib, 3, &cur.tk_nout, &size, NULL, 0) < 0) - cur.tk_nout = 0; - } else { - for (i = 0; i < ndrive; i++) { - deref_kptr(p, &cur_drive, sizeof(cur_drive)); - cur.rxfer[i] = cur_drive.io_rxfer; - cur.wxfer[i] = cur_drive.io_wxfer; - cur.seek[i] = cur_drive.io_seek; - cur.rbytes[i] = cur_drive.io_rbytes; - cur.wbytes[i] = cur_drive.io_wbytes; - timerset(&(cur_drive.io_time), &(cur.time[i])); - p = cur_drive.io_link.tqe_next; - } - - deref_nl(X_TK_NIN, &cur.tk_nin, sizeof(cur.tk_nin)); - deref_nl(X_TK_NOUT, &cur.tk_nout, sizeof(cur.tk_nout)); - } + mib[1] = KERN_TKSTAT; + mib[2] = KERN_TKSTAT_NIN; + size = sizeof(cur.tk_nin); + if (sysctl(mib, 3, &cur.tk_nin, &size, NULL, 0) < 0) + cur.tk_nin = 0; + + mib[2] = KERN_TKSTAT_NOUT; + size = sizeof(cur.tk_nout); + if (sysctl(mib, 3, &cur.tk_nout, &size, NULL, 0) < 0) + cur.tk_nout = 0; - /* - * XXX Need to locate the `correct' CPU when looking for this - * XXX in crash dumps. Just don't report it for now, in that - * XXX case. - */ size = sizeof(cur.cp_time); (void)memset(cur.cp_time, 0, size); - if (memf == NULL) { - mib[0] = CTL_KERN; - mib[1] = KERN_CP_TIME; - if (sysctl(mib, 2, cur.cp_time, &size, NULL, 0) < 0) - (void)memset(cur.cp_time, 0, sizeof(cur.cp_time)); - } + mib[0] = CTL_KERN; + mib[1] = KERN_CP_TIME; + if (sysctl(mib, 2, cur.cp_time, &size, NULL, 0) < 0) + (void)memset(cur.cp_time, 0, sizeof(cur.cp_time)); } /* @@ -259,22 +201,17 @@ tkreadstats(void) size_t size; int mib[3]; - if (memf == NULL) { - mib[0] = CTL_KERN; - mib[1] = KERN_TKSTAT; - mib[2] = KERN_TKSTAT_NIN; - size = sizeof(cur.tk_nin); - if (sysctl(mib, 3, &cur.tk_nin, &size, NULL, 0) < 0) - cur.tk_nin = 0; - - mib[2] = KERN_TKSTAT_NOUT; - size = sizeof(cur.tk_nout); - if (sysctl(mib, 3, &cur.tk_nout, &size, NULL, 0) < 0) - cur.tk_nout = 0; - } else { - deref_nl(X_TK_NIN, &cur.tk_nin, sizeof(cur.tk_nin)); - deref_nl(X_TK_NOUT, &cur.tk_nout, sizeof(cur.tk_nout)); - } + mib[0] = CTL_KERN; + mib[1] = KERN_TKSTAT; + mib[2] = KERN_TKSTAT_NIN; + size = sizeof(cur.tk_nin); + if (sysctl(mib, 3, &cur.tk_nin, &size, NULL, 0) < 0) + cur.tk_nin = 0; + + mib[2] = KERN_TKSTAT_NOUT; + size = sizeof(cur.tk_nout); + if (sysctl(mib, 3, &cur.tk_nout, &size, NULL, 0) < 0) + cur.tk_nout = 0; } /* @@ -287,19 +224,12 @@ cpureadstats(void) size_t size; int mib[2]; - /* - * XXX Need to locate the `correct' CPU when looking for this - * XXX in crash dumps. Just don't report it for now, in that - * XXX case. - */ size = sizeof(cur.cp_time); (void)memset(cur.cp_time, 0, size); - if (memf == NULL) { - mib[0] = CTL_KERN; - mib[1] = KERN_CP_TIME; - if (sysctl(mib, 2, cur.cp_time, &size, NULL, 0) < 0) - (void)memset(cur.cp_time, 0, sizeof(cur.cp_time)); - } + mib[0] = CTL_KERN; + mib[1] = KERN_CP_TIME; + if (sysctl(mib, 2, cur.cp_time, &size, NULL, 0) < 0) + (void)memset(cur.cp_time, 0, sizeof(cur.cp_time)); } /* @@ -309,10 +239,7 @@ cpureadstats(void) int drvinit(int selected) { - struct iostatlist_head iostat_head; - struct io_stats cur_drive, *p; struct clockinfo clockinfo; - char errbuf[_POSIX2_LINE_MAX]; size_t size, i; static int once = 0; int mib[3]; @@ -320,66 +247,34 @@ drvinit(int selected) if (once) return (1); - if (memf == NULL) { - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - size = sizeof(cur.cp_ncpu); - if (sysctl(mib, 2, &cur.cp_ncpu, &size, NULL, 0) == -1) - err(1, "sysctl hw.ncpu failed"); + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + size = sizeof(cur.cp_ncpu); + if (sysctl(mib, 2, &cur.cp_ncpu, &size, NULL, 0) == -1) + err(1, "sysctl hw.ncpu failed"); + + mib[0] = CTL_KERN; + mib[1] = KERN_CLOCKRATE; + size = sizeof(clockinfo); + if (sysctl(mib, 2, &clockinfo, &size, NULL, 0) == -1) + err(1, "sysctl kern.clockrate failed"); + hz = clockinfo.stathz; + if (!hz) + hz = clockinfo.hz; + + mib[0] = CTL_HW; + mib[1] = HW_IOSTATS; + mib[2] = sizeof(struct io_sysctl); + if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1) + err(1, "sysctl hw.drivestats failed"); + ndrive = size / sizeof(struct io_sysctl); - mib[0] = CTL_KERN; - mib[1] = KERN_CLOCKRATE; - size = sizeof(clockinfo); - if (sysctl(mib, 2, &clockinfo, &size, NULL, 0) == -1) - err(1, "sysctl kern.clockrate failed"); - hz = clockinfo.stathz; - if (!hz) - hz = clockinfo.hz; - - mib[0] = CTL_HW; - mib[1] = HW_IOSTATS; - mib[2] = sizeof(struct io_sysctl); - if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1) - err(1, "sysctl hw.drivestats failed"); - ndrive = size / sizeof(struct io_sysctl); - - if (size == 0) { - warnx("No drives attached."); - } else { - drives = (struct io_sysctl *)malloc(size); - if (drives == NULL) - errx(1, "Memory allocation failure."); - } + if (size == 0) { + warnx("No drives attached."); } else { - int drive_count; - /* Open the kernel. */ - if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, - errbuf)) == NULL) - errx(1, "kvm_openfiles: %s", errbuf); - - /* Obtain the namelist symbols from the kernel. */ - if (kvm_nlist(kd, namelist)) - KVM_ERROR("kvm_nlist failed to read symbols."); - - /* Get the number of attached drives. */ - deref_nl(X_DRIVE_COUNT, &drive_count, sizeof(drive_count)); - - if (drive_count < 0) - errx(1, "invalid _drive_count %d.", drive_count); - else if (drive_count == 0) { - warnx("No drives attached."); - } else { - /* Get a pointer to the first drive. */ - deref_nl(X_DRIVELIST, &iostat_head, - sizeof(iostat_head)); - iostathead = iostat_head.tqh_first; - } - ndrive = drive_count; - - /* Get ticks per second. */ - deref_nl(X_STATHZ, &hz, sizeof(hz)); - if (!hz) - deref_nl(X_HZ, &hz, sizeof(hz)); + drives = (struct io_sysctl *)malloc(size); + if (drives == NULL) + errx(1, "Memory allocation failure."); } /* Allocate space for the statistics. */ @@ -412,48 +307,17 @@ drvinit(int selected) dr_name = cur.name; /* Read the drive names and set intial selection. */ - if (memf == NULL) { - mib[0] = CTL_HW; /* Should be still set from */ - mib[1] = HW_IOSTATS; /* ... above, but be safe... */ - mib[2] = sizeof(struct io_sysctl); - if (sysctl(mib, 3, drives, &size, NULL, 0) == -1) - err(1, "sysctl hw.iostats failed"); - for (i = 0; i < ndrive; i++) { - cur.name[i] = drives[i].name; - cur.select[i] = selected; - } - } else { - p = iostathead; - for (i = 0; i < ndrive; i++) { - deref_kptr(p, &cur_drive, sizeof(cur_drive)); - cur.name[i] = strdup(cur_drive.io_name); - if (!cur.name[i]) - err(1, "strdup"); - cur.select[i] = selected; - - p = cur_drive.io_link.tqe_next; - } + mib[0] = CTL_HW; /* Should be still set from */ + mib[1] = HW_IOSTATS; /* ... above, but be safe... */ + mib[2] = sizeof(struct io_sysctl); + if (sysctl(mib, 3, drives, &size, NULL, 0) == -1) + err(1, "sysctl hw.iostats failed"); + for (i = 0; i < ndrive; i++) { + cur.name[i] = drives[i].name; + cur.select[i] = selected; } /* Never do this initialization again. */ once = 1; return (1); } - -/* - * Dereference the kernel pointer `kptr' and fill in the local copy - * pointed to by `ptr'. The storage space must be pre-allocated, - * and the size of the copy passed in `len'. - */ -static void -deref_kptr(void *kptr, void *ptr, size_t len) -{ - char buf[128]; - - if ((size_t)kvm_read(kd, (u_long)kptr, (char *)ptr, len) != len) { - (void)memset(buf, 0, sizeof(buf)); - (void)snprintf(buf, sizeof buf, "can't dereference kptr 0x%lx", - (u_long)kptr); - KVM_ERROR(buf); - } -}