Bug 19809

Summary: Make mbstat.m_mtypes[] u_long instead of u_short
Product: Base System Reporter: iedowse <iedowse>
Component: kernAssignee: dwmalone
Status: Closed FIXED    
Severity: Affects Only Me CC: iedowse
Priority: Normal    
Version: 4.0-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description iedowse 2000-07-09 21:40:01 UTC
	The mbstat.m_mtypes[] array, which is used to store mbuf type
	statistics, is declared with type u_short. For most people
	this is large enough, but large systems with more than 64k
	mbufs configured are becoming quite common now.

	On these systems, overflows can occur, causing meaningless
	values to appear int the output of "netstat -m".

	A related problem, which looks like it has always existed in
	FreeBSD, is that the m_mtypes[MT_FREE] counter is not incremented
	when new mbufs are allocated, so it does not reflect the number
	of free mbufs.

Fix: Apply the following patch. This fixes both of the above
	issues, and removes some assumptions within netstat(1) about
	the size of the m_mtypes[] array.

	The patch also reduces the size of the m_mtypes[] array from
	256 to 32. Currently there are only 16 mbuf types defined, and
	the definitions of 9 of these are #if 0'd out, so we are unlikely
	to reach 32 types anytime soon. This reduces the kernel bss size
	by a few hundred bytes.

How-To-Repeat: 
	Configure a system with more than 64k mbufs, and notice that
	the 'XX mbufs allocated to data' output from netstat wraps
	around at 64k.

	The m_mtypes[MT_FREE] bug can be observed by typing

		print mbstat.m_mtypes[0]

	from a kgdb session; the number printed will generally be around
	65500 on a quiet system with only a few mbufs allocated.
Comment 1 Garrett A. Wollman 2000-07-10 17:56:10 UTC
<<On Sun, 9 Jul 2000 21:31:26 +0100 (BST), iedowse@maths.tcd.ie said:

> 	Apply the following patch. This fixes both of the above
> 	issues, and removes some assumptions within netstat(1) about
> 	the size of the m_mtypes[] array.

Looks good to me.  I'd rather have the counts exported as a separate
MIB entry, though, which would avoid any dependency by netstat on the
actual number of types supported in the kernel.

-GAWollman
Comment 2 Sheldon Hearn freebsd_committer freebsd_triage 2000-07-11 09:46:01 UTC
Responsible Changed
From-To: freebsd-bugs->dwmalone

Haha!  Assigned to a committer near you. :-)
Comment 3 iedowse 2000-07-11 22:12:51 UTC
Garrett suggested that the m_mtypes[] array should be be available
as a separate MIB. This allows userland utilities (currently just
netstat) to function correctly without recompilation if its length
changes.

The included patch moves the mbstat.m_mtypes[] array out of struct
mbstat, and makes it available via sysctl(3) as 'kern.ipc.mbtypes'.
It also changes netstat(1) to use this interface.

Since the size of mbtypes[] is now more freely modifiable, this
patch defines it with only as many entries as are currently necessary
(16).

[Note that right now, 'sysctl -a' only displays the first entry in
the mbtypes[] array. sysctl(8) currently supports arrays of type
(u_)int, but not (u_)long. I'll submit a patch for that separately.]

Ian


Index: sys/kern/uipc_mbuf.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sys/kern/uipc_mbuf.c,v
retrieving revision 1.52
diff -u -r1.52 uipc_mbuf.c
--- sys/kern/uipc_mbuf.c	2000/07/04 16:35:03	1.52
+++ sys/kern/uipc_mbuf.c	2000/07/11 20:38:21
@@ -58,6 +58,7 @@
 struct mbuf *mbutl;
 char	*mclrefcnt;
 struct mbstat mbstat;
+u_long	mbtypes[MT_NTYPES];
 struct mbuf *mmbfree;
 union mcluster *mclfree;
 int	max_linkhdr;
@@ -80,6 +81,8 @@
 SYSCTL_INT(_kern_ipc, OID_AUTO, mbuf_wait, CTLFLAG_RW,
 	   &mbuf_wait, 0, "");
 SYSCTL_STRUCT(_kern_ipc, KIPC_MBSTAT, mbstat, CTLFLAG_RW, &mbstat, mbstat, "");
+SYSCTL_OPAQUE(_kern_ipc, OID_AUTO, mbtypes, CTLFLAG_RD, mbtypes,
+	   sizeof(mbtypes), "LU", "");
 SYSCTL_INT(_kern_ipc, KIPC_NMBCLUSTERS, nmbclusters, CTLFLAG_RD, 
 	   &nmbclusters, 0, "Maximum number of mbuf clusters available");
 SYSCTL_INT(_kern_ipc, OID_AUTO, nmbufs, CTLFLAG_RD, &nmbufs, 0,
@@ -184,6 +187,7 @@
 		p += MSIZE;
 	}
 	mbstat.m_mbufs += nmb;
+	mbtypes[MT_FREE] += nmb;
 	return (1);
 }
 
