aboutsummaryrefslogtreecommitdiff
path: root/sys/net/vnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/vnet.c')
-rw-r--r--sys/net/vnet.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/sys/net/vnet.c b/sys/net/vnet.c
index 298ffb28457f..26635db0caec 100644
--- a/sys/net/vnet.c
+++ b/sys/net/vnet.c
@@ -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 */