diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2015-04-06 15:31:19 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2015-04-06 15:31:19 +0000 |
commit | 93d4534cdc3e28d17925c723d2b50987373a1047 (patch) | |
tree | b33ca315ad4344fe6d3a4486bdccb586fe40623b /sys/netinet/ip_carp.c | |
parent | 5d9359578951e7d657021353ab09a71cdbad0cbc (diff) | |
download | src-93d4534cdc3e28d17925c723d2b50987373a1047.tar.gz src-93d4534cdc3e28d17925c723d2b50987373a1047.zip |
Add sleepable lock to protect at least against two parallel SIOCSVHs.
Sponsored by: Nginx, Inc.
Notes
Notes:
svn path=/head/; revision=281152
Diffstat (limited to 'sys/netinet/ip_carp.c')
-rw-r--r-- | sys/netinet/ip_carp.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 20962b03d83c..ebfe8fd82b0b 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -180,9 +180,6 @@ static int proto_reg[] = {-1, -1}; * * Known issues with locking: * - * - There is no protection for races between two ioctl() requests, - * neither SIOCSVH, nor SIOCAIFADDR & SIOCAIFADDR_IN6. I think that all - * interface ioctl()s should be serialized right in net/if.c. * - Sending ad, we put the pointer to the softc in an mtag, and no reference * counting is done on the softc. * - On module unload we may race (?) with packet processing thread @@ -321,6 +318,7 @@ static void carp_demote_adj(int, char *); static LIST_HEAD(, carp_softc) carp_list; static struct mtx carp_mtx; +static struct sx carp_sx; static struct task carp_sendall_task = TASK_INITIALIZER(0, carp_send_ad_all, NULL); @@ -1650,6 +1648,7 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td) goto out; } + sx_xlock(&carp_sx); switch (cmd) { case SIOCSVH: if ((error = priv_check(td, PRIV_NETINET_CARP))) @@ -1780,6 +1779,7 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td) default: error = EINVAL; } + sx_xunlock(&carp_sx); out: if (locked) @@ -2099,6 +2099,7 @@ carp_mod_cleanup(void) mtx_unlock(&carp_mtx); taskqueue_drain(taskqueue_swi, &carp_sendall_task); mtx_destroy(&carp_mtx); + sx_destroy(&carp_sx); } static int @@ -2107,6 +2108,7 @@ carp_mod_load(void) int err; mtx_init(&carp_mtx, "carp_mtx", NULL, MTX_DEF); + sx_init(&carp_sx, "carp_sx"); LIST_INIT(&carp_list); carp_get_vhid_p = carp_get_vhid; carp_forus_p = carp_forus; |