aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-07-08 01:34:07 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:18:00 -0400
commit5d08ad440feae11b8d6e7599147a8a20ac60f99a (patch)
tree41043588598c7dae1b1edecaac3764924f0cf3bf /net/ipv4
parenta71c085562bcc99e8b711cab4222bff1f6e955da (diff)
[NETFILTER]: nf_conntrack_expect: convert proc functions to hash
Convert from the global expectation list to the hash table. 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.c83
1 files changed, 60 insertions, 23 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 12d6a6327b63..ab8e4c607b7a 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -207,47 +207,68 @@ static const struct file_operations ct_file_ops = {
207}; 207};
208 208
209/* expects */ 209/* expects */
210static void *exp_seq_start(struct seq_file *s, loff_t *pos) 210struct ct_expect_iter_state {
211 unsigned int bucket;
212};
213
214static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
211{ 215{
212 struct list_head *e = &nf_ct_expect_list; 216 struct ct_expect_iter_state *st = seq->private;
213 loff_t i;
214 217
215 /* strange seq_file api calls stop even if we fail, 218 for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
216 * thus we need to grab lock since stop unlocks */ 219 if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
217 read_lock_bh(&nf_conntrack_lock); 220 return nf_ct_expect_hash[st->bucket].first;
221 }
222 return NULL;
223}
218 224
219 if (list_empty(e)) 225static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
220 return NULL; 226 struct hlist_node *head)
227{
228 struct ct_expect_iter_state *st = seq->private;
221 229
222 for (i = 0; i <= *pos; i++) { 230 head = head->next;
223 e = e->next; 231 while (head == NULL) {
224 if (e == &nf_ct_expect_list) 232 if (++st->bucket >= nf_ct_expect_hsize)
225 return NULL; 233 return NULL;
234 head = nf_ct_expect_hash[st->bucket].first;
226 } 235 }
227 return e; 236 return head;
228} 237}
229 238
230static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) 239static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
231{ 240{
232 struct list_head *e = v; 241 struct hlist_node *head = ct_expect_get_first(seq);
233 242
234 ++*pos; 243 if (head)
235 e = e->next; 244 while (pos && (head = ct_expect_get_next(seq, head)))
245 pos--;
246 return pos ? NULL : head;
247}
236 248
237 if (e == &nf_ct_expect_list) 249static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
238 return NULL; 250{
251 read_lock_bh(&nf_conntrack_lock);
252 return ct_expect_get_idx(seq, *pos);
253}
239 254
240 return e; 255static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
256{
257 (*pos)++;
258 return ct_expect_get_next(seq, v);
241} 259}
242 260
243static void exp_seq_stop(struct seq_file *s, void *v) 261static void exp_seq_stop(struct seq_file *seq, void *v)
244{ 262{
245 read_unlock_bh(&nf_conntrack_lock); 263 read_unlock_bh(&nf_conntrack_lock);
246} 264}
247 265
248static int exp_seq_show(struct seq_file *s, void *v) 266static int exp_seq_show(struct seq_file *s, void *v)
249{ 267{
250 struct nf_conntrack_expect *exp = v; 268 struct nf_conntrack_expect *exp;
269 struct hlist_node *n = v;
270
271 exp = hlist_entry(n, struct nf_conntrack_expect, hnode);
251 272
252 if (exp->tuple.src.l3num != AF_INET) 273 if (exp->tuple.src.l3num != AF_INET)
253 return 0; 274 return 0;
@@ -276,7 +297,23 @@ static struct seq_operations exp_seq_ops = {
276 297
277static int exp_open(struct inode *inode, struct file *file) 298static int exp_open(struct inode *inode, struct file *file)
278{ 299{
279 return seq_open(file, &exp_seq_ops); 300 struct seq_file *seq;
301 struct ct_expect_iter_state *st;
302 int ret;
303
304 st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
305 if (st == NULL)
306 return -ENOMEM;
307 ret = seq_open(file, &exp_seq_ops);
308 if (ret)
309 goto out_free;
310 seq = file->private_data;
311 seq->private = st;
312 memset(st, 0, sizeof(struct ct_expect_iter_state));
313 return ret;
314out_free:
315 kfree(st);
316 return ret;
280} 317}
281 318
282static const struct file_operations ip_exp_file_ops = { 319static const struct file_operations ip_exp_file_ops = {
@@ -284,7 +321,7 @@ static const struct file_operations ip_exp_file_ops = {
284 .open = exp_open, 321 .open = exp_open,
285 .read = seq_read, 322 .read = seq_read,
286 .llseek = seq_lseek, 323 .llseek = seq_lseek,
287 .release = seq_release 324 .release = seq_release_private,
288}; 325};
289 326
290static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) 327static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)