diff -ur v2.6.12-rc3/linux/net/ipv4/ipvs/ip_vs_conn.c linux/net/ipv4/ipvs/ip_vs_conn.c --- v2.6.12-rc3/linux/net/ipv4/ipvs/ip_vs_conn.c 2005-03-03 10:17:23.000000000 +0200 +++ linux/net/ipv4/ipvs/ip_vs_conn.c 2005-05-06 14:29:28.478350072 +0300 @@ -759,7 +759,7 @@ return 1; } - +/* Called from keventd and must protect itself from softirqs */ void ip_vs_random_dropentry(void) { int idx; @@ -775,7 +775,7 @@ /* * Lock is actually needed in this loop. */ - ct_write_lock(hash); + ct_write_lock_bh(hash); list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT)) @@ -817,7 +817,7 @@ } ct_write_lock(hash); } - ct_write_unlock(hash); + ct_write_unlock_bh(hash); } } diff -ur v2.6.12-rc3/linux/net/ipv4/ipvs/ip_vs_ctl.c linux/net/ipv4/ipvs/ip_vs_ctl.c --- v2.6.12-rc3/linux/net/ipv4/ipvs/ip_vs_ctl.c 2005-05-06 13:04:37.000000000 +0300 +++ linux/net/ipv4/ipvs/ip_vs_ctl.c 2005-05-06 14:25:18.638331528 +0300 @@ -90,7 +90,8 @@ #endif /* - * update_defense_level is called from keventd and from sysctl. + * update_defense_level is called from keventd and from sysctl, + * so it needs to protect itself from softirqs */ static void update_defense_level(void) { @@ -110,6 +111,8 @@ nomem = (availmem < sysctl_ip_vs_amemthresh); + local_bh_disable(); + /* drop_entry */ spin_lock(&__ip_vs_dropentry_lock); switch (sysctl_ip_vs_drop_entry) { @@ -206,6 +209,8 @@ if (to_change >= 0) ip_vs_protocol_timeout_change(sysctl_ip_vs_secure_tcp>1); write_unlock(&__ip_vs_securetcp_lock); + + local_bh_enable(); } @@ -1360,9 +1365,7 @@ /* Restore the correct value */ *valp = val; } else { - local_bh_disable(); update_defense_level(); - local_bh_enable(); } } return rc;