From nobody@FreeBSD.org  Sun Jun 21 18:39:28 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 539DA106566C
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 21 Jun 2009 18:39:28 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 41B668FC0C
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 21 Jun 2009 18:39:28 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n5LIdRtn020055
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 21 Jun 2009 18:39:27 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n5LIdR5W020047;
	Sun, 21 Jun 2009 18:39:27 GMT
	(envelope-from nobody)
Message-Id: <200906211839.n5LIdR5W020047@www.freebsd.org>
Date: Sun, 21 Jun 2009 18:39:27 GMT
From: Mikolaj Golub <to.my.trociny@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: 'vmstat -s -M core' is broken
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         135893
>Category:       bin
>Synopsis:       [patch] vmstat(8): 'vmstat -s -M core' is broken
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    jhb
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jun 21 18:40:00 UTC 2009
>Closed-Date:    Mon Dec 14 21:09:31 UTC 2009
>Last-Modified:  Mon Dec 14 21:09:31 UTC 2009
>Originator:     Mikolaj Golub
>Release:        
>Organization:
>Environment:
FreeBSD fbsd.zhuzha.ua1 8.0-CURRENT FreeBSD 8.0-CURRENT #0 r193993M: Thu Jun 11 17:01:46 EEST 2009     root@zhuzha.ua1:/home/golub/freebsd/build/obj/home/golub/freebsd/src/sys/GENERIC  i386

FreeBSD zhuzha.ua1 7.2-STABLE FreeBSD 7.2-STABLE #18: Wed Jun  3 14:28:49 EEST 2009     root@zhuzha.ua1:/usr/obj/usr/src/sys/DEBUG  i386
>Description:
'vmstat -s -M core' is broken, printing 0 for most of the counters.

