diff options
author | Patrick McHardy <kaber@trash.net> | 2008-01-31 07:38:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-31 22:27:53 -0500 |
commit | 7d0742da1c8f5df3a34030f0170b30d1a052be80 (patch) | |
tree | f5717a37a9b4fe27abfa7886996d7051c57b91b9 /net/ipv4 | |
parent | c52fbb410b2662a7bbc5cbe5969d73c733151498 (diff) |
[NETFILTER]: nf_conntrack_expect: use RCU for expectation hash
Use RCU for expectation hash. This doesn't buy much for conntrack
runtime performance, but allows to reduce the use of nf_conntrack_lock
for /proc and nf_netlink_conntrack.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 543c02b74c96..2fdcd9233a03 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | |||
@@ -191,10 +191,12 @@ struct ct_expect_iter_state { | |||
191 | static struct hlist_node *ct_expect_get_first(struct seq_file *seq) | 191 | static struct hlist_node *ct_expect_get_first(struct seq_file *seq) |
192 | { | 192 | { |
193 | struct ct_expect_iter_state *st = seq->private; | 193 | struct ct_expect_iter_state *st = seq->private; |
194 | struct hlist_node *n; | ||
194 | 195 | ||
195 | for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { | 196 | for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { |
196 | if (!hlist_empty(&nf_ct_expect_hash[st->bucket])) | 197 | n = rcu_dereference(nf_ct_expect_hash[st->bucket].first); |
197 | return nf_ct_expect_hash[st->bucket].first; | 198 | if (n) |
199 | return n; | ||
198 | } | 200 | } |
199 | return NULL; | 201 | return NULL; |
200 | } | 202 | } |
@@ -204,11 +206,11 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq, | |||
204 | { | 206 | { |
205 | struct ct_expect_iter_state *st = seq->private; | 207 | struct ct_expect_iter_state *st = seq->private; |
206 | 208 | ||
207 | head = head->next; | 209 | head = rcu_dereference(head->next); |
208 | while (head == NULL) { | 210 | while (head == NULL) { |
209 | if (++st->bucket >= nf_ct_expect_hsize) | 211 | if (++st->bucket >= nf_ct_expect_hsize) |
210 | return NULL; | 212 | return NULL; |
211 | head = nf_ct_expect_hash[st->bucket].first; | 213 | head = rcu_dereference(nf_ct_expect_hash[st->bucket].first); |
212 | } | 214 | } |
213 | return head; | 215 | return head; |
214 | } | 216 | } |
@@ -225,7 +227,7 @@ static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos) | |||
225 | 227 | ||
226 | static void *exp_seq_start(struct seq_file *seq, loff_t *pos) | 228 | static void *exp_seq_start(struct seq_file *seq, loff_t *pos) |
227 | { | 229 | { |
228 | read_lock_bh(&nf_conntrack_lock); | 230 | rcu_read_lock(); |
229 | return ct_expect_get_idx(seq, *pos); | 231 | return ct_expect_get_idx(seq, *pos); |
230 | } | 232 | } |
231 | 233 | ||
@@ -237,7 +239,7 @@ static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
237 | 239 | ||
238 | static void exp_seq_stop(struct seq_file *seq, void *v) | 240 | static void exp_seq_stop(struct seq_file *seq, void *v) |
239 | { | 241 | { |
240 | read_unlock_bh(&nf_conntrack_lock); | 242 | rcu_read_unlock(); |
241 | } | 243 | } |
242 | 244 | ||
243 | static int exp_seq_show(struct seq_file *s, void *v) | 245 | static int exp_seq_show(struct seq_file *s, void *v) |