Subject: bin/3200: rpc.rstatd does not report disk transfer statistics
To: None <gnats-bugs@gnats.netbsd.org>
From: None <jarle@runit.sintef.no>
List: netbsd-bugs
Date: 02/08/1997 19:46:09
>Number:         3200
>Category:       bin
>Synopsis:       rpc.rstatd does not report disk transfer statistics
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Feb  8 11:05:01 1997
>Last-Modified:
>Originator:     Jarle Greipsland
>Organization:
SINTEF/Runit
	
>Release:        1997-02-06
>Environment:
	
System: NetBSD natteravn.runit.sintef.no 1.2B NetBSD 1.2B (NATTERAVN) #8: Tue Feb 4 23:36:01 MET 1997 jarle@natteravn.runit.sintef.no:/usr/src/sys/arch/i386/compile/NATTERAVN i386


>Description:

rpc.rstatd does not fill in any disk transfer counters in the dk_xfer
array in the return struct.  Comments in the source indicates that this is
because the layout of the disk transfer statistics doesn't match the old
one anymore.  However, since several other programs in the source tree now
report on disk transfers (vmstat, systat), rpc.rstatd should probably also
be pulled back in line.
	
>How-To-Repeat:

Use a monitoring program like `istat' (from really old versions of
Interviews) or something else that will display disk activity retrieved by
the way of rstatd.  NetBSD systems never do any disk I/O, or so it
seems....

	
>Fix:
	

Apply diff.  I confess, I took the easy way out.  Since vmstat already had
the machinery in place to retrieve the data we need, the modified
rpc.rstatd just import the file dkstats.c from vmstat's source directory
(which is very much the way systat does its things).  Since dkreadstats()
does a bit more than what rstatd requires I guess it can be argued that
this is not the correct approach.  It seems to work though.

Another approach, and possibly a more correct one, might be to import just
the required code fragments from dkreadstats() and friends.
					-jarle

diff -rc rpc.rstatd/Makefile rpc.rstatd.mine/Makefile
*** rpc.rstatd/Makefile	Sat Feb  8 01:28:21 1997
--- rpc.rstatd.mine/Makefile	Sat Feb  8 01:05:14 1997
***************
*** 1,7 ****
  #	$NetBSD: Makefile,v 1.9 1996/08/30 20:17:40 thorpej Exp $
  
  PROG =	rpc.rstatd
! SRCS =	rstatd.c rstat_proc.c
  MAN =	rpc.rstatd.8
  MLINKS=	rpc.rstatd.8 rstatd.8
  
--- 1,10 ----
  #	$NetBSD: Makefile,v 1.9 1996/08/30 20:17:40 thorpej Exp $
  
  PROG =	rpc.rstatd
! .PATH: ${.CURDIR}/../../usr.bin/vmstat
! 
! CFLAGS+=-I${.CURDIR}/../../usr.bin/vmstat
! SRCS =	dkstats.c rstatd.c rstat_proc.c
  MAN =	rpc.rstatd.8
  MLINKS=	rpc.rstatd.8 rstatd.8
  
diff -rc rpc.rstatd/rstat_proc.c rpc.rstatd.mine/rstat_proc.c
*** rpc.rstatd/rstat_proc.c	Sat Feb  8 01:28:51 1997
--- rpc.rstatd.mine/rstat_proc.c	Sat Feb  8 02:13:00 1997
***************
*** 56,61 ****
--- 56,62 ----
  #ifdef BSD
  #include <sys/vmmeter.h>
  #include <sys/dkstat.h>
+ #include "dkstats.h"
  #else
  #include <sys/dk.h>
  #endif
***************
*** 77,110 ****
  int	cp_xlat[CPUSTATES] = { CP_USER, CP_NICE, CP_SYS, CP_IDLE };
  #endif
  
- #ifdef __NetBSD__
- /*
-  * NetBSD does not (currently) support the rpc.rstatd functionality
-  * formerly provided by grabbing dk_xfer from kmem, since NetBSD's
-  * new disk attachment code makes the data harder to look up and the
-  * data is not usually used.  If this becomes a problem, lookup via
-  * the new disk structures should be implemented.
-  */
- #define	NO_DK_XFER
- #endif
- 
  struct nlist nl[] = {
! #define	X_CPTIME	0
! 	{ "_cp_time" },
! #define	X_CNT		1
  	{ "_cnt" },
! #define	X_IFNET		2
  	{ "_ifnet" },
! #define	X_BOOTTIME	3
  	{ "_boottime" },
- #define X_HZ		4
- 	{ "_hz" },
- #ifndef NO_DK_XFER
- #define	X_DKXFER	5
- 	{ "_dk_xfer" },
- #endif
  	{ NULL },
  };
  struct ifnet_head ifnetq;	/* chain of ethernet interfaces */
  int numintfs;
  int stats_service();
--- 78,98 ----
  int	cp_xlat[CPUSTATES] = { CP_USER, CP_NICE, CP_SYS, CP_IDLE };
  #endif
  
  struct nlist nl[] = {
! #define	X_CNT		0
  	{ "_cnt" },
! #define	X_IFNET		1
  	{ "_ifnet" },
! #define	X_BOOTTIME	2
  	{ "_boottime" },
  	{ NULL },
  };
+ 
+ extern int dk_ndrive;		/* From dkstats.c */
+ extern struct _disk cur, last;
+ int hz;
+ char *memf = NULL, *nlistf = NULL;
+ 
  struct ifnet_head ifnetq;	/* chain of ethernet interfaces */
  int numintfs;
  int stats_service();
***************
*** 204,210 ****
  updatestat()
  {
  	long off;
! 	int i, hz;
  	struct vmmeter cnt;
  	struct ifnet ifnet;
  	double avrun[3];
--- 192,198 ----
  updatestat()
  {
  	long off;
! 	int i;
  	struct vmmeter cnt;
  	struct ifnet ifnet;
  	double avrun[3];
***************
*** 229,248 ****
  	}
  	sincelastreq++;
  
! 	if (kvm_read(kfd, (long)nl[X_HZ].n_value, (char *)&hz, sizeof hz) !=
! 	    sizeof hz) {
! 		syslog(LOG_ERR, "can't read hz from kmem");
! 		exit(1);
! 	}
  #ifdef BSD
-  	if (kvm_read(kfd, (long)nl[X_CPTIME].n_value, (char *)cp_time,
- 		     sizeof (cp_time))
- 	    != sizeof (cp_time)) {
- 		syslog(LOG_ERR, "can't read cp_time from kmem");
- 		exit(1);
- 	}
  	for (i = 0; i < CPUSTATES; i++)
! 		stats_all.s1.cp_time[i] = cp_time[cp_xlat[i]];
  #else
   	if (kvm_read(kfd, (long)nl[X_CPTIME].n_value,
  		     (char *)stats_all.s1.cp_time,
--- 217,234 ----
  	}
  	sincelastreq++;
  
! 	/* 
! 	 * dkreadstats reads in the "disk_count" as well as the "disklist"
! 	 * statistics.  It also retrieves "hz" and the "cp_time" array.
! 	 */
! 	dkreadstats();
! 	memset(stats_all.s1.dk_xfer, 0, sizeof(stats_all.s1.dk_xfer));
! 	for (i = 0; i < dk_ndrive && i < DK_NDRIVE; i++)
! 		stats_all.s1.dk_xfer[i] = cur.dk_xfer[i];
! 
  #ifdef BSD
  	for (i = 0; i < CPUSTATES; i++)
! 		stats_all.s1.cp_time[i] = cur.cp_time[cp_xlat[i]];
  #else
   	if (kvm_read(kfd, (long)nl[X_CPTIME].n_value,
  		     (char *)stats_all.s1.cp_time,
***************
*** 287,305 ****
  	stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
  	    hz*(tm.tv_usec - btm.tv_usec)/1000000;
  	stats_all.s2.v_swtch = cnt.v_swtch;
! 
! #ifdef NO_DK_XFER
! 	memset(stats_all.s1.dk_xfer, 0, sizeof (stats_all.s1.dk_xfer));
! #else
!  	if (kvm_read(kfd, (long)nl[X_DKXFER].n_value,
! 		     (char *)stats_all.s1.dk_xfer,
! 		     sizeof (stats_all.s1.dk_xfer))
! 	    != sizeof (stats_all.s1.dk_xfer)) {
! 		syslog(LOG_ERR, "can't read dk_xfer from kmem");
! 		exit(1);
! 	}
! #endif
! 
  	stats_all.s1.if_ipackets = 0;
  	stats_all.s1.if_opackets = 0;
  	stats_all.s1.if_ierrors = 0;
--- 273,279 ----
  	stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
  	    hz*(tm.tv_usec - btm.tv_usec)/1000000;
  	stats_all.s2.v_swtch = cnt.v_swtch;
! 	
  	stats_all.s1.if_ipackets = 0;
  	stats_all.s1.if_opackets = 0;
  	stats_all.s1.if_ierrors = 0;
***************
*** 356,361 ****
--- 330,336 ----
  		numintfs++;
  		off = (long)ifnet.if_list.tqe_next;
  	}
+ 	dkinit(0);
  }
  
  /*
***************
*** 364,390 ****
  int
  havedisk()
  {
! #ifdef NO_DK_XFER
! 	return (0);
! #else
! 	int i, cnt;
! 	long  xfer[DK_NDRIVE];
! 
! 	if (kvm_nlist(kfd, nl) != 0) {
! 		syslog(LOG_ERR, "can't get namelist");
! 		exit (1);
!         }
! 
! 	if (kvm_read(kfd, (long)nl[X_DKXFER].n_value,
! 		     (char *)xfer, sizeof xfer) != sizeof xfer) {
! 		syslog(LOG_ERR, "can't read dk_xfer from kmem");
! 		exit(1);
! 	}
! 	cnt = 0;
! 	for (i=0; i < DK_NDRIVE; i++)
! 		cnt += xfer[i];
! 	return (cnt != 0);
! #endif
  }
  
  void
--- 339,345 ----
  int
  havedisk()
  {
! 	return dk_ndrive != 0;
  }
  
  void
>Audit-Trail:
>Unformatted: