Skip site navigation (1)Skip section navigation (2)
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>