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/c1498e188080
branches:  trunk
changeset: 820155:c1498e188080
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 36dc52d4925b -r c1498e188080 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