diff --git a/sys/net/if.c b/sys/net/if.c --- a/sys/net/if.c +++ b/sys/net/if.c @@ -359,7 +359,8 @@ ifp = ifnet_byindex(idx); if (ifp == NULL || (ifp->if_flags & IFF_DYING)) return (NULL); - if_ref(ifp); + if (!if_try_ref(ifp)) + return (NULL); return (ifp); } @@ -738,9 +739,18 @@ void if_ref(struct ifnet *ifp) { + u_int old; /* We don't assert the ifnet list lock here, but arguably should. */ - refcount_acquire(&ifp->if_refcount); + old = refcount_acquire(&ifp->if_refcount); + KASSERT(old > 0, ("%s: ifp %p has 0 refs", __func__, ifp)); +} + +bool +if_try_ref(struct ifnet *ifp) +{ + NET_EPOCH_ASSERT(); + return (refcount_acquire_if_not_zero(&ifp->if_refcount)); } void diff --git a/sys/net/if_var.h b/sys/net/if_var.h --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -661,6 +661,7 @@ int if_printf(struct ifnet *, const char *, ...) __printflike(2, 3); void if_ref(struct ifnet *); void if_rele(struct ifnet *); +bool if_try_ref(struct ifnet *); int if_setlladdr(struct ifnet *, const u_char *, int); int if_tunnel_check_nesting(struct ifnet *, struct mbuf *, uint32_t, int); void if_up(struct ifnet *);