Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/vmstat Restore the kvm-grovelling code for use on cr...
details: https://anonhg.NetBSD.org/src/rev/deedfd57db67
branches: trunk
changeset: 350013:deedfd57db67
user: pgoyette <pgoyette%NetBSD.org@localhost>
date: Mon Jan 02 01:48:56 2017 +0000
description:
Restore the kvm-grovelling code for use on crash files (where sysctl(3)
is not available). Otherwise, this would always report on the current
running kernel regardless of the use of -M option.
diffstat:
usr.bin/vmstat/vmstat.c | 224 +++++++++++++++++++++++++++++++++++++----------
1 files changed, 175 insertions(+), 49 deletions(-)
diffs (truncated from 314 to 300 lines):
diff -r f941d437ed68 -r deedfd57db67 usr.bin/vmstat/vmstat.c
--- a/usr.bin/vmstat/vmstat.c Mon Jan 02 01:18:42 2017 +0000
+++ b/usr.bin/vmstat/vmstat.c Mon Jan 02 01:48:56 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vmstat.c,v 1.209 2017/01/02 01:02:19 pgoyette Exp $ */
+/* $NetBSD: vmstat.c,v 1.210 2017/01/02 01:48:56 pgoyette Exp $ */
/*-
* Copyright (c) 1998, 2000, 2001, 2007 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
#if 0
static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95";
#else
-__RCSID("$NetBSD: vmstat.c,v 1.209 2017/01/02 01:02:19 pgoyette Exp $");
+__RCSID("$NetBSD: vmstat.c,v 1.210 2017/01/02 01:48:56 pgoyette Exp $");
#endif
#endif /* not lint */
@@ -309,7 +309,9 @@
void doforkst(void);
void hist_traverse(int, const char *);
-void hist_dodump(int[], unsigned int);
+void hist_dodump(struct kern_history *);
+void hist_traverse_sysctl(int, const char *);
+void hist_dodump_sysctl(int[], unsigned int);
char **choosedrives(char **);
@@ -475,7 +477,10 @@
(HISTLIST|HISTDUMP))
errx(1, "you may list or dump,"
" but not both!");
- hist_traverse(todo, histname);
+ if (memf != NULL)
+ hist_traverse(todo, histname);
+ else
+ hist_traverse_sysctl(todo, histname);
(void)putchar('\n');
}
if (todo & FORKSTAT) {
@@ -2000,6 +2005,127 @@
void
hist_traverse(int todo, const char *histname)
{
+ struct kern_history_head histhead;
+ struct kern_history hist, *histkva;
+ char *name = NULL;
+ size_t namelen = 0;
+
+ if (histnl[0].n_value == 0) {
+ warnx("kernel history is not compiled into the kernel.");
+ return;
+ }
+
+ deref_kptr((void *)histnl[X_KERN_HISTORIES].n_value, &histhead,
+ sizeof(histhead), histnl[X_KERN_HISTORIES].n_name);
+
+ if (histhead.lh_first == NULL) {
+ warnx("No active kernel history logs.");
+ return;
+ }
+
+ if (todo & HISTLIST)
+ (void)printf("Active kernel histories:");
+
+ for (histkva = LIST_FIRST(&histhead); histkva != NULL;
+ histkva = LIST_NEXT(&hist, list)) {
+ deref_kptr(histkva, &hist, sizeof(hist), "histkva");
+ if (name == NULL || hist.namelen > namelen) {
+ if (name != NULL)
+ free(name);
+ namelen = hist.namelen;
+ if ((name = malloc(namelen + 1)) == NULL)
+ err(1, "malloc history name");
+ }
+
+ deref_kptr(hist.name, name, namelen, "history name");
+ name[namelen] = '\0';
+ if (todo & HISTLIST)
+ (void)printf(" %s", name);
+ else {
+ /*
+ * If we're dumping all histories, do it, else
+ * check to see if this is the one we want.
+ */
+ if (histname == NULL || strcmp(histname, name) == 0) {
+ if (histname == NULL)
+ (void)printf(
+ "\nkernel history `%s':\n", name);
+ hist_dodump(&hist);
+ }
+ }
+ }
+
+ if (todo & HISTLIST)
+ (void)putchar('\n');
+
+ if (name != NULL)
+ free(name);
+}
+
+/*
+ * Actually dump the history buffer at the specified KVA.
+ */
+void
+hist_dodump(struct kern_history *histp)
+{
+ struct kern_history_ent *histents, *e;
+ size_t histsize;
+ char *fmt = NULL, *fn = NULL;
+ size_t fmtlen = 0, fnlen = 0;
+ unsigned i;
+
+ histsize = sizeof(struct kern_history_ent) * histp->n;
+
+ if ((histents = malloc(histsize)) == NULL)
+ err(1, "malloc history entries");
+
+ (void)memset(histents, 0, histsize);
+
+ deref_kptr(histp->e, histents, histsize, "history entries");
+ i = histp->f;
+ do {
+ e = &histents[i];
+ if (e->fmt != NULL) {
+ if (fmt == NULL || e->fmtlen > fmtlen) {
+ if (fmt != NULL)
+ free(fmt);
+ fmtlen = e->fmtlen;
+ if ((fmt = malloc(fmtlen + 1)) == NULL)
+ err(1, "malloc printf format");
+ }
+ if (fn == NULL || e->fnlen > fnlen) {
+ if (fn != NULL)
+ free(fn);
+ fnlen = e->fnlen;
+ if ((fn = malloc(fnlen + 1)) == NULL)
+ err(1, "malloc function name");
+ }
+
+ deref_kptr(e->fmt, fmt, fmtlen, "printf format");
+ fmt[fmtlen] = '\0';
+
+ deref_kptr(e->fn, fn, fnlen, "function name");
+ fn[fnlen] = '\0';
+
+ (void)printf("%06ld.%06ld ", (long int)e->tv.tv_sec,
+ (long int)e->tv.tv_usec);
+ (void)printf("%s#%ld@%d: ", fn, e->call, e->cpunum);
+ (void)printf(fmt, e->v[0], e->v[1], e->v[2], e->v[3]);
+ (void)putchar('\n');
+ }
+ i = (i + 1) % histp->n;
+ } while (i != histp->f);
+
+ free(histents);
+ if (fmt != NULL)
+ free(fmt);
+ if (fn != NULL)
+ free(fn);
+}
+
+void
+hist_traverse_sysctl(int todo, const char *histname)
+{
int error;
int mib[4];
unsigned int i;
@@ -2010,14 +2136,14 @@
miblen = __arraycount(mib);
error = sysctlnametomib("kern.hist", mib, &miblen);
if (error == ENOENT) {
- warnx("kernel history is not compiled into the kernel.");
- return;
- }
+ warnx("kernel history is not compiled into the kernel.");
+ return;
+ }
if (error != 0) {
err(1, "nametomib failed");
return;
}
-
+
/* get the list of nodenames below kern.hist */
mib[2] = CTL_QUERY;
memset(&query, 0, sizeof(query));
@@ -2029,56 +2155,56 @@
return;
}
if (len == 0) {
- warnx("No active kernel history logs.");
- return;
- }
-
+ warnx("No active kernel history logs.");
+ return;
+ }
+
len = len / sizeof(histnode[0]); /* get # of entries returned */
- if (todo & HISTLIST)
- (void)printf("Active kernel histories:");
-
+ if (todo & HISTLIST)
+ (void)printf("Active kernel histories:");
+
for (i = 0; i < len; i++) {
- if (todo & HISTLIST)
+ if (todo & HISTLIST)
(void)printf(" %s", histnode[i].sysctl_name);
- else {
- /*
- * If we're dumping all histories, do it, else
- * check to see if this is the one we want.
- */
+ else {
+ /*
+ * If we're dumping all histories, do it, else
+ * check to see if this is the one we want.
+ */
if (histname == NULL ||
strcmp(histname, histnode[i].sysctl_name) == 0) {
- if (histname == NULL)
- (void)printf(
+ if (histname == NULL)
+ (void)printf(
"\nkernel history `%s':\n",
histnode[i].sysctl_name);
mib[2] = histnode[i].sysctl_num;
mib[3] = CTL_EOL;
- hist_dodump(mib, 4);
- }
- }
- }
-
- if (todo & HISTLIST)
- (void)putchar('\n');
-}
-
-/*
- * Actually dump the history buffer at the specified KVA.
- */
-void
-hist_dodump(int mib[], unsigned int miblen)
-{
+ hist_dodump_sysctl(mib, 4);
+ }
+ }
+ }
+
+ if (todo & HISTLIST)
+ (void)putchar('\n');
+ }
+
+ /*
+ * Actually dump the history buffer at the specified KVA.
+ */
+ void
+hist_dodump_sysctl(int mib[], unsigned int miblen)
+ {
struct sysctl_history *hist;
struct sysctl_history_event *e;
- size_t histsize;
+ size_t histsize;
char *strp;
- unsigned i;
+ unsigned i;
char *fmt = NULL, *fn = NULL;
-
+
hist = NULL;
histsize = 0;
- do {
+ do {
errno = 0;
if (sysctl(mib, miblen, hist, &histsize, NULL, 0) == 0)
break;
@@ -2089,13 +2215,13 @@
} while (errno == ENOMEM);
if (errno != 0)
err(1, "sysctl failed");
-
+
strp = (char *)(&hist->sh_events[hist->sh_listentry.shle_numentries]);
-
+
(void)printf("%"PRIu32" entries, next is %"PRIu32"\n",
hist->sh_listentry.shle_numentries,
hist->sh_listentry.shle_nextfree);
-
+
i = hist->sh_listentry.shle_nextfree;
do {
@@ -2110,13 +2236,13 @@
e->she_cpunum);
(void)printf(fmt, e->she_values[0], e->she_values[1],
e->she_values[2], e->she_values[3]);
Home |
Main Index |
Thread Index |
Old Index