Add ifa_try_ref() to simplify ifa handling inside epoch.
More and more code migrates from lock-based protection to the NET_EPOCH umbrella. It requires some logic changes, including, notably, refcount handling. When we have an `ifa` pointer and we're running inside epoch we're guaranteed that this pointer will not be freed. However, the following case can still happen: * in thread 1 we drop to 0 refcount for ifa and schedule its deletion. * in thread 2 we use this ifa and reference it * destroy callout kicks in * unhappy user reports bug To address it, new `ifa_try_ref()` function is added, allowing to return failure when we try to reference `ifa` with 0 refcount. Additionally, existing `ifa_ref()` is enforced with `KASSERT` to provide cleaner error in such scenarious. Reviewed By: rstone, donner Differential Revision: https://reviews.freebsd.org/D28639 MFC after: 1 week
This commit is contained in:
+11
-1
@@ -1857,8 +1857,18 @@ ifa_alloc(size_t size, int flags)
|
|||||||
void
|
void
|
||||||
ifa_ref(struct ifaddr *ifa)
|
ifa_ref(struct ifaddr *ifa)
|
||||||
{
|
{
|
||||||
|
u_int old;
|
||||||
|
|
||||||
refcount_acquire(&ifa->ifa_refcnt);
|
old = refcount_acquire(&ifa->ifa_refcnt);
|
||||||
|
KASSERT(old > 0, ("%s: ifa %p has 0 refs", __func__, ifa));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ifa_try_ref(struct ifaddr *ifa)
|
||||||
|
{
|
||||||
|
|
||||||
|
NET_EPOCH_ASSERT();
|
||||||
|
return (refcount_acquire_if_not_zero(&ifa->ifa_refcnt));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -577,6 +577,7 @@ struct ifaddr {
|
|||||||
struct ifaddr * ifa_alloc(size_t size, int flags);
|
struct ifaddr * ifa_alloc(size_t size, int flags);
|
||||||
void ifa_free(struct ifaddr *ifa);
|
void ifa_free(struct ifaddr *ifa);
|
||||||
void ifa_ref(struct ifaddr *ifa);
|
void ifa_ref(struct ifaddr *ifa);
|
||||||
|
int ifa_try_ref(struct ifaddr *ifa);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Multicast address structure. This is analogous to the ifaddr
|
* Multicast address structure. This is analogous to the ifaddr
|
||||||
|
|||||||
Reference in New Issue
Block a user