This is because vmstat looks for statistics only in global `cnt' while the values of most of the counters are collected now in per-CPU variables.
>How-To-Repeat:
vmstat -s -M /dev/mem -N /boot/kernel/kernel

and compare with output of

vmstat -s
>Fix:
Attached patch fixes this.

Patch attached with submission follows:

--- usr.bin/vmstat/vmstat.c.orig	2009-02-22 04:11:24.000000000 +0200
+++ usr.bin/vmstat/vmstat.c	2009-06-21 20:51:20.000000000 +0300
@@ -58,6 +58,7 @@
 #include <sys/resource.h>
 #include <sys/sysctl.h>
 #include <sys/vmmeter.h>
+#include <sys/pcpu.h>
 
 #include <vm/vm_param.h>
 
@@ -418,10 +419,93 @@
 }
 
 static void
+fill_pcpu(struct pcpu ***p, int* maxcpup) {
+	struct pcpu **pp;
+	
+	int maxcpu, size, i;
+
+	*p = NULL;
+	
+	if (kd == NULL)
+		return;
+
+	maxcpu = kvm_getmaxcpu(kd);
+	if(maxcpu < 0)
+		errx(1, "kvm_getcptime: %s", kvm_geterr(kd));
+	if(maxcpu == 0) /* XXX: not sure this check makes sence */
+		return;
+
+	size = sizeof(struct pcpu *) * maxcpu;
+	pp = (struct pcpu **)calloc(1, size);
+	if(pp == NULL)
+		err(1, "malloc %zd bytes", size);
+
+	for(i = 0; i < maxcpu; i++) {
+		pp[i] = kvm_getpcpu(kd, i);
+		if(pp[i] == (struct pcpu *)-1)
+			errx(1, "kvm_getpcpu: %s", kvm_geterr(kd));
+	}
+
+	*maxcpup = maxcpu;
+	*p = pp;
+	return;
+}
+
+static void
+free_pcpu(struct pcpu **p, int maxcpu) {
+	int i;
+	for(i = 0; i < maxcpu; i++)
+		free(p[i]);
+	free(p);
+	p = NULL;
+}
+
+static void
 fill_vmmeter(struct vmmeter *vmmp)
 {
 	if (kd != NULL) {
+		struct pcpu **ppcpup;
+		int maxcpu, i;
+		
 		kread(X_SUM, vmmp, sizeof(*vmmp));
+		
+		fill_pcpu(&ppcpup, &maxcpu);
+		for(i=0; i < maxcpu; i++) {
+			if(ppcpup[i] == NULL)
+				continue;
+#define ADD_FROM_PCPU(i, name) \
+			vmmp->name += ppcpup[i]->pc_cnt.name
+			ADD_FROM_PCPU(i, v_swtch);
+			ADD_FROM_PCPU(i, v_trap);
+			ADD_FROM_PCPU(i, v_syscall);
+			ADD_FROM_PCPU(i, v_intr);
+			ADD_FROM_PCPU(i, v_soft);
+			ADD_FROM_PCPU(i, v_vm_faults);
+			ADD_FROM_PCPU(i, v_cow_faults);
+			ADD_FROM_PCPU(i, v_cow_optim);
+			ADD_FROM_PCPU(i, v_zfod);
+			ADD_FROM_PCPU(i, v_ozfod);
+			ADD_FROM_PCPU(i, v_swapin);
+			ADD_FROM_PCPU(i, v_swapout);
+			ADD_FROM_PCPU(i, v_swappgsin);
+			ADD_FROM_PCPU(i, v_swappgsout);
+			ADD_FROM_PCPU(i, v_vnodein);
+			ADD_FROM_PCPU(i, v_vnodeout);
+			ADD_FROM_PCPU(i, v_vnodepgsin);
+			ADD_FROM_PCPU(i, v_vnodepgsout);
+			ADD_FROM_PCPU(i, v_intrans);
+			ADD_FROM_PCPU(i, v_tfree);
+			ADD_FROM_PCPU(i, v_forks);
+			ADD_FROM_PCPU(i, v_vforks);
+			ADD_FROM_PCPU(i, v_rforks);
+			ADD_FROM_PCPU(i, v_kthreads);
+			ADD_FROM_PCPU(i, v_forkpages);
+			ADD_FROM_PCPU(i, v_vforkpages);
+			ADD_FROM_PCPU(i, v_rforkpages);
+			ADD_FROM_PCPU(i, v_kthreadpages);
+#undef ADD_FROM_PCPU
+		}
+		free_pcpu(ppcpup, maxcpu);
 	} else {
 		size_t size = sizeof(unsigned int);
 #define GET_VM_STATS(cat, name) \


>Release-Note:
>Audit-Trail:

From: John Baldwin <jhb@FreeBSD.org>
To: bug-followup@freebsd.org,
 to.my.trociny@gmail.com
Cc:  
Subject: Re: bin/135893: [patch] vmstat(8): 'vmstat -s -M core' is broken
Date: Thu, 29 Oct 2009 13:20:46 -0400

 This looks good in general.  Some suggestions:
 
 In fill_pcpu():
 - Use 'kvm_getmaxcpu' instead of 'kvm_getcptime' in error message.
 - I think it's ok to just drop the maxcpu == 0 check.
 - I would just use 'calloc(maxcpu, sizeof(struct pcpu *))' and
   have the error just say that calloc() failed w/o including the
   size.
 - C doesn't require a cast for void * pointers, so you can remove
   the cast from calloc().
 - Always use a space after 'if' and let the first { of a function
   start on a new line.
 - I would probably use 'pcpu' instead of 'ppcpup' as the variable
   name.
 
 These are fairly minor nits though.  I can probably fix these things and test 
 it today.
 
 -- 
 John Baldwin

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/135893: commit references a PR
Date: Thu, 29 Oct 2009 17:34:13 +0000 (UTC)

 Author: jhb
 Date: Thu Oct 29 17:34:02 2009
 New Revision: 198620
 URL: http://svn.freebsd.org/changeset/base/198620
 
 Log:
   When fetching sum stats (vmstat -s) from a crash dump, fetch per-CPU counts
   and sum them to form the total counts.
   
   PR:		bin/135893
   Submitted by:	Mikolaj Golub  to my trociny of gmail
   MFC after:	1 week
 
 Modified:
   head/usr.bin/vmstat/vmstat.c
 
 Modified: head/usr.bin/vmstat/vmstat.c
 ==============================================================================
 --- head/usr.bin/vmstat/vmstat.c	Thu Oct 29 17:21:41 2009	(r198619)
 +++ head/usr.bin/vmstat/vmstat.c	Thu Oct 29 17:34:02 2009	(r198620)
 @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/resource.h>
  #include <sys/sysctl.h>
  #include <sys/vmmeter.h>
 +#include <sys/pcpu.h>
  
  #include <vm/vm_param.h>
  
 @@ -418,10 +419,90 @@ getuptime(void)
  }
  
  static void
 +fill_pcpu(struct pcpu ***pcpup, int* maxcpup)
 +{
 +	struct pcpu **pcpu;
 +	
 +	int maxcpu, size, i;
 +
 +	*pcpup = NULL;
 +	
 +	if (kd == NULL)
 +		return;
 +
 +	maxcpu = kvm_getmaxcpu(kd);
 +	if (maxcpu < 0)
 +		errx(1, "kvm_getmaxcpu: %s", kvm_geterr(kd));
 +
 +	pcpu = calloc(maxcpu, sizeof(struct pcpu *));
 +	if (pcpu == NULL)
 +		err(1, "calloc");
 +
 +	for (i = 0; i < maxcpu; i++) {
 +		pcpu[i] = kvm_getpcpu(kd, i);
 +		if (pcpu[i] == (struct pcpu *)-1)
 +			errx(1, "kvm_getpcpu: %s", kvm_geterr(kd));
 +	}
 +
 +	*maxcpup = maxcpu;
 +	*pcpup = pcpu;
 +}
 +
 +static void
 +free_pcpu(struct pcpu **pcpu, int maxcpu)
 +{
 +	int i;
 +
 +	for (i = 0; i < maxcpu; i++)
 +		free(pcpu[i]);
 +	free(pcpu);
 +}
 +
 +static void
  fill_vmmeter(struct vmmeter *vmmp)
  {
 +	struct pcpu **pcpu;
 +	int maxcpu, i;
 +
  	if (kd != NULL) {
  		kread(X_SUM, vmmp, sizeof(*vmmp));
 +		fill_pcpu(&pcpu, &maxcpu);
 +		for (i = 0; i < maxcpu; i++) {
 +			if (pcpu[i] == NULL)
 +				continue;
 +#define ADD_FROM_PCPU(i, name) \
 +			vmmp->name += pcpu[i]->pc_cnt.name
 +			ADD_FROM_PCPU(i, v_swtch);
 +			ADD_FROM_PCPU(i, v_trap);
 +			ADD_FROM_PCPU(i, v_syscall);
 +			ADD_FROM_PCPU(i, v_intr);
 +			ADD_FROM_PCPU(i, v_soft);
 +			ADD_FROM_PCPU(i, v_vm_faults);
 +			ADD_FROM_PCPU(i, v_cow_faults);
 +			ADD_FROM_PCPU(i, v_cow_optim);
 +			ADD_FROM_PCPU(i, v_zfod);
 +			ADD_FROM_PCPU(i, v_ozfod);
 +			ADD_FROM_PCPU(i, v_swapin);
 +			ADD_FROM_PCPU(i, v_swapout);
 +			ADD_FROM_PCPU(i, v_swappgsin);
 +			ADD_FROM_PCPU(i, v_swappgsout);
 +			ADD_FROM_PCPU(i, v_vnodein);
 +			ADD_FROM_PCPU(i, v_vnodeout);
 +			ADD_FROM_PCPU(i, v_vnodepgsin);
 +			ADD_FROM_PCPU(i, v_vnodepgsout);
 +			ADD_FROM_PCPU(i, v_intrans);
 +			ADD_FROM_PCPU(i, v_tfree);
 +			ADD_FROM_PCPU(i, v_forks);
 +			ADD_FROM_PCPU(i, v_vforks);
 +			ADD_FROM_PCPU(i, v_rforks);
 +			ADD_FROM_PCPU(i, v_kthreads);
 +			ADD_FROM_PCPU(i, v_forkpages);
 +			ADD_FROM_PCPU(i, v_vforkpages);
 +			ADD_FROM_PCPU(i, v_rforkpages);
 +			ADD_FROM_PCPU(i, v_kthreadpages);
 +#undef ADD_FROM_PCPU
 +		}
 +		free_pcpu(pcpu, maxcpu);
  	} else {
  		size_t size = sizeof(unsigned int);
  #define GET_VM_STATS(cat, name) \
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: jhb 
State-Changed-When: Thu Oct 29 17:52:29 UTC 2009 
State-Changed-Why:  
Fix committed to HEAD. 


Responsible-Changed-From-To: freebsd-bugs->jhb 
Responsible-Changed-By: jhb 
Responsible-Changed-When: Thu Oct 29 17:52:29 UTC 2009 
Responsible-Changed-Why:  
Fix committed to HEAD. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=135893 
State-Changed-From-To: patched->Closed 
State-Changed-By: jhb 
State-Changed-When: Mon Dec 7 13:17:53 UTC 2009 
State-Changed-Why:  
Merged to 7. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=135893 
State-Changed-From-To: Closed->closed 
State-Changed-By: pav 
State-Changed-When: Mon Dec 14 21:09:14 UTC 2009 
State-Changed-Why:  
fix state 

http://www.freebsd.org/cgi/query-pr.cgi?pr=135893 
>Unformatted:
