svn commit: r213225 - in head/sys: netinet netinet6
Xin LI
delphij at FreeBSD.org
Mon Sep 27 19:26:57 UTC 2010
Author: delphij
Date: Mon Sep 27 19:26:56 2010
New Revision: 213225
URL: http://svn.freebsd.org/changeset/base/213225
Log:
Add a bandaid for a long-standing race condition during route entry
un-expiring.
The previous version of code have no locking when testing rt_refcnt.
The result of the lack of locking may result in a condition where
a routing entry have a reference count but at the same time have
RTPRF_OURS bit set and an expiration timer. These would eventually
lead to a panic:
panic: rtqkill route really not free
When the system have ICMP redirects accepted from local gateway
in a moderate frequency, for instance.
Commit this workaround for now until we have some better solution.
PR: kern/149804
Reviewed by: bz
Tested by: Zhao Xin, Pete French
MFC after: 2 weeks
Modified:
head/sys/netinet/in_rmx.c
head/sys/netinet6/in6_rmx.c
Modified: head/sys/netinet/in_rmx.c
==============================================================================
--- head/sys/netinet/in_rmx.c Mon Sep 27 19:03:18 2010 (r213224)
+++ head/sys/netinet/in_rmx.c Mon Sep 27 19:26:56 2010 (r213225)
@@ -121,12 +121,13 @@ in_matroute(void *v_arg, struct radix_no
struct radix_node *rn = rn_match(v_arg, head);
struct rtentry *rt = (struct rtentry *)rn;
- /*XXX locking? */
- if (rt && rt->rt_refcnt == 0) { /* this is first reference */
+ if (rt) {
+ RT_LOCK(rt);
if (rt->rt_flags & RTPRF_OURS) {
rt->rt_flags &= ~RTPRF_OURS;
rt->rt_rmx.rmx_expire = 0;
}
+ RT_UNLOCK(rt);
}
return rn;
}
Modified: head/sys/netinet6/in6_rmx.c
==============================================================================
--- head/sys/netinet6/in6_rmx.c Mon Sep 27 19:03:18 2010 (r213224)
+++ head/sys/netinet6/in6_rmx.c Mon Sep 27 19:26:56 2010 (r213225)
@@ -193,11 +193,13 @@ in6_matroute(void *v_arg, struct radix_n
struct radix_node *rn = rn_match(v_arg, head);
struct rtentry *rt = (struct rtentry *)rn;
- if (rt && rt->rt_refcnt == 0) { /* this is first reference */
+ if (rt) {
+ RT_LOCK(rt);
if (rt->rt_flags & RTPRF_OURS) {
rt->rt_flags &= ~RTPRF_OURS;
rt->rt_rmx.rmx_expire = 0;
}
+ RT_UNLOCK(rt);
}
return rn;
}
More information about the svn-src-head
mailing list