diff options
author | sam <sam@FreeBSD.org> | 2003-12-20 18:32:48 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2003-12-20 18:32:48 +0000 |
commit | 2a76f369023e788a7c5ccb1d06a260ac3cb0c6f1 (patch) | |
tree | 1f696b9029d105e6f415d5cbcedfc0039836d49d /sys/netinet/ip_mroute.c | |
parent | 3ff50058b8f1c4e96bc4e8483146029f3f583331 (diff) | |
download | FreeBSD-src-2a76f369023e788a7c5ccb1d06a260ac3cb0c6f1.zip FreeBSD-src-2a76f369023e788a7c5ccb1d06a260ac3cb0c6f1.tar.gz |
o move mutex init/destroy logic to the module load/unload hooks;
otherwise they are initialized twice when the code is statically
configured in the kernel because the module load method gets
invoked before the user application calls ip_mrouter_init
o add a mutex to synchronize the module init/done operations; this
sort of was done using the value of ip_mroute but X_ip_mrouter_done
sets it to NULL very early on which can lead to a race against
ip_mrouter_init--using the additional mutex means this is safe now
o don't call ip_mrouter_reset from ip_mrouter_init; this now happens
once at module load and X_ip_mrouter_done does the appropriate
cleanup work to insure the data structures are in a consistent
state so that a subsequent init operation inherits good state
Reviewed by: juli
Diffstat (limited to 'sys/netinet/ip_mroute.c')
-rw-r--r-- | sys/netinet/ip_mroute.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index 447cc27..83f4aa3 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -588,8 +588,6 @@ static void ip_mrouter_reset(void) { bzero((caddr_t)mfctable, sizeof(mfctable)); - MFC_LOCK_INIT(); - VIF_LOCK_INIT(); bzero((caddr_t)nexpire, sizeof(nexpire)); pim_assert = 0; @@ -605,6 +603,8 @@ ip_mrouter_reset(void) callout_init(&tbf_reprocess_ch, CALLOUT_MPSAFE); } +static struct mtx mrouter_mtx; /* used to synch init/done work */ + /* * Enable multicast routing */ @@ -621,10 +621,12 @@ ip_mrouter_init(struct socket *so, int version) if (version != 1) return ENOPROTOOPT; - if (ip_mrouter != NULL) - return EADDRINUSE; + mtx_lock(&mrouter_mtx); - ip_mrouter_reset(); + if (ip_mrouter != NULL) { + mtx_unlock(&mrouter_mtx); + return EADDRINUSE; + } callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL); @@ -634,6 +636,8 @@ ip_mrouter_init(struct socket *so, int version) ip_mrouter = so; + mtx_unlock(&mrouter_mtx); + if (mrtdebug) log(LOG_DEBUG, "ip_mrouter_init\n"); @@ -653,6 +657,13 @@ X_ip_mrouter_done(void) struct mfc *rt; struct rtdetq *rte; + mtx_lock(&mrouter_mtx); + + if (ip_mrouter == NULL) { + mtx_unlock(&mrouter_mtx); + return EINVAL; + } + /* * Detach/disable hooks to the reset of the system. */ @@ -690,7 +701,7 @@ X_ip_mrouter_done(void) bzero((caddr_t)viftable, sizeof(viftable)); numvifs = 0; pim_assert = 0; - VIF_LOCK_DESTROY(); + VIF_UNLOCK(); /* * Free all multicast forwarding cache entries. @@ -717,9 +728,10 @@ X_ip_mrouter_done(void) } } bzero((caddr_t)mfctable, sizeof(mfctable)); + bzero((caddr_t)nexpire, sizeof(nexpire)); bw_upcalls_n = 0; bzero(bw_meter_timers, sizeof(bw_meter_timers)); - MFC_LOCK_DESTROY(); + MFC_UNLOCK(); /* * Reset de-encapsulation cache @@ -730,6 +742,8 @@ X_ip_mrouter_done(void) reg_vif_num = VIFI_INVALID; #endif + mtx_unlock(&mrouter_mtx); + if (mrtdebug) log(LOG_DEBUG, "ip_mrouter_done\n"); @@ -3358,13 +3372,12 @@ pim_input_to_daemon: static int ip_mroute_modevent(module_t mod, int type, void *unused) { - int s; - switch (type) { case MOD_LOAD: - s = splnet(); + mtx_init(&mrouter_mtx, "mrouter initialization", NULL, MTX_DEF); + MFC_LOCK_INIT(); + VIF_LOCK_INIT(); ip_mrouter_reset(); - /* XXX synchronize setup */ ip_mcast_src = X_ip_mcast_src; ip_mforward = X_ip_mforward; ip_mrouter_done = X_ip_mrouter_done; @@ -3400,6 +3413,9 @@ ip_mroute_modevent(module_t mod, int type, void *unused) legal_vif_num = NULL; mrt_ioctl = NULL; rsvp_input_p = NULL; + VIF_LOCK_DESTROY(); + MFC_LOCK_DESTROY(); + mtx_destroy(&mrouter_mtx); break; } return 0; |