Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-8]: src/sys Pull up following revision(s) (requested by ozaki-r i...
details: https://anonhg.NetBSD.org/src/rev/38617ae8235b
branches: netbsd-8
changeset: 434390:38617ae8235b
user: snj <snj%NetBSD.org@localhost>
date: Fri Nov 17 20:24:05 2017 +0000
description:
Pull up following revision(s) (requested by ozaki-r in ticket #353):
sys/net/if_llatbl.c: 1.22
sys/net/if_llatbl.h: 1.13
sys/netinet/if_arp.c: 1.254
sys/netinet/in.c: 1.208-1.209
sys/netinet6/in6.c: 1.249-1.250
sys/netinet6/nd6.c: 1.237
Remove redundant KASSERTMSG
The function is static, has just one caller and the caller does the same check.
--
Fix a deadlock between a route update and lltable
It happens because rtalloc1 is called from lltable with holding
IF_AFDATA_WLOCK.
If a route update is in action, rtalloc1 would wait for its completion with
holding IF_AFDATA_WLOCK. At the same moment, a softint (e.g., arpintr) may try
to take IF_AFDATA_WLOCK and get stuck on it. Unfortunately the stuck softint
prevents the route update from progressing because the route update calls
psref_target_destroy that needs the softint to complete.
A resource allocation graph of the senario looks like this:
route update =(psref_target_destroy)=> softint => IF_AFDATA_WLOCK
=(rt_update_wait)=> route update
Fix the deadlock by pulling rtalloc1 out of the lltable codes inside
IF_AFDATA_WLOCK.
Note that the deadlock happens only if NET_MPSAFE is enabled.
diffstat:
sys/net/if_llatbl.c | 21 ++++++++++++++++-----
sys/net/if_llatbl.h | 9 +++++----
sys/netinet/if_arp.c | 18 ++++++++++++++----
sys/netinet/in.c | 18 +++++++-----------
sys/netinet6/in6.c | 23 ++++++-----------------
sys/netinet6/nd6.c | 11 +++++++----
6 files changed, 55 insertions(+), 45 deletions(-)
diffs (truncated from 332 to 300 lines):
diff -r 2f8383169121 -r 38617ae8235b sys/net/if_llatbl.c
--- a/sys/net/if_llatbl.c Fri Nov 17 20:20:22 2017 +0000
+++ b/sys/net/if_llatbl.c Fri Nov 17 20:24:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_llatbl.c,v 1.18.6.1 2017/07/07 13:57:26 martin Exp $ */
+/* $NetBSD: if_llatbl.c,v 1.18.6.2 2017/11/17 20:24:05 snj Exp $ */
/*
* Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
* Copyright (c) 2004-2008 Qing Li. All rights reserved.
@@ -386,7 +386,7 @@
(ifp->if_flags & IFF_NOARP) == 0) {
#endif
IF_AFDATA_WLOCK(ifp);
- la = lla_create(lt, 0, (struct sockaddr *)dst);
+ la = lla_create(lt, 0, (struct sockaddr *)dst, NULL /* XXX */);
IF_AFDATA_WUNLOCK(ifp);
}
@@ -656,7 +656,12 @@
error = 0;
switch (rtm_type) {
- case RTM_ADD:
+ case RTM_ADD: {
+ struct rtentry *rt;
+
+ /* Never call rtalloc1 with IF_AFDATA_WLOCK */
+ rt = rtalloc1(dst, 0);
+
/* Add static LLE */
IF_AFDATA_WLOCK(ifp);
lle = lla_lookup(llt, 0, dst);
@@ -666,15 +671,19 @@
(lle->la_flags & LLE_STATIC || lle->la_expire == 0)) {
LLE_RUNLOCK(lle);
IF_AFDATA_WUNLOCK(ifp);
+ if (rt != NULL)
+ rt_unref(rt);
error = EEXIST;
goto out;
}
if (lle != NULL)
LLE_RUNLOCK(lle);
- lle = lla_create(llt, 0, dst);
+ lle = lla_create(llt, 0, dst, rt);
if (lle == NULL) {
IF_AFDATA_WUNLOCK(ifp);
+ if (rt != NULL)
+ rt_unref(rt);
error = ENOMEM;
goto out;
}
@@ -703,6 +712,8 @@
laflags = lle->la_flags;
LLE_WUNLOCK(lle);
IF_AFDATA_WUNLOCK(ifp);
+ if (rt != NULL)
+ rt_unref(rt);
#if defined(INET) && NARP > 0
/* gratuitous ARP */
if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) {
@@ -721,8 +732,8 @@
#else
(void)laflags;
#endif
-
break;
+ }
case RTM_DELETE:
IF_AFDATA_WLOCK(ifp);
diff -r 2f8383169121 -r 38617ae8235b sys/net/if_llatbl.h
--- a/sys/net/if_llatbl.h Fri Nov 17 20:20:22 2017 +0000
+++ b/sys/net/if_llatbl.h Fri Nov 17 20:24:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_llatbl.h,v 1.10.8.1 2017/07/07 13:57:26 martin Exp $ */
+/* $NetBSD: if_llatbl.h,v 1.10.8.2 2017/11/17 20:24:05 snj Exp $ */
/*
* Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
* Copyright (c) 2004-2008 Qing Li. All rights reserved.
@@ -190,7 +190,7 @@
typedef struct llentry *(llt_lookup_t)(struct lltable *, u_int flags,
const struct sockaddr *l3addr);
typedef struct llentry *(llt_create_t)(struct lltable *, u_int flags,
- const struct sockaddr *l3addr);
+ const struct sockaddr *l3addr, const struct rtentry *);
typedef int (llt_delete_t)(struct lltable *, u_int flags,
const struct sockaddr *l3addr);
typedef void (llt_prefix_free_t)(struct lltable *,
@@ -297,10 +297,11 @@
}
static __inline struct llentry *
-lla_create(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
+lla_create(struct lltable *llt, u_int flags, const struct sockaddr *l3addr,
+ const struct rtentry *rt)
{
- return (llt->llt_create(llt, flags, l3addr));
+ return (llt->llt_create(llt, flags, l3addr, rt));
}
static __inline int
diff -r 2f8383169121 -r 38617ae8235b sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c Fri Nov 17 20:20:22 2017 +0000
+++ b/sys/netinet/if_arp.c Fri Nov 17 20:24:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_arp.c,v 1.250.2.2 2017/07/07 13:57:27 martin Exp $ */
+/* $NetBSD: if_arp.c,v 1.250.2.3 2017/11/17 20:24:05 snj Exp $ */
/*-
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.250.2.2 2017/07/07 13:57:27 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.250.2.3 2017/11/17 20:24:05 snj Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -754,10 +754,15 @@
}
#undef _IFF_NOARP
if (la == NULL) {
+ struct rtentry *_rt;
+
create_lookup = "create";
+ _rt = rtalloc1(dst, 0);
IF_AFDATA_WLOCK(ifp);
- la = lla_create(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
+ la = lla_create(LLTABLE(ifp), LLE_EXCLUSIVE, dst, _rt);
IF_AFDATA_WUNLOCK(ifp);
+ if (_rt != NULL)
+ rt_unref(_rt);
if (la == NULL)
ARP_STATINC(ARP_STAT_ALLOCFAIL);
else {
@@ -1452,9 +1457,14 @@
la = arplookup(ifp, m, addr, sa, wlock);
if (la == NULL) {
+ struct rtentry *rt;
+
+ rt = rtalloc1(sa, 0);
IF_AFDATA_WLOCK(ifp);
- la = lla_create(LLTABLE(ifp), flags, sa);
+ la = lla_create(LLTABLE(ifp), flags, sa, rt);
IF_AFDATA_WUNLOCK(ifp);
+ if (rt != NULL)
+ rt_unref(rt);
if (la != NULL)
arp_init_llentry(ifp, la);
diff -r 2f8383169121 -r 38617ae8235b sys/netinet/in.c
--- a/sys/netinet/in.c Fri Nov 17 20:20:22 2017 +0000
+++ b/sys/netinet/in.c Fri Nov 17 20:24:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: in.c,v 1.203.2.1 2017/07/07 13:57:27 martin Exp $ */
+/* $NetBSD: in.c,v 1.203.2.2 2017/11/17 20:24:05 snj Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.203.2.1 2017/07/07 13:57:27 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.203.2.2 2017/11/17 20:24:05 snj Exp $");
#include "arp.h"
@@ -1938,15 +1938,11 @@
}
static int
-in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
+in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr,
+ const struct rtentry *rt)
{
- struct rtentry *rt;
int error = EINVAL;
- KASSERTMSG(l3addr->sa_family == AF_INET,
- "sin_family %d", l3addr->sa_family);
-
- rt = rtalloc1(l3addr, 0);
if (rt == NULL)
return error;
@@ -2007,7 +2003,6 @@
error = 0;
error:
- rt_unref(rt);
return error;
}
@@ -2098,7 +2093,8 @@
}
static struct llentry *
-in_lltable_create(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
+in_lltable_create(struct lltable *llt, u_int flags, const struct sockaddr *l3addr,
+ const struct rtentry *rt)
{
const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr;
struct ifnet *ifp = llt->llt_ifp;
@@ -2123,7 +2119,7 @@
* verify this.
*/
if (!(flags & LLE_IFADDR) &&
- in_lltable_rtcheck(ifp, flags, l3addr) != 0)
+ in_lltable_rtcheck(ifp, flags, l3addr, rt) != 0)
return (NULL);
lle = in_lltable_new(sin->sin_addr, flags);
diff -r 2f8383169121 -r 38617ae8235b sys/netinet6/in6.c
--- a/sys/netinet6/in6.c Fri Nov 17 20:20:22 2017 +0000
+++ b/sys/netinet6/in6.c Fri Nov 17 20:24:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: in6.c,v 1.245.2.1 2017/07/07 13:57:26 martin Exp $ */
+/* $NetBSD: in6.c,v 1.245.2.2 2017/11/17 20:24:05 snj Exp $ */
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.245.2.1 2017/07/07 13:57:26 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.245.2.2 2017/11/17 20:24:05 snj Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -2458,17 +2458,11 @@
}
static int
-in6_lltable_rtcheck(struct ifnet *ifp,
- u_int flags,
- const struct sockaddr *l3addr)
+in6_lltable_rtcheck(struct ifnet *ifp, u_int flags,
+ const struct sockaddr *l3addr, const struct rtentry *rt)
{
- struct rtentry *rt;
char ip6buf[INET6_ADDRSTRLEN];
- KASSERTMSG(l3addr->sa_family == AF_INET6,
- "sin_family %d", l3addr->sa_family);
-
- rt = rtalloc1(l3addr, 0);
if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
int s;
struct ifaddr *ifa;
@@ -2481,19 +2475,14 @@
ifa = ifaof_ifpforaddr(l3addr, ifp);
if (ifa != NULL) {
pserialize_read_exit(s);
- if (rt != NULL)
- rt_unref(rt);
return 0;
}
pserialize_read_exit(s);
log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
IN6_PRINT(ip6buf,
&((const struct sockaddr_in6 *)l3addr)->sin6_addr));
- if (rt != NULL)
- rt_unref(rt);
return EINVAL;
}
- rt_unref(rt);
return 0;
}
@@ -2585,7 +2574,7 @@
static struct llentry *
in6_lltable_create(struct lltable *llt, u_int flags,
- const struct sockaddr *l3addr)
+ const struct sockaddr *l3addr, const struct rtentry *rt)
{
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
struct ifnet *ifp = llt->llt_ifp;
@@ -2608,7 +2597,7 @@
* verify this.
*/
if (!(flags & LLE_IFADDR) &&
- in6_lltable_rtcheck(ifp, flags, l3addr) != 0)
+ in6_lltable_rtcheck(ifp, flags, l3addr, rt) != 0)
return NULL;
lle = in6_lltable_new(&sin6->sin6_addr, flags);
diff -r 2f8383169121 -r 38617ae8235b sys/netinet6/nd6.c
--- a/sys/netinet6/nd6.c Fri Nov 17 20:20:22 2017 +0000
+++ b/sys/netinet6/nd6.c Fri Nov 17 20:24:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6.c,v 1.232.2.2 2017/10/24 09:00:22 snj Exp $ */
+/* $NetBSD: nd6.c,v 1.232.2.3 2017/11/17 20:24:05 snj Exp $ */
Home |
Main Index |
Thread Index |
Old Index