summaryrefslogtreecommitdiffstats
path: root/usr.sbin/iostat/iostat.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/iostat/iostat.c')
-rw-r--r--usr.sbin/iostat/iostat.c171
1 files changed, 107 insertions, 64 deletions
diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c
index 6568824..8a8cdc8 100644
--- a/usr.sbin/iostat/iostat.c
+++ b/usr.sbin/iostat/iostat.c
@@ -103,6 +103,7 @@
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/dkstat.h>
+#include <sys/sysctl.h>
#include <err.h>
#include <ctype.h>
@@ -142,8 +143,9 @@ int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0;
/* local function declarations */
static void usage(void);
static void phdr(int signo);
-static void devstats(int perf_select);
+static void devstats(int perf_select,double etime, int havelast);
static void cpustats(void);
+static void getsysctl(const char *, void *, size_t);
static void
usage(void)
@@ -170,7 +172,7 @@ main(int argc, char **argv)
struct devstat_match *matches;
int num_matches = 0;
char errbuf[_POSIX2_LINE_MAX];
- kvm_t *kd;
+ kvm_t *kd = NULL;
int hz, stathz;
int headercount;
long generation;
@@ -179,6 +181,8 @@ main(int argc, char **argv)
long select_generation;
char **specified_devices;
devstat_select_mode select_mode;
+ int use_kvm, havelast = 0;
+ struct clockinfo clkinfo;
matches = NULL;
maxshowdevs = 3;
@@ -224,8 +228,8 @@ main(int argc, char **argv)
break;
case 't':
tflag++;
- if (buildmatch(optarg, &matches,
- &num_matches) != 0)
+ if (devstat_buildmatch(optarg, &matches,
+ &num_matches) != 0)
errx(1, "%s", devstat_errbuf);
break;
case 'T':
@@ -247,19 +251,32 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
- /*
- * Discard setgid privileges if not the running kernel so that bad
- * guys can't print interesting stuff from kernel memory.
- */
- if (nlistf != NULL || memf != NULL)
- setgid(getgid());
+ if (nlistf == NULL && memf == NULL) {
+ use_kvm = 0;
+ getsysctl("kern.clockrate", &clkinfo, sizeof(clkinfo));
+ hz = clkinfo.hz;
+ } else {
+ use_kvm = 1;
+ kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
+
+ if (kd == 0)
+ errx(1, "kvm_openfiles: %s", errbuf);
+
+ if (kvm_nlist(kd, namelist) == -1)
+ errx(1, "kvm_nlist: %s", kvm_geterr(kd));
+
+ (void)nlread(X_HZ, hz);
+ (void)nlread(X_STATHZ, stathz);
+ if (stathz)
+ hz = stathz;
+ }
/*
* Make sure that the userland devstat version matches the kernel
* devstat version. If not, exit and print a message informing
* the user of his mistake.
*/
- if (checkversion() < 0)
+ if (devstat_checkversion(kd) < 0)
errx(1, "%s", devstat_errbuf);
/*
@@ -282,7 +299,7 @@ main(int argc, char **argv)
}
/* find out how many devices we have */
- if ((num_devices = getnumdevs()) < 0)
+ if ((num_devices = devstat_getnumdevs(kd)) < 0)
err(1, "can't get number of devices");
if ((cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo))) ==
@@ -299,7 +316,7 @@ main(int argc, char **argv)
* changed here, since it almost certainly has. We only look for
* errors.
*/
- if (getdevs(&cur) == -1)
+ if (devstat_getdevs(kd, &cur) == -1)
errx(1, "%s", devstat_errbuf);
num_devices = cur.dinfo->numdevs;
@@ -336,12 +353,12 @@ main(int argc, char **argv)
* device list has changed, so we don't look for return values of 0
* or 1. If we get back -1, though, there is an error.
*/
- if (selectdevs(&dev_select, &num_selected,
- &num_selections, &select_generation,
- generation, cur.dinfo->devices, num_devices,
- matches, num_matches,
- specified_devices, num_devices_specified,
- select_mode, maxshowdevs, hflag) == -1)
+ if (devstat_selectdevs(&dev_select, &num_selected,
+ &num_selections, &select_generation, generation,
+ cur.dinfo->devices, num_devices, matches,
+ num_matches, specified_devices,
+ num_devices_specified, select_mode, maxshowdevs,
+ hflag) == -1)
errx(1, "%s", devstat_errbuf);
/*
@@ -382,19 +399,6 @@ main(int argc, char **argv)
if ((wflag > 0) && (cflag == 0))
count = -1;
- kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
-
- if (kd == 0)
- errx(1, "kvm_openfiles: %s", errbuf);
-
- if (kvm_nlist(kd, namelist) == -1)
- errx(1, "kvm_nlist: %s", kvm_geterr(kd));
-
- (void)nlread(X_HZ, hz);
- (void)nlread(X_STATHZ, stathz);
- if (stathz)
- hz = stathz;
-
/*
* If the user stops the program (control-Z) and then resumes it,
* print out the header again.
@@ -410,12 +414,21 @@ main(int argc, char **argv)
phdr(0);
headercount = 20;
}
- (void)kvm_read(kd, namelist[X_TK_NIN].n_value,
- &cur.tk_nin, sizeof(cur.tk_nin));
- (void)kvm_read(kd, namelist[X_TK_NOUT].n_value,
- &cur.tk_nout, sizeof(cur.tk_nout));
- (void)kvm_read(kd, namelist[X_CP_TIME].n_value,
- cur.cp_time, sizeof(cur.cp_time));
+ if (use_kvm) {
+ (void)kvm_read(kd, namelist[X_TK_NIN].n_value,
+ &cur.tk_nin, sizeof(cur.tk_nin));
+ (void)kvm_read(kd, namelist[X_TK_NOUT].n_value,
+ &cur.tk_nout, sizeof(cur.tk_nout));
+ (void)kvm_read(kd, namelist[X_CP_TIME].n_value,
+ cur.cp_time, sizeof(cur.cp_time));
+ } else {
+ getsysctl("kern.tty_nin", &cur.tk_nin,
+ sizeof(cur.tk_nin));
+ getsysctl("kern.tty_nout", &cur.tk_nout,
+ sizeof(cur.tk_nout));
+ getsysctl("kern.cp_time", &cur.cp_time,
+ sizeof(cur.cp_time));
+ }
tmp_dinfo = last.dinfo;
last.dinfo = cur.dinfo;
@@ -425,12 +438,12 @@ main(int argc, char **argv)
/*
* Here what we want to do is refresh our device stats.
- * getdevs() returns 1 when the device list has changed.
+ * devstat_getdevs() returns 1 when the device list has changed.
* If the device list has changed, we want to go through
* the selection process again, in case a device that we
* were previously displaying has gone away.
*/
- switch (getdevs(&cur)) {
+ switch (devstat_getdevs(kd, &cur)) {
case -1:
errx(1, "%s", devstat_errbuf);
break;
@@ -439,13 +452,17 @@ main(int argc, char **argv)
num_devices = cur.dinfo->numdevs;
generation = cur.dinfo->generation;
- retval = selectdevs(&dev_select, &num_selected,
- &num_selections, &select_generation,
- generation, cur.dinfo->devices,
- num_devices, matches, num_matches,
- specified_devices,
- num_devices_specified,
- select_mode, maxshowdevs, hflag);
+ retval = devstat_selectdevs(&dev_select, &num_selected,
+ &num_selections,
+ &select_generation,
+ generation,
+ cur.dinfo->devices,
+ num_devices, matches,
+ num_matches,
+ specified_devices,
+ num_devices_specified,
+ select_mode, maxshowdevs,
+ hflag);
switch(retval) {
case -1:
errx(1, "%s", devstat_errbuf);
@@ -470,13 +487,17 @@ main(int argc, char **argv)
*/
if (hflag > 0) {
int retval;
- retval = selectdevs(&dev_select, &num_selected,
- &num_selections, &select_generation,
- generation, cur.dinfo->devices,
- num_devices, matches, num_matches,
- specified_devices,
- num_devices_specified,
- select_mode, maxshowdevs, hflag);
+ retval = devstat_selectdevs(&dev_select, &num_selected,
+ &num_selections,
+ &select_generation,
+ generation,
+ cur.dinfo->devices,
+ num_devices, matches,
+ num_matches,
+ specified_devices,
+ num_devices_specified,
+ select_mode, maxshowdevs,
+ hflag);
switch(retval) {
case -1:
errx(1,"%s", devstat_errbuf);
@@ -505,13 +526,13 @@ main(int argc, char **argv)
X(cp_time);
etime += cur.cp_time[i];
}
+ etime /= (float)hz;
if (etime == 0.0)
etime = 1.0;
- etime /= (float)hz;
if ((dflag == 0) || (Tflag > 0))
printf("%4.0f%5.0f", cur.tk_nin / etime,
cur.tk_nout/etime);
- devstats(hflag);
+ devstats(hflag, etime, havelast);
if ((dflag == 0) || (Cflag > 0))
cpustats();
printf("\n");
@@ -521,6 +542,7 @@ main(int argc, char **argv)
break;
sleep(waittime);
+ havelast = 1;
}
exit(0);
@@ -583,7 +605,7 @@ phdr(int signo)
}
static void
-devstats(int perf_select)
+devstats(int perf_select, double etime, int havelast)
{
register int dn;
long double transfers_per_second;
@@ -597,7 +619,11 @@ devstats(int perf_select)
* Calculate elapsed time up front, since it's the same for all
* devices.
*/
- busy_seconds = compute_etime(cur.busy_time, last.busy_time);
+ if (havelast)
+ busy_seconds = devstat_compute_etime(cur.busy_time,
+ last.busy_time);
+ else
+ busy_seconds = etime;
for (dn = 0; dn < num_devices; dn++) {
int di;
@@ -608,12 +634,17 @@ devstats(int perf_select)
di = dev_select[dn].position;
- if (compute_stats(&cur.dinfo->devices[di],
- &last.dinfo->devices[di], busy_seconds,
- &total_bytes, &total_transfers,
- &total_blocks, &kb_per_transfer,
- &transfers_per_second, &mb_per_second,
- &blocks_per_second, &ms_per_transaction)!= 0)
+ if (devstat_compute_statistics(&cur.dinfo->devices[di],
+ havelast ? &last.dinfo->devices[di] : NULL, busy_seconds,
+ DSM_TOTAL_BYTES, &total_bytes,
+ DSM_TOTAL_TRANSFERS, &total_transfers,
+ DSM_TOTAL_BLOCKS, &total_blocks,
+ DSM_KB_PER_TRANSFER, &kb_per_transfer,
+ DSM_TRANSFERS_PER_SECOND, &transfers_per_second,
+ DSM_MB_PER_SECOND, &mb_per_second,
+ DSM_BLOCKS_PER_SECOND, &blocks_per_second,
+ DSM_MS_PER_TRANSACTION, &ms_per_transaction,
+ DSM_NONE) != 0)
errx(1, "%s", devstat_errbuf);
if (perf_select != 0) {
@@ -677,3 +708,15 @@ cpustats(void)
printf("%3.0f",
100. * cur.cp_time[state] / (time ? time : 1));
}
+
+static void
+getsysctl(const char *name, void *ptr, size_t len)
+{
+ size_t nlen = len;
+
+ if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)
+ err(1, "sysctl(%s...) failed", name);
+ if (nlen != len)
+ errx(1, "sysctl(%s...): expected %lu, got %lu", name,
+ (unsigned long)len, (unsigned long)nlen);
+}
OpenPOWER on IntegriCloud