aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/if.c14
-rw-r--r--sys/net/if_var.h1
2 files changed, 13 insertions, 2 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 948be6876b65..9d5e9e26b4bb 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -359,7 +359,8 @@ ifnet_byindex_ref(u_short idx)
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 @@ if_free(struct ifnet *ifp)
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
index 291a7781d73c..33a737880a8d 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -661,6 +661,7 @@ void if_link_state_change(struct ifnet *, int);
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 *);