Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/pstat The number of active vnodes may grow in betwe...



details:   https://anonhg.NetBSD.org/src/rev/287d42bbb9f5
branches:  trunk
changeset: 782633:287d42bbb9f5
user:      apb <apb%NetBSD.org@localhost>
date:      Sat Nov 10 11:01:52 2012 +0000

description:
The number of active vnodes may grow in between the sysctl call
that figures out the size, and the sysctl call that fetches the data.

Previously, any growth at all would have resulted in this error message:

        pstat: sysctl: KERN_VNODE: Cannot allocate memory

Now allow for growth of 100 vnodes, or 5%, or both.  Growth in
excess of 2% or 6000 vnodes has been observed in practice.  Also
ignore ENOMEM from the second sysctl call, in case the growth was
even more than we anticipated.

diffstat:

 usr.sbin/pstat/pstat.c |  32 ++++++++++++++++++++++++++++----
 1 files changed, 28 insertions(+), 4 deletions(-)

diffs (72 lines):

diff -r 2a92a9cd9394 -r 287d42bbb9f5 usr.sbin/pstat/pstat.c
--- a/usr.sbin/pstat/pstat.c    Sat Nov 10 01:47:25 2012 +0000
+++ b/usr.sbin/pstat/pstat.c    Sat Nov 10 11:01:52 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pstat.c,v 1.119 2012/06/04 20:13:47 riastradh Exp $    */
+/*     $NetBSD: pstat.c,v 1.120 2012/11/10 11:01:52 apb Exp $  */
 
 /*-
  * Copyright (c) 1980, 1991, 1993, 1994
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)pstat.c    8.16 (Berkeley) 5/9/95";
 #else
-__RCSID("$NetBSD: pstat.c,v 1.119 2012/06/04 20:13:47 riastradh Exp $");
+__RCSID("$NetBSD: pstat.c,v 1.120 2012/11/10 11:01:52 apb Exp $");
 #endif
 #endif /* not lint */
 
@@ -73,6 +73,7 @@
 #include <sys/sysctl.h>
 
 #include <err.h>
+#include <errno.h>
 #include <kvm.h>
 #include <limits.h>
 #include <nlist.h>
@@ -681,7 +682,8 @@
 loadvnodes(int *avnodes)
 {
        int mib[2];
-       size_t copysize;
+       int status;
+       size_t copysize, oldsize;
        char *vnodebase;
 
        if (totalflag) {
@@ -696,12 +698,34 @@
        }
        mib[0] = CTL_KERN;
        mib[1] = KERN_VNODE;
+       /*
+        * First sysctl call gets the necessary buffer size; second
+        * sysctl call gets the data.  We allow for some growth in the
+        * data size between the two sysctl calls (increases of a few
+        * thousand vnodes in between the two calls have been observed).
+        * We ignore ENOMEM from the second sysctl call, which can
+        * happen if the kernel's data grew by even more than we allowed
+        * for.
+        */
        if (sysctl(mib, 2, NULL, &copysize, NULL, 0) == -1)
                err(1, "sysctl: KERN_VNODE");
+       oldsize = copysize;
+       copysize += 100 * sizeof(struct vnode) + copysize / 20;
        if ((vnodebase = malloc(copysize)) == NULL)
                err(1, "malloc");
-       if (sysctl(mib, 2, vnodebase, &copysize, NULL, 0) == -1)
+       status = sysctl(mib, 2, vnodebase, &copysize, NULL, 0);
+       if (status == -1 && errno != ENOMEM)
                err(1, "sysctl: KERN_VNODE");
+#if 0 /* for debugging the amount of growth allowed for */
+       if (copysize != oldsize) {
+               warnx("count changed from %ld to %ld (%+ld)%s",
+                   (long)(oldsize / sizeof(struct vnode)),
+                   (long)(copysize / sizeof(struct vnode)),
+                   (long)(copysize / sizeof(struct vnode)) -
+                       (long)(oldsize / sizeof(struct vnode)),
+                   (status == 0 ? "" : ", and errno = ENOMEM"));
+       }
+#endif
        if (copysize % (VPTRSZ + VNODESZ))
                errx(1, "vnode size mismatch");
        *avnodes = copysize / (VPTRSZ + VNODESZ);



Home | Main Index | Thread Index | Old Index