Module Name: src
Committed By: ozaki-r
Date: Tue Nov 15 01:50:06 UTC 2016
Modified Files:
src/sys/net: if.c radix.c radix.h route.c route.h rtbl.c
src/sys/netinet6: nd6_rtr.c
src/sys/nfs: nfs_boot.c
Log Message:
Don't use rt_walktree to delete routes
Some functions use rt_walktree to scan the routing table and delete
matched routes. However, we shouldn't use rt_walktree to delete
routes because rt_walktree is recursive to the routing table (radix
tree) and isn't friendly to MP-ification. rt_walktree allows a caller
to pass a callback function to delete an matched entry. The callback
function is called from an API of the radix tree (rn_walktree) but
also calls an API of the radix tree to delete an entry.
This change adds a new API of the radix tree, rn_search_matched,
which returns a matched entry that is selected by a callback
function passed by a caller and the caller itself deletes the
entry. By using the API, we can avoid the recursive form.
To generate a diff of this commit:
cvs rdiff -u -r1.361 -r1.362 src/sys/net/if.c
cvs rdiff -u -r1.45 -r1.46 src/sys/net/radix.c
cvs rdiff -u -r1.22 -r1.23 src/sys/net/radix.h
cvs rdiff -u -r1.181 -r1.182 src/sys/net/route.c
cvs rdiff -u -r1.106 -r1.107 src/sys/net/route.h
cvs rdiff -u -r1.3 -r1.4 src/sys/net/rtbl.c
cvs rdiff -u -r1.119 -r1.120 src/sys/netinet6/nd6_rtr.c
cvs rdiff -u -r1.86 -r1.87 src/sys/nfs/nfs_boot.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/if.c
diff -u src/sys/net/if.c:1.361 src/sys/net/if.c:1.362
--- src/sys/net/if.c:1.361 Sat Nov 5 23:30:22 2016
+++ src/sys/net/if.c Tue Nov 15 01:50:06 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if.c,v 1.361 2016/11/05 23:30:22 pgoyette Exp $ */
+/* $NetBSD: if.c,v 1.362 2016/11/15 01:50:06 ozaki-r Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.361 2016/11/05 23:30:22 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.362 2016/11/15 01:50:06 ozaki-r Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -185,7 +185,7 @@ int ifqmaxlen = IFQ_MAXLEN;
struct psref_class *ifa_psref_class __read_mostly;
-static int if_rt_walktree(struct rtentry *, void *);
+static int if_delroute_matcher(struct rtentry *, void *);
static struct if_clone *if_clone_lookup(const char *, int *);
@@ -1279,11 +1279,9 @@ again:
if_free_sadl(ifp);
- /* Walk the routing table looking for stragglers. */
- for (i = 0; i <= AF_MAX; i++) {
- while (rt_walktree(i, if_rt_walktree, ifp) == ERESTART)
- continue;
- }
+ /* Delete stray routes from the routing table. */
+ for (i = 0; i <= AF_MAX; i++)
+ rt_delete_matched_entries(i, if_delroute_matcher, ifp);
DOMAIN_FOREACH(dp) {
if (dp->dom_ifdetach != NULL && ifp->if_afdata[dp->dom_family])
@@ -1403,28 +1401,14 @@ if_detach_queues(struct ifnet *ifp, stru
* ifnet.
*/
static int
-if_rt_walktree(struct rtentry *rt, void *v)
+if_delroute_matcher(struct rtentry *rt, void *v)
{
struct ifnet *ifp = (struct ifnet *)v;
- int error;
- struct rtentry *retrt;
- if (rt->rt_ifp != ifp)
+ if (rt->rt_ifp == ifp)
+ return 1;
+ else
return 0;
-
- /* Delete the entry. */
- error = rtrequest(RTM_DELETE, rt_getkey(rt), rt->rt_gateway,
- rt_mask(rt), rt->rt_flags, &retrt);
- if (error == 0) {
- KASSERT(retrt == rt);
- KASSERT((retrt->rt_flags & RTF_UP) == 0);
- retrt->rt_ifp = NULL;
- rtfree(retrt);
- } else {
- printf("%s: warning: unable to delete rtentry @ %p, "
- "error = %d\n", ifp->if_xname, rt, error);
- }
- return ERESTART;
}
/*
Index: src/sys/net/radix.c
diff -u src/sys/net/radix.c:1.45 src/sys/net/radix.c:1.46
--- src/sys/net/radix.c:1.45 Mon Aug 24 22:21:26 2015
+++ src/sys/net/radix.c Tue Nov 15 01:50:06 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: radix.c,v 1.45 2015/08/24 22:21:26 pooka Exp $ */
+/* $NetBSD: radix.c,v 1.46 2016/11/15 01:50:06 ozaki-r Exp $ */
/*
* Copyright (c) 1988, 1989, 1993
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: radix.c,v 1.45 2015/08/24 22:21:26 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: radix.c,v 1.46 2016/11/15 01:50:06 ozaki-r Exp $");
#ifndef _NET_RADIX_H_
#include <sys/param.h>
@@ -1005,6 +1005,37 @@ rn_walktree(
/* NOTREACHED */
}
+struct radix_node *
+rn_search_matched(struct radix_node_head *h,
+ int (*matcher)(struct radix_node *, void *), void *w)
+{
+ bool matched;
+ struct radix_node *base, *next, *rn;
+ /*
+ * This gets complicated because we may delete the node
+ * while applying the function f to it, so we need to calculate
+ * the successor node in advance.
+ */
+ rn = rn_walkfirst(h->rnh_treetop, NULL, NULL);
+ for (;;) {
+ base = rn;
+ next = rn_walknext(rn, NULL, NULL);
+ /* Process leaves */
+ while ((rn = base) != NULL) {
+ base = rn->rn_dupedkey;
+ if (!(rn->rn_flags & RNF_ROOT)) {
+ matched = (*matcher)(rn, w);
+ if (matched)
+ return rn;
+ }
+ }
+ rn = next;
+ if (rn->rn_flags & RNF_ROOT)
+ return NULL;
+ }
+ /* NOTREACHED */
+}
+
struct delayinit {
void **head;
int off;
Index: src/sys/net/radix.h
diff -u src/sys/net/radix.h:1.22 src/sys/net/radix.h:1.23
--- src/sys/net/radix.h:1.22 Wed May 27 17:46:50 2009
+++ src/sys/net/radix.h Tue Nov 15 01:50:06 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: radix.h,v 1.22 2009/05/27 17:46:50 pooka Exp $ */
+/* $NetBSD: radix.h,v 1.23 2016/11/15 01:50:06 ozaki-r Exp $ */
/*
* Copyright (c) 1988, 1989, 1993
@@ -139,6 +139,10 @@ int rn_refines(const void *, const void
int rn_walktree(struct radix_node_head *,
int (*)(struct radix_node *, void *),
void *);
+struct radix_node *
+ rn_search_matched(struct radix_node_head *,
+ int (*)(struct radix_node *, void *),
+ void *);
struct radix_node
*rn_addmask(const void *, int, int),
*rn_addroute(const void *, const void *, struct radix_node_head *,
Index: src/sys/net/route.c
diff -u src/sys/net/route.c:1.181 src/sys/net/route.c:1.182
--- src/sys/net/route.c:1.181 Tue Oct 25 02:45:09 2016
+++ src/sys/net/route.c Tue Nov 15 01:50:06 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: route.c,v 1.181 2016/10/25 02:45:09 ozaki-r Exp $ */
+/* $NetBSD: route.c,v 1.182 2016/11/15 01:50:06 ozaki-r Exp $ */
/*-
* Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
#endif
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.181 2016/10/25 02:45:09 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.182 2016/11/15 01:50:06 ozaki-r Exp $");
#include <sys/param.h>
#ifdef RTFLUSH_DEBUG
@@ -116,6 +116,7 @@ __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.
#include <sys/pool.h>
#include <sys/kauth.h>
#include <sys/workqueue.h>
+#include <sys/syslog.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -1634,6 +1635,44 @@ rt_check_reject_route(const struct rtent
return 0;
}
+void
+rt_delete_matched_entries(sa_family_t family, int (*f)(struct rtentry *, void *),
+ void *v)
+{
+
+ for (;;) {
+ int s;
+ int error;
+ struct rtentry *rt, *retrt = NULL;
+
+ s = splsoftnet();
+ rt = rtbl_search_matched_entry(family, f, v);
+ if (rt == NULL) {
+ splx(s);
+ return;
+ }
+ rt->rt_refcnt++;
+ splx(s);
+
+ error = rtrequest(RTM_DELETE, rt_getkey(rt), rt->rt_gateway,
+ rt_mask(rt), rt->rt_flags, &retrt);
+ if (error == 0) {
+ KASSERT(retrt == rt);
+ KASSERT((retrt->rt_flags & RTF_UP) == 0);
+ retrt->rt_ifp = NULL;
+ rtfree(rt);
+ rtfree(retrt);
+ } else if (error == ESRCH) {
+ /* Someone deleted the entry already. */
+ rtfree(rt);
+ } else {
+ log(LOG_ERR, "%s: unable to delete rtentry @ %p, "
+ "error = %d\n", rt->rt_ifp->if_xname, rt, error);
+ /* XXX how to treat this case? */
+ }
+ }
+}
+
#ifdef DDB
#include <machine/db_machdep.h>
Index: src/sys/net/route.h
diff -u src/sys/net/route.h:1.106 src/sys/net/route.h:1.107
--- src/sys/net/route.h:1.106 Tue Oct 25 02:45:09 2016
+++ src/sys/net/route.h Tue Nov 15 01:50:06 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: route.h,v 1.106 2016/10/25 02:45:09 ozaki-r Exp $ */
+/* $NetBSD: route.h,v 1.107 2016/11/15 01:50:06 ozaki-r Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@@ -408,6 +408,8 @@ struct sockaddr *
rt_gettag(const struct rtentry *);
int rt_check_reject_route(const struct rtentry *, const struct ifnet *);
+void rt_delete_matched_entries(sa_family_t,
+ int (*)(struct rtentry *, void *), void *);
static inline void
rt_assert_referenced(const struct rtentry *rt)
@@ -504,6 +506,9 @@ struct rtentry *
rt_matchaddr(rtbl_t *, const struct sockaddr *);
int rt_refines(const struct sockaddr *, const struct sockaddr *);
int rt_walktree(sa_family_t, int (*)(struct rtentry *, void *), void *);
+struct rtentry *
+ rtbl_search_matched_entry(sa_family_t,
+ int (*)(struct rtentry *, void *), void *);
void rtbl_init(void);
#endif /* _KERNEL */
Index: src/sys/net/rtbl.c
diff -u src/sys/net/rtbl.c:1.3 src/sys/net/rtbl.c:1.4
--- src/sys/net/rtbl.c:1.3 Mon Apr 11 09:21:18 2016
+++ src/sys/net/rtbl.c Tue Nov 15 01:50:06 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: rtbl.c,v 1.3 2016/04/11 09:21:18 ozaki-r Exp $ */
+/* $NetBSD: rtbl.c,v 1.4 2016/11/15 01:50:06 ozaki-r Exp $ */
/*-
* Copyright (c) 1998, 2008, 2011 The NetBSD Foundation, Inc.
@@ -95,7 +95,7 @@
#endif /* _KERNEL && _KERNEL_OPT */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtbl.c,v 1.3 2016/04/11 09:21:18 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtbl.c,v 1.4 2016/11/15 01:50:06 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/kmem.h>
@@ -204,6 +204,23 @@ rt_walktree(sa_family_t family, int (*f)
return rn_walktree(&t->t_rnh, rt_walktree_visitor, &rw);
}
+struct rtentry *
+rtbl_search_matched_entry(sa_family_t family,
+ int (*f)(struct rtentry *, void *), void *v)
+{
+ rtbl_t *t = rt_tables[family];
+ struct rtwalk rw;
+
+ if (t == NULL)
+ return 0;
+
+ rw.rw_f = f;
+ rw.rw_v = v;
+
+ return (struct rtentry *)
+ rn_search_matched(&t->t_rnh, rt_walktree_visitor, &rw);
+}
+
rtbl_t *
rt_gettable(sa_family_t af)
{
Index: src/sys/netinet6/nd6_rtr.c
diff -u src/sys/netinet6/nd6_rtr.c:1.119 src/sys/netinet6/nd6_rtr.c:1.120
--- src/sys/netinet6/nd6_rtr.c:1.119 Tue Aug 16 10:31:57 2016
+++ src/sys/netinet6/nd6_rtr.c Tue Nov 15 01:50:06 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6_rtr.c,v 1.119 2016/08/16 10:31:57 roy Exp $ */
+/* $NetBSD: nd6_rtr.c,v 1.120 2016/11/15 01:50:06 ozaki-r Exp $ */
/* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.119 2016/08/16 10:31:57 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.120 2016/11/15 01:50:06 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -80,7 +80,7 @@ static void in6_init_address_ltimes(stru
struct in6_addrlifetime *);
static void purge_detached(struct ifnet *);
-static int rt6_deleteroute(struct rtentry *, void *);
+static int rt6_deleteroute_matcher(struct rtentry *, void *);
extern int nd6_recalc_reachtm_interval;
@@ -2162,12 +2162,12 @@ rt6_flush(struct in6_addr *gateway, stru
return;
}
- rt_walktree(AF_INET6, rt6_deleteroute, (void *)gateway);
+ rt_delete_matched_entries(AF_INET6, rt6_deleteroute_matcher, gateway);
splx(s);
}
static int
-rt6_deleteroute(struct rtentry *rt, void *arg)
+rt6_deleteroute_matcher(struct rtentry *rt, void *arg)
{
struct in6_addr *gate = (struct in6_addr *)arg;
@@ -2192,8 +2192,7 @@ rt6_deleteroute(struct rtentry *rt, void
if ((rt->rt_flags & RTF_HOST) == 0)
return (0);
- return (rtrequest(RTM_DELETE, rt_getkey(rt), rt->rt_gateway,
- rt_mask(rt), rt->rt_flags, NULL));
+ return 1;
}
int
Index: src/sys/nfs/nfs_boot.c
diff -u src/sys/nfs/nfs_boot.c:1.86 src/sys/nfs/nfs_boot.c:1.87
--- src/sys/nfs/nfs_boot.c:1.86 Thu Jul 7 06:55:43 2016
+++ src/sys/nfs/nfs_boot.c Tue Nov 15 01:50:06 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_boot.c,v 1.86 2016/07/07 06:55:43 msaitoh Exp $ */
+/* $NetBSD: nfs_boot.c,v 1.87 2016/11/15 01:50:06 ozaki-r Exp $ */
/*-
* Copyright (c) 1995, 1997 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_boot.c,v 1.86 2016/07/07 06:55:43 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_boot.c,v 1.87 2016/11/15 01:50:06 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_nfs.h"
@@ -97,7 +97,7 @@ int nfs_boot_bootstatic = 1; /* BOOTSTAT
static int md_mount(struct sockaddr_in *mdsin, char *path,
struct nfs_args *argp, struct lwp *l);
-static int nfs_boot_delroute(struct rtentry *, void *);
+static int nfs_boot_delroute_matcher(struct rtentry *, void *);
static void nfs_boot_defrt(struct in_addr *);
static int nfs_boot_getfh(struct nfs_dlmount *ndm, struct lwp *);
@@ -559,26 +559,20 @@ nfs_boot_defrt(struct in_addr *gw_ip)
}
static int
-nfs_boot_delroute(struct rtentry *rt, void *w)
+nfs_boot_delroute_matcher(struct rtentry *rt, void *w)
{
- int error;
if ((void *)rt->rt_ifp != w)
return 0;
- error = rtrequest(RTM_DELETE, rt_getkey(rt), NULL, rt_mask(rt), 0,
- NULL);
- if (error != 0)
- printf("%s: del route, error=%d\n", __func__, error);
-
- return 0;
+ return 1;
}
void
nfs_boot_flushrt(struct ifnet *ifp)
{
- rt_walktree(AF_INET, nfs_boot_delroute, ifp);
+ rt_delete_matched_entries(AF_INET, nfs_boot_delroute_matcher, ifp);
}
/*