Index: sys/sys/mbuf.h
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/sys/sys/mbuf.h,v
retrieving revision 1.51
diff -u -r1.51 mbuf.h
--- sys/sys/mbuf.h	2000/07/04 16:35:15	1.51
+++ sys/sys/mbuf.h	2000/07/11 17:54:03
@@ -180,6 +180,8 @@
 #define	MT_CONTROL	14	/* extra-data protocol message */
 #define	MT_OOBDATA	15	/* expedited data  */
 
+#define	MT_NTYPES	16	/* number of mbuf types for mbtypes[] */
+
 /*
  * mbuf statistics
  */
@@ -191,7 +193,6 @@
 	u_long	m_drops;	/* times failed to find space */
 	u_long	m_wait;		/* times waited for space */
 	u_long	m_drain;	/* times drained protocols for space */
-	u_short	m_mtypes[256];	/* type specific mbuf allocations */
 	u_long	m_mcfail;	/* times m_copym failed */
 	u_long	m_mpfail;	/* times m_pullup failed */
 	u_long	m_msize;	/* length of an mbuf */
@@ -284,9 +285,9 @@
 	_mm = mmbfree;							\
 	if (_mm != NULL) {						\
 		mmbfree = _mm->m_next;					\
-		mbstat.m_mtypes[MT_FREE]--;				\
+		mbtypes[MT_FREE]--;					\
 		_mm->m_type = _mtype;					\
-		mbstat.m_mtypes[_mtype]++;				\
+		mbtypes[_mtype]++;					\
 		_mm->m_next = NULL;					\
 		_mm->m_nextpkt = NULL;					\
 		_mm->m_data = _mm->m_dat;				\
@@ -314,9 +315,9 @@
 	_mm = mmbfree;							\
 	if (_mm != NULL) {						\
 		mmbfree = _mm->m_next;					\
-		mbstat.m_mtypes[MT_FREE]--;				\
+		mbtypes[MT_FREE]--;					\
 		_mm->m_type = _mtype;					\
-		mbstat.m_mtypes[_mtype]++;				\
+		mbtypes[_mtype]++;					\
 		_mm->m_next = NULL;					\
 		_mm->m_nextpkt = NULL;					\
 		_mm->m_data = _mm->m_pktdat;				\
@@ -419,12 +420,12 @@
 	struct mbuf *_mm = (m);						\
 									\
 	KASSERT(_mm->m_type != MT_FREE, ("freeing free mbuf"));		\
-	mbstat.m_mtypes[_mm->m_type]--;					\
+	mbtypes[_mm->m_type]--;						\
 	if (_mm->m_flags & M_EXT)					\
 		MEXTFREE1(m);						\
 	(n) = _mm->m_next;						\
 	_mm->m_type = MT_FREE;						\
-	mbstat.m_mtypes[MT_FREE]++;					\
+	mbtypes[MT_FREE]++;						\
 	_mm->m_next = mmbfree;						\
 	mmbfree = _mm;							\
 	MMBWAKEUP();							\
@@ -508,8 +509,8 @@
 	int _mt = (t);							\
 	int _ms = splimp();						\
 									\
-	mbstat.m_mtypes[_mm->m_type]--;					\
-	mbstat.m_mtypes[_mt]++;						\
+	mbtypes[_mm->m_type]--;						\
+	mbtypes[_mt]++;							\
 	splx(_ms);							\
 	_mm->m_type = (_mt);						\
 } while (0)
@@ -536,6 +537,7 @@
 extern	int		 max_hdr;	/* largest link+protocol header */
 extern	int		 max_datalen;	/* MHLEN - max_hdr */
 extern	struct mbstat	 mbstat;
+extern	u_long		 mbtypes[MT_NTYPES]; /* per-type mbuf allocations */
 extern	int		 mbuf_wait;	/* mbuf sleep time */
 extern	struct mbuf	*mbutl;		/* virtual address of mclusters */
 extern	char		*mclrefcnt;	/* cluster reference counts */
Index: usr.bin/netstat/mbuf.c
===================================================================
RCS file: /FreeBSD/FreeBSD-CVS/src/usr.bin/netstat/mbuf.c,v
retrieving revision 1.17
diff -u -r1.17 mbuf.c
--- usr.bin/netstat/mbuf.c	1999/12/28 06:38:37	1.17
+++ usr.bin/netstat/mbuf.c	2000/07/11 19:39:16
@@ -47,6 +47,7 @@
 
 #include <err.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include "netstat.h"
 
 #define	YES	1
@@ -54,10 +55,10 @@
 
 struct	mbstat mbstat;
 
-static struct mbtypes {
+static struct mbtypenames {
 	int	mt_type;
 	char	*mt_name;
-} mbtypes[] = {
+} mbtypenames[] = {
 	{ MT_DATA,	"data" },
 	{ MT_OOBDATA,	"oob data" },
 	{ MT_CONTROL,	"ancillary data" },
@@ -91,9 +92,6 @@
 	{ 0, 0 }
 };
 
-int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(short);
-bool seen[256];			/* "have we seen this type yet?" */
-
 /*
  * Print mbuf statistics.
  */
@@ -102,9 +100,14 @@
 {
 	register int totmem, totfree, totmbufs;
 	register int i;
-	register struct mbtypes *mp;
-	int name[3], nmbclusters, nmbufs;
-	size_t nmbclen, nmbuflen, mbstatlen;
+	struct mbtypenames *mp;
+	int name[3], nmbclusters, nmbufs, nmbtypes;
+	size_t nmbclen, nmbuflen, mbstatlen, mbtypeslen;
+	u_long *mbtypes;
+	bool *seen;	/* "have we seen this type yet?" */
+
+	mbtypes = NULL;
+	seen = NULL;
 
 	name[0] = CTL_KERN;
 	name[1] = KERN_IPC;
@@ -112,20 +115,40 @@
 	mbstatlen = sizeof mbstat;
 	if (sysctl(name, 3, &mbstat, &mbstatlen, 0, 0) < 0) {
 		warn("sysctl: retrieving mbstat");
-		return;
+		goto err;
+	}
+
+	if (sysctlbyname("kern.ipc.mbtypes", NULL, &mbtypeslen, NULL, 0) < 0) {
+		warn("sysctl: retrieving mbtypes length");
+		goto err;
+	}
+	if ((mbtypes = malloc(mbtypeslen)) == NULL) {
+		warn("malloc: %lu bytes for mbtypes", (u_long)mbtypeslen);
+		goto err;
 	}
+	if (sysctlbyname("kern.ipc.mbtypes", mbtypes, &mbtypeslen, NULL,
+	    0) < 0) {
+		warn("sysctl: retrieving mbtypes");
+		goto err;
+	}
 
+	nmbtypes = mbtypeslen / sizeof(*mbtypes);
+	if ((seen = calloc(nmbtypes, sizeof(*seen))) == NULL) {
+		warn("calloc");
+		goto err;
+	}
+		
 	name[2] = KIPC_NMBCLUSTERS;
 	nmbclen = sizeof(int);
 	if (sysctl(name, 3, &nmbclusters, &nmbclen, 0, 0) < 0) {
 		warn("sysctl: retrieving nmbclusters");
-		return;
+		goto err;
 	}
 
 	nmbuflen = sizeof(int);
 	if (sysctlbyname("kern.ipc.nmbufs", &nmbufs, &nmbuflen, 0, 0) < 0) {
 		warn("sysctl: retrieving nmbufs");
-		return;
+		goto err;
 	}
 
 #undef MSIZE
@@ -133,27 +156,22 @@
 #undef MCLBYTES
 #define	MCLBYTES	(mbstat.m_mclbytes)
 
-	if (nmbtypes != 256) {
-		warnx("unexpected change to mbstat; check source");
-		return;
-	}
-
 	totmbufs = 0;
-	for (mp = mbtypes; mp->mt_name; mp++)
-		totmbufs += mbstat.m_mtypes[mp->mt_type];
+	for (mp = mbtypenames; mp->mt_name; mp++)
+		totmbufs += mbtypes[mp->mt_type];
 	printf("%u/%lu/%u mbufs in use (current/peak/max):\n", totmbufs,
 	    mbstat.m_mbufs, nmbufs);
-	for (mp = mbtypes; mp->mt_name; mp++)
-		if (mbstat.m_mtypes[mp->mt_type]) {
+	for (mp = mbtypenames; mp->mt_name; mp++)
+		if (mbtypes[mp->mt_type]) {
 			seen[mp->mt_type] = YES;
-			printf("\t%u mbufs allocated to %s\n",
-			    mbstat.m_mtypes[mp->mt_type], mp->mt_name);
+			printf("\t%lu mbufs allocated to %s\n",
+			    mbtypes[mp->mt_type], mp->mt_name);
 		}
 	seen[MT_FREE] = YES;
 	for (i = 0; i < nmbtypes; i++)
-		if (!seen[i] && mbstat.m_mtypes[i]) {
-			printf("\t%u mbufs allocated to <mbuf type %d>\n",
-			    mbstat.m_mtypes[i], i);
+		if (!seen[i] && mbtypes[i]) {
+			printf("\t%lu mbufs allocated to <mbuf type %d>\n",
+			    mbtypes[i], i);
 		}
 	printf("%lu/%lu/%u mbuf clusters in use (current/peak/max)\n",
 		mbstat.m_clusters - mbstat.m_clfree, mbstat.m_clusters,
@@ -166,4 +184,10 @@
 	printf("%lu requests for memory denied\n", mbstat.m_drops);
 	printf("%lu requests for memory delayed\n", mbstat.m_wait);
 	printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
+
+err:
+	if (mbtypes != NULL)
+		free(mbtypes);
+	if (seen != NULL)
+		free(seen);
 }
Comment 4 bmilekic@dsuper.net 2000-07-11 23:46:21 UTC
  Somebody PLEASE commit this as soon as possible, and let me (or us) know.

   I need to roll some diffs covering this part of the tree as well, and
   the fact that this stuff is just sitting there is not helping
   consistency (it would reduce work if I merged them and then rolled the
   diffs after they are in the tree).

  Thanks in advance,
  --Bosko


On Tue, 11 Jul 2000, Ian Dowse wrote:

> 
> Garrett suggested that the m_mtypes[] array should be be available
> as a separate MIB. This allows userland utilities (currently just
> netstat) to function correctly without recompilation if its length
> changes.
> 
> The included patch moves the mbstat.m_mtypes[] array out of struct
> mbstat, and makes it available via sysctl(3) as 'kern.ipc.mbtypes'.
> It also changes netstat(1) to use this interface.
> 
> Since the size of mbtypes[] is now more freely modifiable, this
> patch defines it with only as many entries as are currently necessary
> (16).
> 
> [Note that right now, 'sysctl -a' only displays the first entry in
> the mbtypes[] array. sysctl(8) currently supports arrays of type
> (u_)int, but not (u_)long. I'll submit a patch for that separately.]
> 
> Ian
> 
> 
> Index: sys/kern/uipc_mbuf.c
> ===================================================================
> RCS file: /FreeBSD/FreeBSD-CVS/src/sys/kern/uipc_mbuf.c,v
> retrieving revision 1.52
> diff -u -r1.52 uipc_mbuf.c
> --- sys/kern/uipc_mbuf.c	2000/07/04 16:35:03	1.52
> +++ sys/kern/uipc_mbuf.c	2000/07/11 20:38:21
> @@ -58,6 +58,7 @@
>  struct mbuf *mbutl;
>  char	*mclrefcnt;
>  struct mbstat mbstat;
> +u_long	mbtypes[MT_NTYPES];
>  struct mbuf *mmbfree;
>  union mcluster *mclfree;
>  int	max_linkhdr;
> @@ -80,6 +81,8 @@
>  SYSCTL_INT(_kern_ipc, OID_AUTO, mbuf_wait, CTLFLAG_RW,
>  	   &mbuf_wait, 0, "");
>  SYSCTL_STRUCT(_kern_ipc, KIPC_MBSTAT, mbstat, CTLFLAG_RW, &mbstat, mbstat, "");
> +SYSCTL_OPAQUE(_kern_ipc, OID_AUTO, mbtypes, CTLFLAG_RD, mbtypes,
> +	   sizeof(mbtypes), "LU", "");
>  SYSCTL_INT(_kern_ipc, KIPC_NMBCLUSTERS, nmbclusters, CTLFLAG_RD, 
>  	   &nmbclusters, 0, "Maximum number of mbuf clusters available");
>  SYSCTL_INT(_kern_ipc, OID_AUTO, nmbufs, CTLFLAG_RD, &nmbufs, 0,
> @@ -184,6 +187,7 @@
>  		p += MSIZE;
>  	}
>  	mbstat.m_mbufs += nmb;
> +	mbtypes[MT_FREE] += nmb;
>  	return (1);
>  }
>  
> Index: sys/sys/mbuf.h
> ===================================================================
> RCS file: /FreeBSD/FreeBSD-CVS/src/sys/sys/mbuf.h,v
> retrieving revision 1.51
> diff -u -r1.51 mbuf.h
> --- sys/sys/mbuf.h	2000/07/04 16:35:15	1.51
> +++ sys/sys/mbuf.h	2000/07/11 17:54:03
> @@ -180,6 +180,8 @@
>  #define	MT_CONTROL	14	/* extra-data protocol message */
>  #define	MT_OOBDATA	15	/* expedited data  */
>  
> +#define	MT_NTYPES	16	/* number of mbuf types for mbtypes[] */
> +
>  /*
>   * mbuf statistics
>   */
> @@ -191,7 +193,6 @@
>  	u_long	m_drops;	/* times failed to find space */
>  	u_long	m_wait;		/* times waited for space */
>  	u_long	m_drain;	/* times drained protocols for space */
> -	u_short	m_mtypes[256];	/* type specific mbuf allocations */
>  	u_long	m_mcfail;	/* times m_copym failed */
>  	u_long	m_mpfail;	/* times m_pullup failed */
>  	u_long	m_msize;	/* length of an mbuf */
> @@ -284,9 +285,9 @@
>  	_mm = mmbfree;							\
>  	if (_mm != NULL) {						\
>  		mmbfree = _mm->m_next;					\
> -		mbstat.m_mtypes[MT_FREE]--;				\
> +		mbtypes[MT_FREE]--;					\
>  		_mm->m_type = _mtype;					\
> -		mbstat.m_mtypes[_mtype]++;				\
> +		mbtypes[_mtype]++;					\
>  		_mm->m_next = NULL;					\
>  		_mm->m_nextpkt = NULL;					\
>  		_mm->m_data = _mm->m_dat;				\
> @@ -314,9 +315,9 @@
>  	_mm = mmbfree;							\
>  	if (_mm != NULL) {						\
>  		mmbfree = _mm->m_next;					\
> -		mbstat.m_mtypes[MT_FREE]--;				\
> +		mbtypes[MT_FREE]--;					\
>  		_mm->m_type = _mtype;					\
> -		mbstat.m_mtypes[_mtype]++;				\
> +		mbtypes[_mtype]++;					\
>  		_mm->m_next = NULL;					\
>  		_mm->m_nextpkt = NULL;					\
>  		_mm->m_data = _mm->m_pktdat;				\
> @@ -419,12 +420,12 @@
>  	struct mbuf *_mm = (m);						\
>  									\
>  	KASSERT(_mm->m_type != MT_FREE, ("freeing free mbuf"));		\
> -	mbstat.m_mtypes[_mm->m_type]--;					\
> +	mbtypes[_mm->m_type]--;						\
>  	if (_mm->m_flags & M_EXT)					\
>  		MEXTFREE1(m);						\
>  	(n) = _mm->m_next;						\
>  	_mm->m_type = MT_FREE;						\
> -	mbstat.m_mtypes[MT_FREE]++;					\
> +	mbtypes[MT_FREE]++;						\
>  	_mm->m_next = mmbfree;						\
>  	mmbfree = _mm;							\
>  	MMBWAKEUP();							\
> @@ -508,8 +509,8 @@
>  	int _mt = (t);							\
>  	int _ms = splimp();						\
>  									\
> -	mbstat.m_mtypes[_mm->m_type]--;					\
> -	mbstat.m_mtypes[_mt]++;						\
> +	mbtypes[_mm->m_type]--;						\
> +	mbtypes[_mt]++;							\
>  	splx(_ms);							\
>  	_mm->m_type = (_mt);						\
>  } while (0)
> @@ -536,6 +537,7 @@
>  extern	int		 max_hdr;	/* largest link+protocol header */
>  extern	int		 max_datalen;	/* MHLEN - max_hdr */
>  extern	struct mbstat	 mbstat;
> +extern	u_long		 mbtypes[MT_NTYPES]; /* per-type mbuf allocations */
>  extern	int		 mbuf_wait;	/* mbuf sleep time */
>  extern	struct mbuf	*mbutl;		/* virtual address of mclusters */
>  extern	char		*mclrefcnt;	/* cluster reference counts */
> Index: usr.bin/netstat/mbuf.c
> ===================================================================
> RCS file: /FreeBSD/FreeBSD-CVS/src/usr.bin/netstat/mbuf.c,v
> retrieving revision 1.17
> diff -u -r1.17 mbuf.c
> --- usr.bin/netstat/mbuf.c	1999/12/28 06:38:37	1.17
> +++ usr.bin/netstat/mbuf.c	2000/07/11 19:39:16
> @@ -47,6 +47,7 @@
>  
>  #include <err.h>
>  #include <stdio.h>
> +#include <stdlib.h>
>  #include "netstat.h"
>  
>  #define	YES	1
> @@ -54,10 +55,10 @@
>  
>  struct	mbstat mbstat;
>  
> -static struct mbtypes {
> +static struct mbtypenames {
>  	int	mt_type;
>  	char	*mt_name;
> -} mbtypes[] = {
> +} mbtypenames[] = {
>  	{ MT_DATA,	"data" },
>  	{ MT_OOBDATA,	"oob data" },
>  	{ MT_CONTROL,	"ancillary data" },
> @@ -91,9 +92,6 @@
>  	{ 0, 0 }
>  };
>  
> -int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(short);
> -bool seen[256];			/* "have we seen this type yet?" */
> -
>  /*
>   * Print mbuf statistics.
>   */
> @@ -102,9 +100,14 @@
>  {
>  	register int totmem, totfree, totmbufs;
>  	register int i;
> -	register struct mbtypes *mp;
> -	int name[3], nmbclusters, nmbufs;
> -	size_t nmbclen, nmbuflen, mbstatlen;
> +	struct mbtypenames *mp;
> +	int name[3], nmbclusters, nmbufs, nmbtypes;
> +	size_t nmbclen, nmbuflen, mbstatlen, mbtypeslen;
> +	u_long *mbtypes;
> +	bool *seen;	/* "have we seen this type yet?" */
> +
> +	mbtypes = NULL;
> +	seen = NULL;
>  
>  	name[0] = CTL_KERN;
>  	name[1] = KERN_IPC;
> @@ -112,20 +115,40 @@
>  	mbstatlen = sizeof mbstat;
>  	if (sysctl(name, 3, &mbstat, &mbstatlen, 0, 0) < 0) {
>  		warn("sysctl: retrieving mbstat");
> -		return;
> +		goto err;
> +	}
> +
> +	if (sysctlbyname("kern.ipc.mbtypes", NULL, &mbtypeslen, NULL, 0) < 0) {
> +		warn("sysctl: retrieving mbtypes length");
> +		goto err;
> +	}
> +	if ((mbtypes = malloc(mbtypeslen)) == NULL) {
> +		warn("malloc: %lu bytes for mbtypes", (u_long)mbtypeslen);
> +		goto err;
>  	}
> +	if (sysctlbyname("kern.ipc.mbtypes", mbtypes, &mbtypeslen, NULL,
> +	    0) < 0) {
> +		warn("sysctl: retrieving mbtypes");
> +		goto err;
> +	}
>  
> +	nmbtypes = mbtypeslen / sizeof(*mbtypes);
> +	if ((seen = calloc(nmbtypes, sizeof(*seen))) == NULL) {
> +		warn("calloc");
> +		goto err;
> +	}
> +		
>  	name[2] = KIPC_NMBCLUSTERS;
>  	nmbclen = sizeof(int);
>  	if (sysctl(name, 3, &nmbclusters, &nmbclen, 0, 0) < 0) {
>  		warn("sysctl: retrieving nmbclusters");
> -		return;
> +		goto err;
>  	}
>  
>  	nmbuflen = sizeof(int);
>  	if (sysctlbyname("kern.ipc.nmbufs", &nmbufs, &nmbuflen, 0, 0) < 0) {
>  		warn("sysctl: retrieving nmbufs");
> -		return;
> +		goto err;
>  	}
>  
>  #undef MSIZE
> @@ -133,27 +156,22 @@
>  #undef MCLBYTES
>  #define	MCLBYTES	(mbstat.m_mclbytes)
>  
> -	if (nmbtypes != 256) {
> -		warnx("unexpected change to mbstat; check source");
> -		return;
> -	}
> -
>  	totmbufs = 0;
> -	for (mp = mbtypes; mp->mt_name; mp++)
> -		totmbufs += mbstat.m_mtypes[mp->mt_type];
> +	for (mp = mbtypenames; mp->mt_name; mp++)
> +		totmbufs += mbtypes[mp->mt_type];
>  	printf("%u/%lu/%u mbufs in use (current/peak/max):\n", totmbufs,
>  	    mbstat.m_mbufs, nmbufs);
> -	for (mp = mbtypes; mp->mt_name; mp++)
> -		if (mbstat.m_mtypes[mp->mt_type]) {
> +	for (mp = mbtypenames; mp->mt_name; mp++)
> +		if (mbtypes[mp->mt_type]) {
>  			seen[mp->mt_type] = YES;
> -			printf("\t%u mbufs allocated to %s\n",
> -			    mbstat.m_mtypes[mp->mt_type], mp->mt_name);
> +			printf("\t%lu mbufs allocated to %s\n",
> +			    mbtypes[mp->mt_type], mp->mt_name);
>  		}
>  	seen[MT_FREE] = YES;
>  	for (i = 0; i < nmbtypes; i++)
> -		if (!seen[i] && mbstat.m_mtypes[i]) {
> -			printf("\t%u mbufs allocated to <mbuf type %d>\n",
> -			    mbstat.m_mtypes[i], i);
> +		if (!seen[i] && mbtypes[i]) {
> +			printf("\t%lu mbufs allocated to <mbuf type %d>\n",
> +			    mbtypes[i], i);
>  		}
>  	printf("%lu/%lu/%u mbuf clusters in use (current/peak/max)\n",
>  		mbstat.m_clusters - mbstat.m_clfree, mbstat.m_clusters,
> @@ -166,4 +184,10 @@
>  	printf("%lu requests for memory denied\n", mbstat.m_drops);
>  	printf("%lu requests for memory delayed\n", mbstat.m_wait);
>  	printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
> +
> +err:
> +	if (mbtypes != NULL)
> +		free(mbtypes);
> +	if (seen != NULL)
> +		free(seen);
>  }
> 
> 


--
 Bosko Milekic  *  Voice/Mobile: 514.865.7738  *  Pager: 514.921.0237
    bmilekic@technokratis.com  *  http://www.technokratis.com/
Comment 5 Alfred Perlstein freebsd_committer freebsd_triage 2000-07-15 07:46:49 UTC
State Changed
From-To: open->closed

Patches applied, thank you Ian!