aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/ip_carp.c
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2015-04-06 15:31:19 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2015-04-06 15:31:19 +0000
commit93d4534cdc3e28d17925c723d2b50987373a1047 (patch)
treeb33ca315ad4344fe6d3a4486bdccb586fe40623b /sys/netinet/ip_carp.c
parent5d9359578951e7d657021353ab09a71cdbad0cbc (diff)
downloadsrc-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.c8
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;