diff options
author | Matt Macy <mmacy@FreeBSD.org> | 2018-05-29 00:53:53 +0000 |
---|---|---|
committer | Matt Macy <mmacy@FreeBSD.org> | 2018-05-29 00:53:53 +0000 |
commit | 1ebec5faf41f65a793b4f4217d7a67125c877510 (patch) | |
tree | 03d65f0506109173c2c435a4477f918c522ba37d /sys/net/if.c | |
parent | 20c44ba36bb677af339a0c1ddbee70b8a34e159a (diff) | |
download | src-1ebec5faf41f65a793b4f4217d7a67125c877510.tar.gz src-1ebec5faf41f65a793b4f4217d7a67125c877510.zip |
route: fix missed ref adds
- ensure that we bump the ifa ref whenever we add a reference
- defer freeing epoch protected references until after the if_purgaddrs
loop
Notes
Notes:
svn path=/head/; revision=334305
Diffstat (limited to 'sys/net/if.c')
-rw-r--r-- | sys/net/if.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 7cecaf73fe34..37ed26092c0c 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -967,7 +967,7 @@ if_purgeaddrs(struct ifnet *ifp) { struct ifaddr *ifa, *next; - /* XXX cannot hold IF_ADDR_WLOCK over called functions. */ + NET_EPOCH_ENTER(); CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) { if (ifa->ifa_addr->sa_family == AF_LINK) continue; @@ -997,6 +997,7 @@ if_purgeaddrs(struct ifnet *ifp) IF_ADDR_WUNLOCK(ifp); ifa_free(ifa); } + NET_EPOCH_EXIT(); } /* @@ -2196,6 +2197,10 @@ link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) ifa = ifaof_ifpforaddr(dst, ifp); if (ifa) { oifa = rt->rt_ifa; + if (oifa != ifa) { + ifa_free(oifa); + ifa_ref(ifa); + } rt->rt_ifa = ifa; if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ifa->ifa_rtrequest(cmd, rt, info); @@ -3675,10 +3680,8 @@ if_delmulti_ifma_flags(struct ifmultiaddr *ifma, int flags) CK_STAILQ_FOREACH(oifp, &V_ifnet, if_link) if (ifp == oifp) break; - if (ifp != oifp) { - printf("%s: ifnet %p disappeared\n", __func__, ifp); + if (ifp != oifp) ifp = NULL; - } IFNET_RUNLOCK_NOSLEEP(); } #endif |