From 217c29934ef297ecaf0a3d23e5c4a2d2136ea665 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 21 Sep 2016 11:47:28 -0700 Subject: [PATCH 3/7] Add netdump mbuf allocator hooks One of the problems with earlier implementations of this feature is that it would attempt to allocate mbufs from UMA after a panic. This isn't reliable, particularly if the system was short on memory when it panicked. This implementation reserves mbufs at dumpon time for use by netdump. When the kernel is dumping, the mbuf allocation functions dip into this pool rather than going to UMA. --- sys/kern/kern_mbuf.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++ sys/kern/uipc_mbuf.c | 10 +++++-- sys/sys/mbuf.h | 46 +++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 3 deletions(-) diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c index 58a23ad..b9798ce 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -50,6 +50,10 @@ __FBSDID("$FreeBSD$"); #include #include +/* Begin Isilon */ +#include +/* End Isilon */ + /* * In FreeBSD, Mbufs and Mbuf Clusters are allocated from UMA * Zones. @@ -448,6 +452,14 @@ mb_ctor_mbuf(void *mem, int size, void *arg, int how) int flags; short type; + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + printf("%s: allocation from %p after a panic\n", + __func__, get_caller_ip()); +#endif + /* End Isilon */ + #ifdef INVARIANTS trash_ctor(mem, size, arg, how); #endif @@ -478,6 +490,14 @@ mb_dtor_mbuf(void *mem, int size, void *arg) struct mbuf *m; unsigned long flags; + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + printf("%s: allocation from %p after a panic\n", + __func__, get_caller_ip()); +#endif + /* End Isilon */ + m = (struct mbuf *)mem; flags = (unsigned long)arg; @@ -497,6 +517,14 @@ mb_dtor_pack(void *mem, int size, void *arg) { struct mbuf *m; + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + printf("%s: allocation from %p after a panic\n", + __func__, get_caller_ip()); +#endif + /* End Isilon */ + m = (struct mbuf *)mem; if ((m->m_flags & M_PKTHDR) != 0) m_tag_delete_chain(m, NULL); @@ -537,6 +565,14 @@ mb_ctor_clust(void *mem, int size, void *arg, int how) { struct mbuf *m; + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + printf("%s: allocation from %p after a panic\n", + __func__, get_caller_ip()); +#endif + /* End Isilon */ + #ifdef INVARIANTS trash_ctor(mem, size, arg, how); #endif @@ -568,6 +604,14 @@ mb_zinit_pack(void *mem, int size, int how) { struct mbuf *m; + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + printf("%s: allocation from %p after a panic\n", + __func__, get_caller_ip()); +#endif + /* End Isilon */ + m = (struct mbuf *)mem; /* m is virgin. */ if (uma_zalloc_arg(zone_clust, m, how) == NULL || m->m_ext.ext_buf == NULL) @@ -588,6 +632,14 @@ mb_zfini_pack(void *mem, int size) { struct mbuf *m; + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + printf("%s: allocation from %p after a panic\n", + __func__, get_caller_ip()); +#endif + /* End Isilon */ + m = (struct mbuf *)mem; #ifdef INVARIANTS trash_fini(m->m_ext.ext_buf, MCLBYTES); @@ -609,6 +661,14 @@ mb_ctor_pack(void *mem, int size, void *arg, int how) int error, flags; short type; + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + printf("%s: allocation from %p after a panic\n", + __func__, get_caller_ip()); +#endif + /* End Isilon */ + m = (struct mbuf *)mem; args = (struct mb_args *)arg; flags = args->flags; @@ -724,6 +784,13 @@ mb_free_ext(struct mbuf *m) (void)(*(m->m_ext.ext_free))(m, m->m_ext.ext_arg1, m->m_ext.ext_arg2); break; + /* Begin Isilon */ +#ifdef NETDUMP + case EXT_NETDUMP: + netdump_m_free(m); + break; +#endif + /* End Isilon */ default: KASSERT(m->m_ext.ext_type == 0, ("%s: unknown ext_type", __func__)); @@ -788,6 +855,13 @@ m_get2(int size, int how, short type, int flags) args.type = type; /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + return (netdump_m_get(size, type, flags)); +#endif + /* End Isilon */ + + /* Begin Isilon */ if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0)) { m = uma_zalloc_arg(zone_mbuf, &args, how); MBUF_TRACK_INSERT(m); @@ -831,6 +905,13 @@ m_getjcl(int how, short type, int flags, int size) uma_zone_t zone; /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + return (netdump_m_get(size, type, flags)); +#endif + /* End Isilon */ + + /* Begin Isilon */ if (size == MCLBYTES) { m = m_getcl(how, type, flags); if (m != NULL) diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index cca8c91..475b3778 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -249,9 +249,13 @@ m_pkthdr_init(struct mbuf *m, int how) bzero(&m->m_pkthdr, sizeof(m->m_pkthdr)); #ifdef MAC /* If the label init fails, fail the alloc */ - error = mac_mbuf_init(m, how); - if (error) - return (error); + /* Begin Isilon */ + if (!NETDUMPING()) { + error = mac_mbuf_init(m, how); + if (error) + return (error); + } + /* End Isilon */ #endif return (0); diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 7f34c22..990f1fa 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -456,6 +456,9 @@ struct mbuf { #define EXT_JUMBO16 5 /* jumbo cluster 16184 bytes */ #define EXT_PACKET 6 /* mbuf+cluster from packet zone */ #define EXT_MBUF 7 /* external mbuf reference (M_IOVEC) */ +/* Begin Isilon */ +#define EXT_NETDUMP 8 /* kernel dump pages */ +/* End Isilon */ #define EXT_VENDOR1 224 /* for vendor-internal use */ #define EXT_VENDOR2 225 /* for vendor-internal use */ @@ -688,6 +691,18 @@ struct mbuf *m_unshare(struct mbuf *, int); struct mbuf *m_copytoalignm(struct mbuf *m, int off0, int len0, int wait, int *newlen); /* End Isilon */ +/* Begin Isilon */ +#ifdef NETDUMP +extern int dumping; +#define NETDUMPING() __predict_false(dumping) + +struct mbuf *netdump_m_get(int size, short type, int flags); +void netdump_m_free(struct mbuf *); +#else +#define NETDUMPING() 0 +#endif +/* End Isilon */ + static __inline int m_gettype(int size) { @@ -808,6 +823,13 @@ m_get(int how, short type) struct mbuf *mb; /* End Isilon */ + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + return (netdump_m_get(MLEN, type, 0)); +#endif + /* End Isilon */ + args.flags = 0; args.type = type; /* Begin Isilon */ @@ -845,6 +867,13 @@ m_gethdr(int how, short type) struct mbuf *mb; /* End Isilon */ + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + return (netdump_m_get(MLEN, type, M_PKTHDR)); +#endif + /* End Isilon */ + args.flags = M_PKTHDR; args.type = type; /* Begin Isilon */ @@ -861,6 +890,14 @@ m_getcl(int how, short type, int flags) /* Begin Isilon */ struct mbuf *mb; /* End Isilon */ + + /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) + return (netdump_m_get(MCLBYTES, type, flags)); +#endif + /* End Isilon */ + args.flags = flags; args.type = type; /* Begin Isilon */ @@ -1280,6 +1317,15 @@ m_free(struct mbuf *m) struct mbuf *n = m->m_next; /* Begin Isilon */ +#ifdef NETDUMP + if (NETDUMPING()) { + netdump_m_free(m); + return (n); + } +#endif + /* End Isilon */ + + /* Begin Isilon */ MBUF_TRACK_REMOVE(m); M_TRACK_FREE(m, __func__); if ((m->m_flags & M_EXT) != 0) -- 2.10.1