aboutsummaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2009-06-03 04:32:06 -0400
committerpablo <pablo@1984.(none)>2009-06-03 04:32:06 -0400
commite34d5c1a4f9919a81b4ea4591d7383245f35cb8e (patch)
tree0a19bfe3e162b2b8de9b9414dcc2bef0a07e7133 /include/net
parent17e6e4eac070607a35464ea7e2c5eceac32e5eca (diff)
netfilter: conntrack: replace notify chain by function pointer
This patch removes the notify chain infrastructure and replace it by a simple function pointer. This issue has been mentioned in the mailing list several times: the use of the notify chain adds too much overhead for something that is only used by ctnetlink. This patch also changes nfnetlink_send(). It seems that gfp_any() returns GFP_KERNEL for user-context request, like those via ctnetlink, inside the RCU read-side section which is not valid. Using GFP_KERNEL is also evil since netlink may schedule(), this leads to "scheduling while atomic" bug reports. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h68
1 files changed, 48 insertions, 20 deletions
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 2e17a2d0eb3b..1afb907e015a 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -6,7 +6,6 @@
6#define _NF_CONNTRACK_ECACHE_H 6#define _NF_CONNTRACK_ECACHE_H
7#include <net/netfilter/nf_conntrack.h> 7#include <net/netfilter/nf_conntrack.h>
8 8
9#include <linux/notifier.h>
10#include <linux/interrupt.h> 9#include <linux/interrupt.h>
11#include <net/net_namespace.h> 10#include <net/net_namespace.h>
12#include <net/netfilter/nf_conntrack_expect.h> 11#include <net/netfilter/nf_conntrack_expect.h>
@@ -69,9 +68,13 @@ struct nf_ct_event {
69 int report; 68 int report;
70}; 69};
71 70
72extern struct atomic_notifier_head nf_conntrack_chain; 71struct nf_ct_event_notifier {
73extern int nf_conntrack_register_notifier(struct notifier_block *nb); 72 int (*fcn)(unsigned int events, struct nf_ct_event *item);
74extern int nf_conntrack_unregister_notifier(struct notifier_block *nb); 73};
74
75extern struct nf_ct_event_notifier *nf_conntrack_event_cb;
76extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
77extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
75 78
76extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); 79extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
77extern void __nf_ct_event_cache_init(struct nf_conn *ct); 80extern void __nf_ct_event_cache_init(struct nf_conn *ct);
@@ -97,13 +100,23 @@ nf_conntrack_event_report(enum ip_conntrack_events event,
97 u32 pid, 100 u32 pid,
98 int report) 101 int report)
99{ 102{
100 struct nf_ct_event item = { 103 struct nf_ct_event_notifier *notify;
101 .ct = ct, 104
102 .pid = pid, 105 rcu_read_lock();
103 .report = report 106 notify = rcu_dereference(nf_conntrack_event_cb);
104 }; 107 if (notify == NULL)
105 if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) 108 goto out_unlock;
106 atomic_notifier_call_chain(&nf_conntrack_chain, event, &item); 109
110 if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
111 struct nf_ct_event item = {
112 .ct = ct,
113 .pid = pid,
114 .report = report
115 };
116 notify->fcn(event, &item);
117 }
118out_unlock:
119 rcu_read_unlock();
107} 120}
108 121
109static inline void 122static inline void
@@ -118,9 +131,13 @@ struct nf_exp_event {
118 int report; 131 int report;
119}; 132};
120 133
121extern struct atomic_notifier_head nf_ct_expect_chain; 134struct nf_exp_event_notifier {
122extern int nf_ct_expect_register_notifier(struct notifier_block *nb); 135 int (*fcn)(unsigned int events, struct nf_exp_event *item);
123extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb); 136};
137
138extern struct nf_exp_event_notifier *nf_expect_event_cb;
139extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
140extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
124 141
125static inline void 142static inline void
126nf_ct_expect_event_report(enum ip_conntrack_expect_events event, 143nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
@@ -128,12 +145,23 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
128 u32 pid, 145 u32 pid,
129 int report) 146 int report)
130{ 147{
131 struct nf_exp_event item = { 148 struct nf_exp_event_notifier *notify;
132 .exp = exp, 149
133 .pid = pid, 150 rcu_read_lock();
134 .report = report 151 notify = rcu_dereference(nf_expect_event_cb);
135 }; 152 if (notify == NULL)
136 atomic_notifier_call_chain(&nf_ct_expect_chain, event, &item); 153 goto out_unlock;
154
155 {
156 struct nf_exp_event item = {
157 .exp = exp,
158 .pid = pid,
159 .report = report
160 };
161 notify->fcn(event, &item);
162 }
163out_unlock:
164 rcu_read_unlock();
137} 165}
138 166
139static inline void 167static inline void