diff options
author | Simon Horman <horms@verge.net.au> | 2009-08-31 08:18:48 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2009-08-31 08:18:48 -0400 |
commit | 1e66dafc75f40a08b2addb82779987b269b4ca23 (patch) | |
tree | 8e8804cb6ffdd05e5ac7758d0559d4698026dd65 /net/netfilter | |
parent | 3993832464dd4e14a4c926583a11f0fa92c1f0f0 (diff) |
ipvs: Use atomic operations atomicly
A pointed out by Shin Hong, IPVS doesn't always use atomic operations
in an atomic manner. While this seems unlikely to be manifest in
strange behaviour, it seems appropriate to clean this up.
Cc: shin hong <hongshin@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 6 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_wrr.c | 7 |
2 files changed, 7 insertions, 6 deletions
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index b227750af752..a986ee20e128 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1259,7 +1259,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, | |||
1259 | struct ip_vs_iphdr iph; | 1259 | struct ip_vs_iphdr iph; |
1260 | struct ip_vs_protocol *pp; | 1260 | struct ip_vs_protocol *pp; |
1261 | struct ip_vs_conn *cp; | 1261 | struct ip_vs_conn *cp; |
1262 | int ret, restart, af; | 1262 | int ret, restart, af, pkts; |
1263 | 1263 | ||
1264 | af = (skb->protocol == htons(ETH_P_IP)) ? AF_INET : AF_INET6; | 1264 | af = (skb->protocol == htons(ETH_P_IP)) ? AF_INET : AF_INET6; |
1265 | 1265 | ||
@@ -1346,12 +1346,12 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, | |||
1346 | * Sync connection if it is about to close to | 1346 | * Sync connection if it is about to close to |
1347 | * encorage the standby servers to update the connections timeout | 1347 | * encorage the standby servers to update the connections timeout |
1348 | */ | 1348 | */ |
1349 | atomic_inc(&cp->in_pkts); | 1349 | pkts = atomic_add_return(1, &cp->in_pkts); |
1350 | if (af == AF_INET && | 1350 | if (af == AF_INET && |
1351 | (ip_vs_sync_state & IP_VS_STATE_MASTER) && | 1351 | (ip_vs_sync_state & IP_VS_STATE_MASTER) && |
1352 | (((cp->protocol != IPPROTO_TCP || | 1352 | (((cp->protocol != IPPROTO_TCP || |
1353 | cp->state == IP_VS_TCP_S_ESTABLISHED) && | 1353 | cp->state == IP_VS_TCP_S_ESTABLISHED) && |
1354 | (atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1] | 1354 | (pkts % sysctl_ip_vs_sync_threshold[1] |
1355 | == sysctl_ip_vs_sync_threshold[0])) || | 1355 | == sysctl_ip_vs_sync_threshold[0])) || |
1356 | ((cp->protocol == IPPROTO_TCP) && (cp->old_state != cp->state) && | 1356 | ((cp->protocol == IPPROTO_TCP) && (cp->old_state != cp->state) && |
1357 | ((cp->state == IP_VS_TCP_S_FIN_WAIT) || | 1357 | ((cp->state == IP_VS_TCP_S_FIN_WAIT) || |
diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c index 70ff82cda57d..6182e8ea0be7 100644 --- a/net/netfilter/ipvs/ip_vs_wrr.c +++ b/net/netfilter/ipvs/ip_vs_wrr.c | |||
@@ -77,11 +77,12 @@ static int ip_vs_wrr_gcd_weight(struct ip_vs_service *svc) | |||
77 | static int ip_vs_wrr_max_weight(struct ip_vs_service *svc) | 77 | static int ip_vs_wrr_max_weight(struct ip_vs_service *svc) |
78 | { | 78 | { |
79 | struct ip_vs_dest *dest; | 79 | struct ip_vs_dest *dest; |
80 | int weight = 0; | 80 | int new_weight, weight = 0; |
81 | 81 | ||
82 | list_for_each_entry(dest, &svc->destinations, n_list) { | 82 | list_for_each_entry(dest, &svc->destinations, n_list) { |
83 | if (atomic_read(&dest->weight) > weight) | 83 | new_weight = atomic_read(&dest->weight); |
84 | weight = atomic_read(&dest->weight); | 84 | if (new_weight > weight) |
85 | weight = new_weight; | ||
85 | } | 86 | } |
86 | 87 | ||
87 | return weight; | 88 | return weight; |