From owner-freebsd-bugs@FreeBSD.ORG Sat Mar 17 07:00:16 2007 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id D200C16A404 for ; Sat, 17 Mar 2007 07:00:16 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [69.147.83.40]) by mx1.freebsd.org (Postfix) with ESMTP id B336213C469 for ; Sat, 17 Mar 2007 07:00:16 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id l2H70Gdu092180 for ; Sat, 17 Mar 2007 07:00:16 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id l2H70GqJ092179; Sat, 17 Mar 2007 07:00:16 GMT (envelope-from gnats) Resent-Date: Sat, 17 Mar 2007 07:00:16 GMT Resent-Message-Id: <200703170700.l2H70GqJ092179@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Bruce Becker Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 32D1416A403 for ; Sat, 17 Mar 2007 06:51:58 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [69.147.83.33]) by mx1.freebsd.org (Postfix) with ESMTP id 22D1913C465 for ; Sat, 17 Mar 2007 06:51:58 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.13.1/8.13.1) with ESMTP id l2H6pvrW053834 for ; Sat, 17 Mar 2007 06:51:58 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.13.1/8.13.1/Submit) id l2H6pvHA053831; Sat, 17 Mar 2007 06:51:57 GMT (envelope-from nobody) Message-Id: <200703170651.l2H6pvHA053831@www.freebsd.org> Date: Sat, 17 Mar 2007 06:51:57 GMT From: Bruce Becker To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.0 Cc: Subject: misc/110426: rpc.rstatd returns bad info X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 Mar 2007 07:00:16 -0000 >Number: 110426 >Category: misc >Synopsis: rpc.rstatd returns bad info >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat Mar 17 07:00:11 GMT 2007 >Closed-Date: >Last-Modified: >Originator: Bruce Becker >Release: 4.11 >Organization: G.T.S. >Environment: FreeBSD infra-gw 4.11-STABLE FreeBSD 4.11-STABLE #3: Wed Feb 7 16:21:26 EST 2007 root@infra-gw:/usr/obj/usr/src/sys/FW-YQ i386 >Description: 4.x & 3.x seem to have issues with opackets systcl mib (always returns 0) this fix uses the kmem interface as well as fixes some code botches >How-To-Repeat: view using SunOS/Solaris perfmeter or sysutils/xsysstats port >Fix: Patch included Patch attached with submission follows: --- rstat_proc.c~ Fri Apr 2 01:56:09 2004 +++ rstat_proc.c Sat Jan 28 22:24:19 2006 @@ -63,7 +63,7 @@ #include #include -#include +#include #undef FSHIFT /* Use protocol's shift and scale values */ #undef FSCALE @@ -79,6 +79,8 @@ { "_cp_time" }, #define X_CNT 1 { "_cnt" }, +#define X_IFNET 2 + { "_ifnet" }, { "" }, }; @@ -87,6 +89,8 @@ void setup __P((void)); int stats_service(); +int firstifnet, numintfs; + extern int from_inetd; int sincelastreq = 0; /* number of alarms since last request */ extern int closedown; @@ -140,6 +144,7 @@ if (! stat_is_init) stat_init(); sincelastreq = 0; + stats_all.s2.if_opackets = stats_all.s3.if_opackets; return(&stats_all.s2); } @@ -151,6 +156,7 @@ if (! stat_is_init) stat_init(); sincelastreq = 0; + stats_all.s1.if_opackets = stats_all.s3.if_opackets; return(&stats_all.s1); } @@ -187,10 +193,11 @@ void updatestat() { + long off; int i, hz; struct clockinfo clockrate; struct vmmeter cnt; - struct ifmibdata ifmd; + struct ifnet ifnet; double avrun[3]; struct timeval tm, btm; int mib[6]; @@ -229,13 +236,13 @@ exit(1); } for(i = 0; i < RSTAT_CPUSTATES ; i++) - stats_all.s1.cp_time[i] = bsd_cp_time[cp_time_xlat[i]]; + stats_all.s3.cp_time[i] = bsd_cp_time[cp_time_xlat[i]]; (void)getloadavg(avrun, sizeof(avrun) / sizeof(avrun[0])); - stats_all.s2.avenrun[0] = avrun[0] * FSCALE; - stats_all.s2.avenrun[1] = avrun[1] * FSCALE; - stats_all.s2.avenrun[2] = avrun[2] * FSCALE; + stats_all.s3.avenrun[0] = avrun[0] * FSCALE; + stats_all.s3.avenrun[1] = avrun[1] * FSCALE; + stats_all.s3.avenrun[2] = avrun[2] * FSCALE; mib[0] = CTL_KERN; mib[1] = KERN_BOOTTIME; @@ -245,13 +252,13 @@ exit(1); } - stats_all.s2.boottime.tv_sec = btm.tv_sec; - stats_all.s2.boottime.tv_usec = btm.tv_usec; + stats_all.s3.boottime.tv_sec = btm.tv_sec; + stats_all.s3.boottime.tv_usec = btm.tv_usec; #ifdef DEBUG - fprintf(stderr, "%d %d %d %d\n", stats_all.s1.cp_time[0], - stats_all.s1.cp_time[1], stats_all.s1.cp_time[2], stats_all.s1.cp_time[3]); + fprintf(stderr, "%d %d %d %d\n", stats_all.s3.cp_time[0], + stats_all.s3.cp_time[1], stats_all.s3.cp_time[2], stats_all.s3.cp_time[3]); #endif /* XXX - should use sysctl */ @@ -259,54 +266,40 @@ syslog(LOG_ERR, "rstat: can't read cnt from kmem"); exit(1); } - stats_all.s1.v_pgpgin = cnt.v_vnodepgsin; - stats_all.s1.v_pgpgout = cnt.v_vnodepgsout; - stats_all.s1.v_pswpin = cnt.v_swappgsin; - stats_all.s1.v_pswpout = cnt.v_swappgsout; - stats_all.s1.v_intr = cnt.v_intr; + stats_all.s3.v_pgpgin = cnt.v_vnodepgsin; + stats_all.s3.v_pgpgout = cnt.v_vnodepgsout; + stats_all.s3.v_pswpin = cnt.v_swappgsin; + stats_all.s3.v_pswpout = cnt.v_swappgsout; + stats_all.s3.v_intr = cnt.v_intr; gettimeofday(&tm, (struct timezone *) 0); - stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) + + stats_all.s3.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.s3.v_swtch = cnt.v_swtch; /* update disk transfers */ - updatexfers(RSTAT_DK_NDRIVE, stats_all.s1.dk_xfer); + updatexfers(RSTAT_DK_NDRIVE, stats_all.s3.dk_xfer); - mib[0] = CTL_NET; - mib[1] = PF_LINK; - mib[2] = NETLINK_GENERIC; - mib[3] = IFMIB_SYSTEM; - mib[4] = IFMIB_IFCOUNT; - len = sizeof ifcount; - if (sysctl(mib, 5, &ifcount, &len, 0, 0) < 0) { - syslog(LOG_ERR, "sysctl(net.link.generic.system.ifcount): %m"); - exit(1); - } - - stats_all.s1.if_ipackets = 0; - stats_all.s1.if_opackets = 0; - stats_all.s1.if_ierrors = 0; - stats_all.s1.if_oerrors = 0; - stats_all.s1.if_collisions = 0; - for (i = 1; i <= ifcount; i++) { - len = sizeof ifmd; - mib[3] = IFMIB_IFDATA; - mib[4] = i; - mib[5] = IFDATA_GENERAL; - if (sysctl(mib, 6, &ifmd, &len, 0, 0) < 0) { - syslog(LOG_ERR, "sysctl(net.link.ifdata.%d.general)" - ": %m", i); - exit(1); + stats_all.s3.if_ipackets = 0; + stats_all.s3.if_opackets = 0; + stats_all.s3.if_ierrors = 0; + stats_all.s3.if_oerrors = 0; + stats_all.s3.if_collisions = 0; + for (off = firstifnet, i = 0; off && i < numintfs; i++) { + if (kvm_read(kd, off, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) { + syslog(LOG_ERR, "can't read ifnet from kmem"); + exit(1); + } + stats_all.s3.if_ipackets += ifnet.if_data.ifi_ipackets; + stats_all.s3.if_opackets += ifnet.if_data.ifi_opackets; + stats_all.s3.if_ierrors += ifnet.if_data.ifi_ierrors; + stats_all.s3.if_oerrors += ifnet.if_data.ifi_oerrors; + stats_all.s3.if_collisions += ifnet.if_data.ifi_collisions; + off = (long)ifnet.if_list.tqe_next; } - stats_all.s1.if_ipackets += ifmd.ifmd_data.ifi_ipackets; - stats_all.s1.if_opackets += ifmd.ifmd_data.ifi_opackets; - stats_all.s1.if_ierrors += ifmd.ifmd_data.ifi_ierrors; - stats_all.s1.if_oerrors += ifmd.ifmd_data.ifi_oerrors; - stats_all.s1.if_collisions += ifmd.ifmd_data.ifi_collisions; - } - gettimeofday((struct timeval *)&stats_all.s3.curtime, - (struct timezone *) 0); + gettimeofday(&tm, (struct timezone *) 0); + stats_all.s3.curtime.tv_sec = tm.tv_sec; + stats_all.s3.curtime.tv_usec = tm.tv_usec; alarm(1); } @@ -314,18 +307,46 @@ setup() { char errbuf[_POSIX2_LINE_MAX]; - int en; - - if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) { - syslog(LOG_ERR, "rpc.rstatd, %s", errbuf); - exit(1); + struct ifnet ifnet; + long off; + static int is_kd_setup = 0; + + /* setup() is called after each dormant->active + * transition. Since we never close the kvm files + * (there's no reason), make sure we don't open them + * each time, as that can lead to exhaustion of all open + * files! */ + if (!is_kd_setup) { + kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); + if (kd == NULL) { + syslog(LOG_ERR, "%s", errbuf); + exit (1); + } + is_kd_setup = 1; } if ((en = kvm_nlist(kd, nl)) != 0) { syslog(LOG_ERR, "rstatd: Can't get namelist. %d", en); exit (1); } + + if (kvm_read(kd, (long)nl[X_IFNET].n_value, &firstifnet, + sizeof(int)) != sizeof(int)) { + syslog(LOG_ERR, "can't read firstifnet from kmem"); + exit(1); + } + + numintfs = 0; + for (off = firstifnet; off;) { + if (kvm_read(kd, off, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) { + syslog(LOG_ERR, "can't read ifnet from kmem for ifcount"); + exit(1); + } + numintfs++; + off = (long)ifnet.if_list.tqe_next; + } + } /* @@ -449,7 +470,7 @@ switch (rqstp->rq_proc) { case NULLPROC: - (void)svc_sendreply(transp, xdr_void, (char *)NULL); + (void)svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL); goto leave; case RSTATPROC_STATS: @@ -497,15 +518,15 @@ goto leave; } bzero((char *)&argument, sizeof(argument)); - if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { + if (!svc_getargs(transp, (xdrproc_t)xdr_argument, (caddr_t)&argument)) { svcerr_decode(transp); goto leave; } result = (*local)(&argument, rqstp); - if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { + if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { svcerr_systemerr(transp); } - if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) + if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (caddr_t)&argument)) errx(1, "unable to free arguments"); leave: if (from_inetd) >Release-Note: >Audit-Trail: >Unformatted: