Fix rib_subscribe() waitok flag by performing allocation outside epoch.
Make in6_inithead() use rib_subscribe with waitok to achieve reliable subscription allocation. Reviewed by: glebius
This commit is contained in:
parent
fc254a2e4a
commit
9a00f6d067
@ -743,26 +743,26 @@ rib_notify(struct rib_head *rnh, enum rib_subscription_type type,
|
||||
/*
|
||||
* Subscribe for the changes in the routing table specified by @fibnum and
|
||||
* @family.
|
||||
* Needs to be run in network epoch.
|
||||
*
|
||||
* Returns pointer to the subscription structure on success.
|
||||
*/
|
||||
struct rib_subscription *
|
||||
rib_subscribe(uint32_t fibnum, int family, rib_subscription_cb_t *f, void *arg,
|
||||
enum rib_subscription_type type, int waitok)
|
||||
enum rib_subscription_type type, bool waitok)
|
||||
{
|
||||
struct rib_head *rnh;
|
||||
struct rib_subscription *rs;
|
||||
struct epoch_tracker et;
|
||||
int flags = M_ZERO | (waitok ? M_WAITOK : 0);
|
||||
|
||||
NET_EPOCH_ASSERT();
|
||||
KASSERT((fibnum < rt_numfibs), ("%s: bad fibnum", __func__));
|
||||
rnh = rt_tables_get_rnh(fibnum, family);
|
||||
|
||||
rs = malloc(sizeof(struct rib_subscription), M_RTABLE, flags);
|
||||
if (rs == NULL)
|
||||
return (NULL);
|
||||
|
||||
NET_EPOCH_ENTER(et);
|
||||
KASSERT((fibnum < rt_numfibs), ("%s: bad fibnum", __func__));
|
||||
rnh = rt_tables_get_rnh(fibnum, family);
|
||||
|
||||
rs->func = f;
|
||||
rs->arg = arg;
|
||||
rs->type = type;
|
||||
@ -770,6 +770,7 @@ rib_subscribe(uint32_t fibnum, int family, rib_subscription_cb_t *f, void *arg,
|
||||
RIB_WLOCK(rnh);
|
||||
CK_STAILQ_INSERT_TAIL(&rnh->rnh_subscribers, rs, next);
|
||||
RIB_WUNLOCK(rnh);
|
||||
NET_EPOCH_EXIT(et);
|
||||
|
||||
return (rs);
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ typedef void rib_subscription_cb_t(struct rib_head *rnh, struct rib_cmd_info *rc
|
||||
|
||||
struct rib_subscription *rib_subscribe(uint32_t fibnum, int family,
|
||||
rib_subscription_cb_t *f, void *arg, enum rib_subscription_type type,
|
||||
int waitok);
|
||||
bool waitok);
|
||||
int rib_unsibscribe(uint32_t fibnum, int family, struct rib_subscription *rs);
|
||||
|
||||
#endif
|
||||
|
@ -150,8 +150,8 @@ rib6_preadd(u_int fibnum, const struct sockaddr *addr, const struct sockaddr *ma
|
||||
int
|
||||
in6_inithead(void **head, int off, u_int fibnum)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct rib_head *rh;
|
||||
struct rib_subscription *rs;
|
||||
|
||||
rh = rt_table_init(offsetof(struct sockaddr_in6, sin6_addr) << 3,
|
||||
AF_INET6, fibnum);
|
||||
@ -164,12 +164,9 @@ in6_inithead(void **head, int off, u_int fibnum)
|
||||
#endif
|
||||
*head = (void *)rh;
|
||||
|
||||
NET_EPOCH_ENTER(et);
|
||||
if (rib_subscribe(fibnum, AF_INET6, nd6_subscription_cb, NULL,
|
||||
RIB_NOTIFY_IMMEDIATE, M_NOWAIT) == NULL)
|
||||
log(LOG_ERR, "in6_inithead(): unable to subscribe to fib %u\n",
|
||||
fibnum);
|
||||
NET_EPOCH_EXIT(et);
|
||||
rs = rib_subscribe(fibnum, AF_INET6, nd6_subscription_cb, NULL,
|
||||
RIB_NOTIFY_IMMEDIATE, true);
|
||||
KASSERT(rs != NULL, ("Unable to subscribe to fib %u\n", fibnum));
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user