From 5392bf8aeb2e3f1af3f963e0cf6c80e281355039 Mon Sep 17 00:00:00 2001 From: ozaki-r Date: Thu, 3 Sep 2015 02:04:31 +0000 Subject: [PATCH] Add refcnt constraint checks for debugging It's useful to know where the constraint is violated (by extra rtfree). It's enabled only if DEBUG because it's heavy (O(n)). --- sys/net/route.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/sys/net/route.c b/sys/net/route.c index 3979bf593cc6..1d27ffb63ccd 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $NetBSD: route.c,v 1.150 2015/08/31 06:25:15 ozaki-r Exp $ */ +/* $NetBSD: route.c,v 1.151 2015/09/03 02:04:31 ozaki-r Exp $ */ /*- * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. @@ -96,7 +96,7 @@ #endif #include -__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.150 2015/08/31 06:25:15 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.151 2015/09/03 02:04:31 ozaki-r Exp $"); #include #ifdef RTFLUSH_DEBUG @@ -410,6 +410,26 @@ rtalloc1(const struct sockaddr *dst, int report) return newrt; } +#ifdef DEBUG +/* + * Check the following constraint for each rtcache: + * if a rtcache holds a rtentry, the rtentry's refcnt is more than zero, + * i.e., the rtentry should be referenced at least by the rtcache. + */ +static void +rtcache_check_rtrefcnt(int family) +{ + struct domain *dom = pffinddomain(family); + struct route *ro; + + if (dom == NULL) + return; + + LIST_FOREACH(ro, &dom->dom_rtcache, ro_rtcache_next) + KDASSERT(ro->_ro_rt == NULL || ro->_ro_rt->rt_refcnt > 0); +} +#endif + void rtfree(struct rtentry *rt) { @@ -419,6 +439,10 @@ rtfree(struct rtentry *rt) KASSERT(rt->rt_refcnt > 0); rt->rt_refcnt--; +#ifdef DEBUG + if (rt_getkey(rt) != NULL) + rtcache_check_rtrefcnt(rt_getkey(rt)->sa_family); +#endif if (rt->rt_refcnt == 0 && (rt->rt_flags & RTF_UP) == 0) { rt_assert_inactive(rt); rttrash--;