Modify netstat -mb to use libmemstat when accessing a core dump or live
kernel memory and not using sysctl. Previously, libmemstat was used only for the live kernel via sysctl paths. This results in netstat output becoming both more consistent between core dumps and the live kernel, and also more information in the core dump case than previously (i.e., mbuf cache information). Statistics relating to sfbufs still rely on a kvm descriptor as they are not currently exposed via libmemstat. netstat -m operating on a core is still unable to print certain sfbuf stats available on the live kernel. MFC after: 1 week
This commit is contained in:
parent
be2cb7fae9
commit
d4426f281d
@ -447,19 +447,9 @@ main(int argc, char *argv[])
|
||||
if (mflag) {
|
||||
if (memf != NULL) {
|
||||
if (kread(0, 0, 0) == 0)
|
||||
mbpr(nl[N_MBSTAT].n_value,
|
||||
nl[N_MBTYPES].n_value,
|
||||
nl[N_NMBCLUSTERS].n_value,
|
||||
nl[N_NMBUFS].n_value,
|
||||
nl[N_MBHI].n_value,
|
||||
nl[N_CLHI].n_value,
|
||||
nl[N_MBLO].n_value,
|
||||
nl[N_CLLO].n_value,
|
||||
nl[N_NCPUS].n_value,
|
||||
nl[N_PAGESZ].n_value,
|
||||
nl[N_MBPSTAT].n_value);
|
||||
mbpr(kvmd, nl[N_MBSTAT].n_value);
|
||||
} else
|
||||
mbpr(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
mbpr(NULL, 0);
|
||||
exit(0);
|
||||
}
|
||||
#if 0
|
||||
|
@ -49,138 +49,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <kvm.h>
|
||||
#include <memstat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "netstat.h"
|
||||
|
||||
#define YES 1
|
||||
typedef int bool;
|
||||
|
||||
static struct mbtypenames {
|
||||
short mt_type;
|
||||
const char *mt_name;
|
||||
} mbtypenames[] = {
|
||||
{ MT_DATA, "data" },
|
||||
{ MT_OOBDATA, "oob data" },
|
||||
{ MT_CONTROL, "ancillary data" },
|
||||
{ MT_HEADER, "packet headers" },
|
||||
#ifdef MT_SOCKET
|
||||
{ MT_SOCKET, "socket structures" }, /* XXX */
|
||||
#endif
|
||||
#ifdef MT_PCB
|
||||
{ MT_PCB, "protocol control blocks" }, /* XXX */
|
||||
#endif
|
||||
#ifdef MT_RTABLE
|
||||
{ MT_RTABLE, "routing table entries" }, /* XXX */
|
||||
#endif
|
||||
#ifdef MT_HTABLE
|
||||
{ MT_HTABLE, "IMP host table entries" }, /* XXX */
|
||||
#endif
|
||||
#ifdef MT_ATABLE
|
||||
{ MT_ATABLE, "address resolution tables" },
|
||||
#endif
|
||||
{ MT_FTABLE, "fragment reassembly queue headers" }, /* XXX */
|
||||
{ MT_SONAME, "socket names and addresses" },
|
||||
#ifdef MT_SOOPTS
|
||||
{ MT_SOOPTS, "socket options" },
|
||||
#endif
|
||||
#ifdef MT_RIGHTS
|
||||
{ MT_RIGHTS, "access rights" },
|
||||
#endif
|
||||
#ifdef MT_IFADDR
|
||||
{ MT_IFADDR, "interface addresses" }, /* XXX */
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Print mbuf statistics extracted from kmem.
|
||||
* Print mbuf statistics.
|
||||
*/
|
||||
void
|
||||
mbpr_kmem(u_long mbaddr, u_long nmbcaddr, u_long nmbufaddr, u_long mbhiaddr,
|
||||
u_long clhiaddr, u_long mbloaddr, u_long clloaddr, u_long pgsaddr,
|
||||
u_long mbpaddr)
|
||||
{
|
||||
int i, nmbclusters;
|
||||
short nmbtypes;
|
||||
size_t mlen;
|
||||
long *mbtypes = NULL;
|
||||
struct mbstat *mbstat = NULL;
|
||||
struct mbtypenames *mp;
|
||||
bool *seen = NULL;
|
||||
|
||||
mlen = sizeof *mbstat;
|
||||
if ((mbstat = malloc(mlen)) == NULL) {
|
||||
warn("malloc: cannot allocate memory for mbstat");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (kread(mbaddr, (char *)mbstat, sizeof mbstat))
|
||||
goto err;
|
||||
if (kread(nmbcaddr, (char *)&nmbclusters, sizeof(int)))
|
||||
goto err;
|
||||
|
||||
if (mbstat->m_mbufs < 0) mbstat->m_mbufs = 0; /* XXX */
|
||||
if (mbstat->m_mclusts < 0) mbstat->m_mclusts = 0; /* XXX */
|
||||
|
||||
nmbtypes = mbstat->m_numtypes;
|
||||
if ((seen = calloc(nmbtypes, sizeof(*seen))) == NULL) {
|
||||
warn("calloc: cannot allocate memory for mbtypes seen flag");
|
||||
goto err;
|
||||
}
|
||||
if ((mbtypes = calloc(nmbtypes, sizeof(long *))) == NULL) {
|
||||
warn("calloc: cannot allocate memory for mbtypes");
|
||||
goto err;
|
||||
}
|
||||
|
||||
#undef MSIZE
|
||||
#define MSIZE (mbstat->m_msize)
|
||||
#undef MCLBYTES
|
||||
#define MCLBYTES (mbstat->m_mclbytes)
|
||||
|
||||
printf("%lu mbufs in use\n", mbstat->m_mbufs);
|
||||
|
||||
for (mp = mbtypenames; mp->mt_name; mp++) {
|
||||
if (mbtypes[mp->mt_type]) {
|
||||
seen[mp->mt_type] = YES;
|
||||
printf("\t %lu mbufs allocated to %s\n",
|
||||
mbtypes[mp->mt_type], mp->mt_name);
|
||||
}
|
||||
}
|
||||
for (i = 1; i < nmbtypes; i++) {
|
||||
if (!seen[i] && mbtypes[i])
|
||||
printf("\t %lu mbufs allocated to <mbuf type: %d>\n",
|
||||
mbtypes[i], i);
|
||||
}
|
||||
|
||||
printf("%lu/%d mbuf clusters in use (current/max)\n",
|
||||
mbstat->m_mclusts, nmbclusters);
|
||||
|
||||
printf("%lu KBytes allocated to network\n", (mbstat->m_mbufs * MSIZE +
|
||||
mbstat->m_mclusts * MCLBYTES) / 1024);
|
||||
printf("%lu requests for sfbufs denied\n", mbstat->sf_allocfail);
|
||||
printf("%lu requests for sfbufs delayed\n", mbstat->sf_allocwait);
|
||||
printf("%lu requests for I/O initiated by sendfile\n",
|
||||
mbstat->sf_iocnt);
|
||||
printf("%lu calls to protocol drain routines\n", mbstat->m_drain);
|
||||
|
||||
err:
|
||||
if (mbtypes != NULL)
|
||||
free(mbtypes);
|
||||
if (seen != NULL)
|
||||
free(seen);
|
||||
if (mbstat != NULL)
|
||||
free(mbstat);
|
||||
}
|
||||
|
||||
/*
|
||||
* If running on a live kernel, directly query the zone allocator for stats
|
||||
* from the four mbuf-related zones/types.
|
||||
*/
|
||||
static void
|
||||
mbpr_sysctl(void)
|
||||
mbpr(void *kvmd, u_long mbaddr)
|
||||
{
|
||||
struct memory_type_list *mtlp;
|
||||
struct memory_type *mtp;
|
||||
@ -193,7 +73,9 @@ mbpr_sysctl(void)
|
||||
int nsfbufs, nsfbufspeak, nsfbufsused;
|
||||
struct mbstat mbstat;
|
||||
size_t mlen;
|
||||
int error, live;
|
||||
|
||||
live = (kvmd == NULL);
|
||||
mtlp = memstat_mtl_alloc();
|
||||
if (mtlp == NULL) {
|
||||
warn("memstat_mtl_alloc");
|
||||
@ -201,14 +83,29 @@ mbpr_sysctl(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Use memstat_sysctl_all() because some mbuf-related memory is in
|
||||
* uma(9), and some malloc(9).
|
||||
* Use memstat_*_all() because some mbuf-related memory is in uma(9),
|
||||
* and some malloc(9).
|
||||
*/
|
||||
if (live) {
|
||||
printf("live\n");
|
||||
if (memstat_sysctl_all(mtlp, 0) < 0) {
|
||||
warnx("memstat_sysctl_all: %s",
|
||||
memstat_strerror(memstat_mtl_geterror(mtlp)));
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
printf("kvm\n");
|
||||
if (memstat_kvm_all(mtlp, kvmd) < 0) {
|
||||
error = memstat_mtl_geterror(mtlp);
|
||||
if (error == MEMSTAT_ERROR_KVM)
|
||||
warnx("memstat_kvm_all: %s",
|
||||
kvm_geterr(kvmd));
|
||||
else
|
||||
warnx("memstat_kvm_all: %s",
|
||||
memstat_strerror(error));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_MEM_NAME);
|
||||
if (mtp == NULL) {
|
||||
@ -267,15 +164,18 @@ mbpr_sysctl(void)
|
||||
printf("%llu mbuf tags in use\n", tag_count);
|
||||
#endif
|
||||
|
||||
if (live) {
|
||||
mlen = sizeof(nsfbufs);
|
||||
if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &mlen, NULL, 0) &&
|
||||
!sysctlbyname("kern.ipc.nsfbufsused", &nsfbufsused, &mlen, NULL,
|
||||
if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &mlen, NULL,
|
||||
0) &&
|
||||
!sysctlbyname("kern.ipc.nsfbufspeak", &nsfbufspeak, &mlen, NULL,
|
||||
0)) {
|
||||
!sysctlbyname("kern.ipc.nsfbufsused", &nsfbufsused,
|
||||
&mlen, NULL, 0) &&
|
||||
!sysctlbyname("kern.ipc.nsfbufspeak", &nsfbufspeak,
|
||||
&mlen, NULL, 0)) {
|
||||
printf("%d/%d/%d sfbufs in use (current/peak/max)\n",
|
||||
nsfbufsused, nsfbufspeak, nsfbufs);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* Calculate in-use bytes as:
|
||||
@ -326,34 +226,21 @@ mbpr_sysctl(void)
|
||||
packet_failures);
|
||||
#endif
|
||||
|
||||
if (live) {
|
||||
mlen = sizeof(mbstat);
|
||||
if (!sysctlbyname("kern.ipc.mbstat", &mbstat, &mlen, NULL, 0)) {
|
||||
printf("%lu requests for sfbufs denied\n",
|
||||
mbstat.sf_allocfail);
|
||||
printf("%lu requests for sfbufs delayed\n",
|
||||
mbstat.sf_allocwait);
|
||||
if (sysctlbyname("kern.ipc.mbstat", &mbstat, &mlen, NULL, 0)) {
|
||||
warn("kern.ipc.mbstat");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (kread(mbaddr, (char *)&mbstat, sizeof mbstat))
|
||||
goto out;
|
||||
}
|
||||
printf("%lu requests for sfbufs denied\n", mbstat.sf_allocfail);
|
||||
printf("%lu requests for sfbufs delayed\n", mbstat.sf_allocwait);
|
||||
printf("%lu requests for I/O initiated by sendfile\n",
|
||||
mbstat.sf_iocnt);
|
||||
printf("%lu calls to protocol drain routines\n",
|
||||
mbstat.m_drain);
|
||||
}
|
||||
|
||||
printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
|
||||
out:
|
||||
memstat_mtl_free(mtlp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print mbuf statistics.
|
||||
*/
|
||||
void
|
||||
mbpr(u_long mbaddr, u_long mbtaddr __unused, u_long nmbcaddr, u_long nmbufaddr,
|
||||
u_long mbhiaddr, u_long clhiaddr, u_long mbloaddr, u_long clloaddr,
|
||||
u_long cpusaddr __unused, u_long pgsaddr, u_long mbpaddr)
|
||||
{
|
||||
|
||||
if (mbaddr != 0)
|
||||
mbpr_kmem(mbaddr, nmbcaddr, nmbufaddr, mbhiaddr, clhiaddr,
|
||||
mbloaddr, clloaddr, pgsaddr, mbpaddr);
|
||||
else
|
||||
mbpr_sysctl();
|
||||
}
|
||||
|
@ -99,8 +99,7 @@ void inet6print(struct in6_addr *, int, const char *, int);
|
||||
void pfkey_stats(u_long, const char *, int);
|
||||
#endif
|
||||
|
||||
void mbpr(u_long, u_long, u_long, u_long, u_long, u_long,
|
||||
u_long, u_long, u_long, u_long, u_long);
|
||||
void mbpr(void *, u_long);
|
||||
|
||||
void hostpr(u_long, u_long);
|
||||
void impstats(u_long, u_long);
|
||||
|
Loading…
Reference in New Issue
Block a user