提交 5d08ad44 编写于 作者: P Patrick McHardy 提交者: David S. Miller

[NETFILTER]: nf_conntrack_expect: convert proc functions to hash

Convert from the global expectation list to the hash table.
Signed-off-by: NPatrick McHardy <kaber@trash.net>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 a71c0855
...@@ -207,47 +207,68 @@ static const struct file_operations ct_file_ops = { ...@@ -207,47 +207,68 @@ static const struct file_operations ct_file_ops = {
}; };
/* expects */ /* expects */
static void *exp_seq_start(struct seq_file *s, loff_t *pos) struct ct_expect_iter_state {
unsigned int bucket;
};
static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
{ {
struct list_head *e = &nf_ct_expect_list; struct ct_expect_iter_state *st = seq->private;
loff_t i;
/* strange seq_file api calls stop even if we fail, for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
* thus we need to grab lock since stop unlocks */ if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
read_lock_bh(&nf_conntrack_lock); return nf_ct_expect_hash[st->bucket].first;
}
return NULL;
}
if (list_empty(e)) static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
return NULL; struct hlist_node *head)
{
struct ct_expect_iter_state *st = seq->private;
for (i = 0; i <= *pos; i++) { head = head->next;
e = e->next; while (head == NULL) {
if (e == &nf_ct_expect_list) if (++st->bucket >= nf_ct_expect_hsize)
return NULL; return NULL;
head = nf_ct_expect_hash[st->bucket].first;
} }
return e; return head;
} }
static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
{ {
struct list_head *e = v; struct hlist_node *head = ct_expect_get_first(seq);
++*pos; if (head)
e = e->next; while (pos && (head = ct_expect_get_next(seq, head)))
pos--;
return pos ? NULL : head;
}
if (e == &nf_ct_expect_list) static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
return NULL; {
read_lock_bh(&nf_conntrack_lock);
return ct_expect_get_idx(seq, *pos);
}
return e; static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
(*pos)++;
return ct_expect_get_next(seq, v);
} }
static void exp_seq_stop(struct seq_file *s, void *v) static void exp_seq_stop(struct seq_file *seq, void *v)
{ {
read_unlock_bh(&nf_conntrack_lock); read_unlock_bh(&nf_conntrack_lock);
} }
static int exp_seq_show(struct seq_file *s, void *v) static int exp_seq_show(struct seq_file *s, void *v)
{ {
struct nf_conntrack_expect *exp = v; struct nf_conntrack_expect *exp;
struct hlist_node *n = v;
exp = hlist_entry(n, struct nf_conntrack_expect, hnode);
if (exp->tuple.src.l3num != AF_INET) if (exp->tuple.src.l3num != AF_INET)
return 0; return 0;
...@@ -276,7 +297,23 @@ static struct seq_operations exp_seq_ops = { ...@@ -276,7 +297,23 @@ static struct seq_operations exp_seq_ops = {
static int exp_open(struct inode *inode, struct file *file) static int exp_open(struct inode *inode, struct file *file)
{ {
return seq_open(file, &exp_seq_ops); struct seq_file *seq;
struct ct_expect_iter_state *st;
int ret;
st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
if (st == NULL)
return -ENOMEM;
ret = seq_open(file, &exp_seq_ops);
if (ret)
goto out_free;
seq = file->private_data;
seq->private = st;
memset(st, 0, sizeof(struct ct_expect_iter_state));
return ret;
out_free:
kfree(st);
return ret;
} }
static const struct file_operations ip_exp_file_ops = { static const struct file_operations ip_exp_file_ops = {
...@@ -284,7 +321,7 @@ static const struct file_operations ip_exp_file_ops = { ...@@ -284,7 +321,7 @@ static const struct file_operations ip_exp_file_ops = {
.open = exp_open, .open = exp_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = seq_release .release = seq_release_private,
}; };
static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
......
...@@ -377,47 +377,68 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect) ...@@ -377,47 +377,68 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
EXPORT_SYMBOL_GPL(nf_ct_expect_related); EXPORT_SYMBOL_GPL(nf_ct_expect_related);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static void *exp_seq_start(struct seq_file *s, loff_t *pos) struct ct_expect_iter_state {
unsigned int bucket;
};
static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
{ {
struct list_head *e = &nf_ct_expect_list; struct ct_expect_iter_state *st = seq->private;
loff_t i;
/* strange seq_file api calls stop even if we fail, for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
* thus we need to grab lock since stop unlocks */ if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
read_lock_bh(&nf_conntrack_lock); return nf_ct_expect_hash[st->bucket].first;
}
return NULL;
}
if (list_empty(e)) static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
return NULL; struct hlist_node *head)
{
struct ct_expect_iter_state *st = seq->private;
for (i = 0; i <= *pos; i++) { head = head->next;
e = e->next; while (head == NULL) {
if (e == &nf_ct_expect_list) if (++st->bucket >= nf_ct_expect_hsize)
return NULL; return NULL;
head = nf_ct_expect_hash[st->bucket].first;
} }
return e; return head;
} }
static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
{ {
struct list_head *e = v; struct hlist_node *head = ct_expect_get_first(seq);
++*pos; if (head)
e = e->next; while (pos && (head = ct_expect_get_next(seq, head)))
pos--;
return pos ? NULL : head;
}
if (e == &nf_ct_expect_list) static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
return NULL; {
read_lock_bh(&nf_conntrack_lock);
return ct_expect_get_idx(seq, *pos);
}
return e; static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
(*pos)++;
return ct_expect_get_next(seq, v);
} }
static void exp_seq_stop(struct seq_file *s, void *v) static void exp_seq_stop(struct seq_file *seq, void *v)
{ {
read_unlock_bh(&nf_conntrack_lock); read_unlock_bh(&nf_conntrack_lock);
} }
static int exp_seq_show(struct seq_file *s, void *v) static int exp_seq_show(struct seq_file *s, void *v)
{ {
struct nf_conntrack_expect *expect = v; struct nf_conntrack_expect *expect;
struct hlist_node *n = v;
expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
if (expect->timeout.function) if (expect->timeout.function)
seq_printf(s, "%ld ", timer_pending(&expect->timeout) seq_printf(s, "%ld ", timer_pending(&expect->timeout)
...@@ -443,15 +464,31 @@ static struct seq_operations exp_seq_ops = { ...@@ -443,15 +464,31 @@ static struct seq_operations exp_seq_ops = {
static int exp_open(struct inode *inode, struct file *file) static int exp_open(struct inode *inode, struct file *file)
{ {
return seq_open(file, &exp_seq_ops); struct seq_file *seq;
struct ct_expect_iter_state *st;
int ret;
st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
if (st == NULL)
return -ENOMEM;
ret = seq_open(file, &exp_seq_ops);
if (ret)
goto out_free;
seq = file->private_data;
seq->private = st;
memset(st, 0, sizeof(struct ct_expect_iter_state));
return ret;
out_free:
kfree(st);
return ret;
} }
const struct file_operations exp_file_ops = { static const struct file_operations exp_file_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = exp_open, .open = exp_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = seq_release .release = seq_release_private,
}; };
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册