From d4426f281da07fb113c31aa445d6de39d0fea4e6 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Sun, 13 Nov 2005 14:06:01 +0000 Subject: [PATCH] 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 --- usr.bin/netstat/main.c | 14 +-- usr.bin/netstat/mbuf.c | 215 +++++++++----------------------------- usr.bin/netstat/netstat.h | 3 +- 3 files changed, 54 insertions(+), 178 deletions(-) diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c index 5a07e3bea183..4c89a941ace6 100644 --- a/usr.bin/netstat/main.c +++ b/usr.bin/netstat/main.c @@ -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 diff --git a/usr.bin/netstat/mbuf.c b/usr.bin/netstat/mbuf.c index 9bb403822d6d..4faa18d7c3ea 100644 --- a/usr.bin/netstat/mbuf.c +++ b/usr.bin/netstat/mbuf.c @@ -49,138 +49,18 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #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 \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,13 +83,28 @@ 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 (memstat_sysctl_all(mtlp, 0) < 0) { - warnx("memstat_sysctl_all: %s", - memstat_strerror(memstat_mtl_geterror(mtlp))); - goto out; + 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); @@ -267,14 +164,17 @@ mbpr_sysctl(void) printf("%llu mbuf tags in use\n", tag_count); #endif - mlen = sizeof(nsfbufs); - if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &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); + if (live) { + mlen = sizeof(nsfbufs); + if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &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); + } } /*- @@ -326,34 +226,21 @@ mbpr_sysctl(void) packet_failures); #endif - 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); - printf("%lu requests for I/O initiated by sendfile\n", - mbstat.sf_iocnt); - printf("%lu calls to protocol drain routines\n", - mbstat.m_drain); + if (live) { + mlen = sizeof(mbstat); + 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); 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(); -} diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h index c69d5f7c4343..3d3e745c52d1 100644 --- a/usr.bin/netstat/netstat.h +++ b/usr.bin/netstat/netstat.h @@ -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);