Date: Tue, 22 Mar 2016 13:16:53 +0000 (UTC) From: "George V. Neville-Neil" <gnn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r297188 - in head: share/dtrace sys/kern sys/sys Message-ID: <201603221316.u2MDGrNJ020249@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gnn Date: Tue Mar 22 13:16:52 2016 New Revision: 297188 URL: https://svnweb.freebsd.org/changeset/base/297188 Log: Add an mbuf provider to DTrace. The mbuf provider is made up of a set of Statically Defined Tracepoints which help us look into mbufs as they are allocated and freed. This can be used to inspect the buffers or for a simplified mbuf leak detector. New tracepoints are: mbuf:::m-init mbuf:::m-gethdr mbuf:::m-get mbuf:::m-getcl mbuf:::m-clget mbuf:::m-cljget mbuf:::m-cljset mbuf:::m-free mbuf:::m-freem There is also a translator for mbufs which gives some visibility into the structure, see mbuf.d for more details. Reviewed by: bz, markj MFC after: 2 weeks Sponsored by: Rubicon Communications (Netgate) Differential Revision: https://reviews.freebsd.org/D5682 Added: head/share/dtrace/mbuf.d (contents, props changed) Modified: head/share/dtrace/Makefile head/sys/kern/kern_mbuf.c head/sys/kern/uipc_mbuf.c head/sys/sys/mbuf.h Modified: head/share/dtrace/Makefile ============================================================================== --- head/share/dtrace/Makefile Tue Mar 22 12:40:09 2016 (r297187) +++ head/share/dtrace/Makefile Tue Mar 22 13:16:52 2016 (r297188) @@ -30,4 +30,10 @@ SCRIPTS= blocking \ SCRIPTSDIR= ${SHAREDIR}/dtrace +DSRCS= mbuf.d + +FILES= ${DSRCS} +FILESDIR= /usr/lib/dtrace +FILESMODE= ${NOBINMODE} + .include <bsd.prog.mk> Added: head/share/dtrace/mbuf.d ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/dtrace/mbuf.d Tue Mar 22 13:16:52 2016 (r297188) @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2016 George V. Neville-Neil + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + * Translators and flags for the mbuf structure. FreeBSD specific code. + * + */ + +#pragma D depends_on module kernel +#pragma D depends_on provider mbuf + +/* + * mbuf flags of global significance and layer crossing. + * Those of only protocol/layer specific significance are to be mapped + * to M_PROTO[1-12] and cleared at layer handoff boundaries. + * NB: Limited to the lower 24 bits. + */ + +#pragma D binding "1.6.3" M_EXT +inline int M_EXT = 0x00000001; /* has associated external storage */ +#pragma D binding "1.6.3" M_PKTHDR +inline int M_PKTHDR = 0x00000002; /* start of record */ +#pragma D binding "1.6.3" M_EOR +inline int M_EOR = 0x00000004; /* end of record */ +#pragma D binding "1.6.3" M_RDONLY +inline int M_RDONLY = 0x00000008; /* associated data is marked read-only */ +#pragma D binding "1.6.3" M_BCAST +inline int M_BCAST = 0x00000010; /* send/received as link-level broadcast */ +#pragma D binding "1.6.3" M_MCAST +inline int M_MCAST = 0x00000020; /* send/received as link-level multicast */ +#pragma D binding "1.6.3" M_PROMISC +inline int M_PROMISC = 0x00000040; /* packet was not for us */ +#pragma D binding "1.6.3" M_VLANTAG +inline int M_VLANTAG = 0x00000080; /* ether_vtag is valid */ +#pragma D binding "1.6.3" M_UNUSED_8 +inline int M_UNUSED_8 = 0x00000100; /* --available-- */ +#pragma D binding "1.6.3" M_NOFREE +inline int M_NOFREE = 0x00000200; /* do not free mbuf, embedded in cluster */ + +#pragma D binding "1.6.3" M_PROTO1 +inline int M_PROTO1 = 0x00001000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO2 +inline int M_PROTO2 = 0x00002000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO3 +inline int M_PROTO3 = 0x00004000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO4 +inline int M_PROTO4 = 0x00008000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO5 +inline int M_PROTO5 = 0x00010000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO6 +inline int M_PROTO6 = 0x00020000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO7 +inline int M_PROTO7 = 0x00040000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO8 +inline int M_PROTO8 = 0x00080000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO9 +inline int M_PROTO9 = 0x00100000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO10 +inline int M_PROTO10 = 0x00200000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO11 +inline int M_PROTO11 = 0x00400000; /* protocol-specific */ +#pragma D binding "1.6.3" M_PROTO12 +inline int M_PROTO12 = 0x00800000; /* protocol-specific */ + +#pragma D binding "1.6.3" mbufflags_string +inline string mbufflags_string[uint32_t flags] = + flags & M_EXT ? "M_EXT" : + flags & M_PKTHDR ? "M_PKTHDR" : + flags & M_EOR ? "M_EOR" : + flags & M_RDONLY ? "M_RDONLY" : + flags & M_BCAST ? "M_BCAST" : + flags & M_MCAST ? "M_MCAST" : + flags & M_PROMISC ? "M_PROMISC" : + flags & M_VLANTAG ? "M_VLANTAG" : + flags & M_UNUSED_8 ? "M_UNUSED_8" : + flags & M_NOFREE ? "M_NOFREE" : + flags & M_PROTO1 ? "M_PROTO1" : + flags & M_PROTO2 ? "M_PROTO2" : + flags & M_PROTO3 ? "M_PROTO3" : + flags & M_PROTO4 ? "M_PROTO4" : + flags & M_PROTO5 ? "M_PROTO5" : + flags & M_PROTO6 ? "M_PROTO6" : + flags & M_PROTO7 ? "M_PROTO7" : + flags & M_PROTO8 ? "M_PROTO8" : + flags & M_PROTO9 ? "M_PROTO9" : + flags & M_PROTO10 ? "M_PROTO10" : + flags & M_PROTO11 ? "M_PROTO11" : + flags & M_PROTO12 ? "M_PROTO12" : + "none" ; + +/* + * Packet tag structure (see below for details). + */ +typedef struct m_tag { + u_int16_t m_tag_id; /* Tag ID */ + u_int16_t m_tag_len; /* Length of data */ + u_int32_t m_tag_cookie; /* ABI/Module ID */ +} m_tag_t; + +/* + * Record/packet header in first mbuf of chain; valid only if M_PKTHDR is set. + * Size ILP32: 48 + * LP64: 56 + * Compile-time assertions in uipc_mbuf.c test these values to ensure that + * they are correct. + */ +typedef struct pkthdr { +/* struct ifnet *rcvif; */ /* rcv interface */ + int32_t len; /* total packet length */ + + /* Layer crossing persistent information. */ + uint32_t flowid; /* packet's 4-tuple system */ + uint64_t csum_flags; /* checksum and offload features */ + uint16_t fibnum; /* this packet should use this fib */ + uint8_t cosqos; /* class/quality of service */ + uint8_t rsstype; /* hash type */ +} pkthdr_t; + +/* + * Description of external storage mapped into mbuf; valid only if M_EXT is + * set. + * Size ILP32: 28 + * LP64: 48 + * Compile-time assertions in uipc_mbuf.c test these values to ensure that + * they are correct. + */ +typedef struct m_ext { + volatile u_int *ext_cnt; /* pointer to ref count info */ + caddr_t ext_buf; /* start of buffer */ + uint32_t ext_size; /* size of buffer, for ext_free */ + uint32_t ext_type:8, /* type of external storage */ + ext_flags:24; /* external storage mbuf flags */ + void *ext_arg1; /* optional argument pointer */ + void *ext_arg2; /* optional argument pointer */ +} m_ext_t; + +/* + * The core of the mbuf object along with some shortcut defines for practical + * purposes. + */ +struct mbuf { + uintptr_t mbuf_addr; + /* + * Header present at the beginning of every mbuf. + * Size ILP32: 24 + * LP64: 32 + * Compile-time assertions in uipc_mbuf.c test these values to ensure + * that they are correct. + */ + caddr_t m_data; /* location of data */ + int32_t m_len; /* amount of data in this mbuf */ + uint32_t m_type:8, /* type of data in this mbuf */ + m_flags:24; /* flags; see below */ + /* + * A set of optional headers (packet header, external storage header) + * and internal data storage. Historically, these arrays were sized + * to MHLEN (space left after a packet header) and MLEN (space left + * after only a regular mbuf header); they are now variable size in + * order to support future work on variable-size mbufs. + */ + /* union { */ + /* struct { */ + /* struct pkthdr m_pkthdr; */ + /* union { */ + /* struct m_ext m_ext; */ + /* char m_pktdat[0]; */ + /* }; */ + /* }; */ + /* char m_dat[0]; */ + /* }; */ + char *m_dat; +}; + +typedef struct mbufinfo { + uintptr_t mbuf_addr; + caddr_t m_data; + int32_t m_len; + uint8_t m_type; + uint32_t m_flags; +} mbufinfo_t; + +translator mbufinfo_t < struct mbuf *p > { + mbuf_addr = (uintptr_t)p; + m_data = p->m_data; + m_len = p->m_len; + m_type = p->m_type & 0xff000000; + m_flags = p->m_type & 0x00ffffff; +}; Modified: head/sys/kern/kern_mbuf.c ============================================================================== --- head/sys/kern/kern_mbuf.c Tue Mar 22 12:40:09 2016 (r297187) +++ head/sys/kern/kern_mbuf.c Tue Mar 22 13:16:52 2016 (r297188) @@ -731,6 +731,7 @@ m_clget(struct mbuf *m, int how) zone_drain(zone_pack); uma_zalloc_arg(zone_clust, m, how); } + MBUF_PROBE2(m__clget, m, how); return (m->m_flags & M_EXT); } @@ -745,7 +746,8 @@ void * m_cljget(struct mbuf *m, int how, int size) { uma_zone_t zone; - + void *retval; + if (m != NULL) { KASSERT((m->m_flags & M_EXT) == 0, ("%s: mbuf %p has M_EXT", __func__, m)); @@ -753,7 +755,11 @@ m_cljget(struct mbuf *m, int how, int si } zone = m_getzone(size); - return (uma_zalloc_arg(zone, m, how)); + retval = uma_zalloc_arg(zone, m, how); + + MBUF_PROBE4(m__cljget, m, how, size, retval); + + return (retval); } /* @@ -933,6 +939,7 @@ m_extadd(struct mbuf *mb, caddr_t buf, u void m_freem(struct mbuf *mb) { + MBUF_PROBE1(m__freem, mb); while (mb != NULL) mb = m_free(mb); Modified: head/sys/kern/uipc_mbuf.c ============================================================================== --- head/sys/kern/uipc_mbuf.c Tue Mar 22 12:40:09 2016 (r297187) +++ head/sys/kern/uipc_mbuf.c Tue Mar 22 13:16:52 2016 (r297188) @@ -47,6 +47,51 @@ __FBSDID("$FreeBSD$"); #include <sys/domain.h> #include <sys/protosw.h> #include <sys/uio.h> +#include <sys/sdt.h> + +SDT_PROVIDER_DEFINE(mbuf); + +SDT_PROBE_DEFINE5_XLATE(mbuf, , , m__init, + "struct mbuf *", "mbufinfo_t *", + "uint32_t", "uint32_t", + "uint16_t", "uint16_t", + "uint32_t", "uint32_t", + "uint32_t", "uint32_t"); + +SDT_PROBE_DEFINE3_XLATE(mbuf, , , m__gethdr, + "uint32_t", "uint32_t", + "uint16_t", "uint16_t", + "struct mbuf *", "mbufinfo_t *"); + +SDT_PROBE_DEFINE3_XLATE(mbuf, , , m__get, + "uint32_t", "uint32_t", + "uint16_t", "uint16_t", + "struct mbuf *", "mbufinfo_t *"); + +SDT_PROBE_DEFINE4_XLATE(mbuf, , , m__getcl, + "uint32_t", "uint32_t", + "uint16_t", "uint16_t", + "uint32_t", "uint32_t", + "struct mbuf *", "mbufinfo_t *"); + +SDT_PROBE_DEFINE3_XLATE(mbuf, , , m__clget, + "struct mbuf *", "mbufinfo_t *", + "uint32_t", "uint32_t", + "uint32_t", "uint32_t"); + +SDT_PROBE_DEFINE4_XLATE(mbuf, , , m__cljget, + "struct mbuf *", "mbufinfo_t *", + "uint32_t", "uint32_t", + "uint32_t", "uint32_t", + "void*", "void*"); + +SDT_PROBE_DEFINE(mbuf, , , m__cljset); + +SDT_PROBE_DEFINE1_XLATE(mbuf, , , m__free, + "struct mbuf *", "mbufinfo_t *"); + +SDT_PROBE_DEFINE1_XLATE(mbuf, , , m__freem, + "struct mbuf *", "mbufinfo_t *"); #include <security/mac/mac_framework.h> Modified: head/sys/sys/mbuf.h ============================================================================== --- head/sys/sys/mbuf.h Tue Mar 22 12:40:09 2016 (r297187) +++ head/sys/sys/mbuf.h Tue Mar 22 13:16:52 2016 (r297188) @@ -44,6 +44,34 @@ #endif #endif +#ifdef _KERNEL +#include <sys/sdt.h> + +#define MBUF_PROBE1(probe, arg0) \ + SDT_PROBE1(mbuf, , , probe, arg0) +#define MBUF_PROBE2(probe, arg0, arg1) \ + SDT_PROBE2(mbuf, , , probe, arg0, arg1) +#define MBUF_PROBE3(probe, arg0, arg1, arg2) \ + SDT_PROBE3(mbuf, , , probe, arg0, arg1, arg2) +#define MBUF_PROBE4(probe, arg0, arg1, arg2, arg3) \ + SDT_PROBE4(mbuf, , , probe, arg0, arg1, arg2, arg3) +#define MBUF_PROBE5(probe, arg0, arg1, arg2, arg3, arg4) \ + SDT_PROBE5(mbuf, , , probe, arg0, arg1, arg2, arg3, arg4) + +SDT_PROVIDER_DECLARE(mbuf); + +SDT_PROBE_DECLARE(mbuf, , , m__init); +SDT_PROBE_DECLARE(mbuf, , , m__gethdr); +SDT_PROBE_DECLARE(mbuf, , , m__get); +SDT_PROBE_DECLARE(mbuf, , , m__getcl); +SDT_PROBE_DECLARE(mbuf, , , m__clget); +SDT_PROBE_DECLARE(mbuf, , , m__cljget); +SDT_PROBE_DECLARE(mbuf, , , m__cljset); +SDT_PROBE_DECLARE(mbuf, , , m__free); +SDT_PROBE_DECLARE(mbuf, , , m__freem); + +#endif /* _KERNEL */ + /* * Mbufs are of a single size, MSIZE (sys/param.h), which includes overhead. * An mbuf may add a single "mbuf cluster" of size MCLBYTES (also in @@ -664,7 +692,7 @@ m_getzone(int size) static __inline int m_init(struct mbuf *m, int how, short type, int flags) { - int error; + int error = 0; m->m_next = NULL; m->m_nextpkt = NULL; @@ -672,42 +700,50 @@ m_init(struct mbuf *m, int how, short ty m->m_len = 0; m->m_flags = flags; m->m_type = type; - if (flags & M_PKTHDR) { - if ((error = m_pkthdr_init(m, how)) != 0) - return (error); - } + if (flags & M_PKTHDR) + error = m_pkthdr_init(m, how); - return (0); + MBUF_PROBE5(m__init, m, how, type, flags, error); + return (error); } static __inline struct mbuf * m_get(int how, short type) { + struct mbuf *m; struct mb_args args; args.flags = 0; args.type = type; - return (uma_zalloc_arg(zone_mbuf, &args, how)); + m = uma_zalloc_arg(zone_mbuf, &args, how); + MBUF_PROBE3(m__get, how, type, m); + return (m); } static __inline struct mbuf * m_gethdr(int how, short type) { + struct mbuf *m; struct mb_args args; args.flags = M_PKTHDR; args.type = type; - return (uma_zalloc_arg(zone_mbuf, &args, how)); + m = uma_zalloc_arg(zone_mbuf, &args, how); + MBUF_PROBE3(m__gethdr, how, type, m); + return (m); } static __inline struct mbuf * m_getcl(int how, short type, int flags) { + struct mbuf *m; struct mb_args args; args.flags = flags; args.type = type; - return (uma_zalloc_arg(zone_pack, &args, how)); + m = uma_zalloc_arg(zone_pack, &args, how); + MBUF_PROBE4(m__getcl, how, type, flags, m); + return (m); } /* @@ -747,6 +783,7 @@ m_cljset(struct mbuf *m, void *cl, int t m->m_ext.ext_flags = EXT_FLAG_EMBREF; m->m_ext.ext_count = 1; m->m_flags |= M_EXT; + MBUF_PROBE3(m__cljset, m, cl, type); } static __inline void @@ -1122,6 +1159,7 @@ m_free(struct mbuf *m) { struct mbuf *n = m->m_next; + MBUF_PROBE1(m__free, m); if ((m->m_flags & (M_PKTHDR|M_NOFREE)) == (M_PKTHDR|M_NOFREE)) m_tag_delete_chain(m, NULL); if (m->m_flags & M_EXT)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201603221316.u2MDGrNJ020249>