Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 4 Feb 2010 07:55:42 +0000 (UTC)
From:      Marko Zec <zec@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r203483 - head/sys/net
Message-ID:  <201002040755.o147tgXS053773@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: zec
Date: Thu Feb  4 07:55:42 2010
New Revision: 203483
URL: http://svn.freebsd.org/changeset/base/203483

Log:
  Instead of spamming the console on each curvnet recursion event, print
  out each such call graph only once, along with a stack backtrace.  This
  should make kernels built with VNET_DEBUG reasonably usable again in
  busy / production environments.
  
  Introduce a new DDB command "show vnetrcrs" which dumps the whole log
  of distinctive curvnet recursion events.  This might be useful when
  recursion reports get burried / lost too deep in the message buffer.
  In the later case stack backtraces are not available.
  
  Reviewed by:	bz
  MFC after:	3 days

Modified:
  head/sys/net/vnet.c
  head/sys/net/vnet.h

Modified: head/sys/net/vnet.c
==============================================================================
--- head/sys/net/vnet.c	Thu Feb  4 07:26:26 2010	(r203482)
+++ head/sys/net/vnet.c	Thu Feb  4 07:55:42 2010	(r203483)
@@ -37,8 +37,10 @@
 __FBSDID("$FreeBSD$");
 
 #include "opt_ddb.h"
+#include "opt_kdb.h"
 
 #include <sys/param.h>
+#include <sys/kdb.h>
 #include <sys/kernel.h>
 #include <sys/jail.h>
 #include <sys/systm.h>
@@ -616,6 +618,65 @@ vnet_sysuninit(void)
 	VNET_SYSINIT_RUNLOCK();
 }
 
+#ifdef VNET_DEBUG
+struct vnet_recursion {
+	SLIST_ENTRY(vnet_recursion)	 vnr_le;
+	const char			*prev_fn;
+	const char			*where_fn;
+	int				 where_line;
+	struct vnet			*old_vnet;
+	struct vnet			*new_vnet;
+};
+
+static SLIST_HEAD(, vnet_recursion) vnet_recursions =
+    SLIST_HEAD_INITIALIZER(vnet_recursions);
+
+static void
+vnet_print_recursion(struct vnet_recursion *vnr, int brief)
+{
+
+	if (!brief)
+		printf("CURVNET_SET() recursion in ");
+	printf("%s() line %d, prev in %s()", vnr->where_fn, vnr->where_line,
+	    vnr->prev_fn);
+	if (brief)
+		printf(", ");
+	else
+		printf("\n    ");
+	printf("%p -> %p\n", vnr->old_vnet, vnr->new_vnet);
+}
+
+void
+vnet_log_recursion(struct vnet *old_vnet, const char *old_fn, int line)
+{
+	struct vnet_recursion *vnr;
+
+	/* Skip already logged recursion events. */
+	SLIST_FOREACH(vnr, &vnet_recursions, vnr_le)
+		if (vnr->prev_fn == old_fn &&
+		    vnr->where_fn == curthread->td_vnet_lpush &&
+		    vnr->where_line == line &&
+		    (vnr->old_vnet == vnr->new_vnet) == (curvnet == old_vnet))
+			return;
+
+	vnr = malloc(sizeof(*vnr), M_VNET, M_NOWAIT | M_ZERO);
+	if (vnr == NULL)
+		panic("%s: malloc failed", __func__);
+	vnr->prev_fn = old_fn;
+	vnr->where_fn = curthread->td_vnet_lpush;
+	vnr->where_line = line;
+	vnr->old_vnet = old_vnet;
+	vnr->new_vnet = curvnet;
+
+	SLIST_INSERT_HEAD(&vnet_recursions, vnr, vnr_le);
+
+	vnet_print_recursion(vnr, 0);
+#ifdef KDB
+	kdb_backtrace();
+#endif
+}
+#endif /* VNET_DEBUG */
+
 #ifdef DDB
 DB_SHOW_COMMAND(vnets, db_show_vnets)
 {
@@ -637,4 +698,14 @@ DB_SHOW_COMMAND(vnets, db_show_vnets)
 			break;
 	}
 }
+
+#ifdef VNET_DEBUG
+DB_SHOW_COMMAND(vnetrcrs, db_show_vnetrcrs)
+{
+	struct vnet_recursion *vnr;
+
+	SLIST_FOREACH(vnr, &vnet_recursions, vnr_le)
+		vnet_print_recursion(vnr, 1);
+}
 #endif
+#endif /* DDB */

Modified: head/sys/net/vnet.h
==============================================================================
--- head/sys/net/vnet.h	Thu Feb  4 07:26:26 2010	(r203482)
+++ head/sys/net/vnet.h	Thu Feb  4 07:55:42 2010	(r203483)
@@ -108,6 +108,8 @@ void	vnet_destroy(struct vnet *vnet);
  * assertions.
  */
 #ifdef VNET_DEBUG
+void vnet_log_recursion(struct vnet *, const char *, int);
+
 #define	VNET_ASSERT(condition)						\
 	if (!(condition)) {						\
 		printf("VNET_ASSERT @ %s:%d %s():\n",			\
@@ -125,9 +127,7 @@ void	vnet_destroy(struct vnet *vnet);
 #define	CURVNET_SET_VERBOSE(arg)					\
 	CURVNET_SET_QUIET(arg)						\
 	if (saved_vnet)							\
-		printf("CURVNET_SET(%p) in %s() on cpu %d, prev %p in %s()\n", \
-		       curvnet,	curthread->td_vnet_lpush, curcpu,	\
-		       saved_vnet, saved_vnet_lpush);
+		vnet_log_recursion(saved_vnet, saved_vnet_lpush, __LINE__);
 
 #define	CURVNET_SET(arg)	CURVNET_SET_VERBOSE(arg)
  



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002040755.o147tgXS053773>