aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-11-15 12:17:21 -0500
committerPatrick McHardy <kaber@trash.net>2010-11-15 12:17:21 -0500
commit0e60ebe04c51807db972d03665651ae6b5c26d7e (patch)
treed76ba4540a6eb2008b2035e8f6371597e5ed6a13
parent9811600f7c1f18152430c6b93b0a76fdd88a59ce (diff)
netfilter: add __rcu annotations
Add some __rcu annotations and use helpers to reduce number of sparse warnings (CONFIG_SPARSE_RCU_POINTER=y) Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/netfilter.h6
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h4
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h2
-rw-r--r--net/netfilter/core.c4
-rw-r--r--net/netfilter/nf_conntrack_expect.c6
-rw-r--r--net/netfilter/nf_conntrack_proto.c20
-rw-r--r--net/netfilter/nf_conntrack_standalone.c9
-rw-r--r--net/netfilter/nf_log.c6
-rw-r--r--net/netfilter/nf_queue.c18
-rw-r--r--net/netfilter/nfnetlink_log.c6
10 files changed, 53 insertions, 28 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 89341c32631a..928a35ec21c7 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -265,7 +265,7 @@ struct nf_afinfo {
265 int route_key_size; 265 int route_key_size;
266}; 266};
267 267
268extern const struct nf_afinfo *nf_afinfo[NFPROTO_NUMPROTO]; 268extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO];
269static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family) 269static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family)
270{ 270{
271 return rcu_dereference(nf_afinfo[family]); 271 return rcu_dereference(nf_afinfo[family]);
@@ -355,9 +355,9 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
355#endif /*CONFIG_NETFILTER*/ 355#endif /*CONFIG_NETFILTER*/
356 356
357#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 357#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
358extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *); 358extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu;
359extern void nf_ct_attach(struct sk_buff *, struct sk_buff *); 359extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
360extern void (*nf_ct_destroy)(struct nf_conntrack *); 360extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu;
361#else 361#else
362static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {} 362static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
363#endif 363#endif
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index f596b60d6d75..8fdb04b8cce0 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -67,7 +67,7 @@ struct nf_ct_event_notifier {
67 int (*fcn)(unsigned int events, struct nf_ct_event *item); 67 int (*fcn)(unsigned int events, struct nf_ct_event *item);
68}; 68};
69 69
70extern struct nf_ct_event_notifier *nf_conntrack_event_cb; 70extern struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
71extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); 71extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
72extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb); 72extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
73 73
@@ -167,7 +167,7 @@ struct nf_exp_event_notifier {
167 int (*fcn)(unsigned int events, struct nf_exp_event *item); 167 int (*fcn)(unsigned int events, struct nf_exp_event *item);
168}; 168};
169 169
170extern struct nf_exp_event_notifier *nf_expect_event_cb; 170extern struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
171extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb); 171extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
172extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb); 172extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
173 173
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index a7547611e8f1..e8010f445ae1 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -73,7 +73,7 @@ struct nf_conntrack_l3proto {
73 struct module *me; 73 struct module *me;
74}; 74};
75 75
76extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX]; 76extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
77 77
78/* Protocol registration. */ 78/* Protocol registration. */
79extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto); 79extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 85dabb86be6f..5faec4fd8193 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -212,7 +212,7 @@ EXPORT_SYMBOL(skb_make_writable);
212/* This does not belong here, but locally generated errors need it if connection 212/* This does not belong here, but locally generated errors need it if connection
213 tracking in use: without this, connection may not be in hash table, and hence 213 tracking in use: without this, connection may not be in hash table, and hence
214 manufactured ICMP or RST packets will not be associated with it. */ 214 manufactured ICMP or RST packets will not be associated with it. */
215void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *); 215void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu __read_mostly;
216EXPORT_SYMBOL(ip_ct_attach); 216EXPORT_SYMBOL(ip_ct_attach);
217 217
218void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) 218void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
@@ -229,7 +229,7 @@ void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
229} 229}
230EXPORT_SYMBOL(nf_ct_attach); 230EXPORT_SYMBOL(nf_ct_attach);
231 231
232void (*nf_ct_destroy)(struct nf_conntrack *); 232void (*nf_ct_destroy)(struct nf_conntrack *) __rcu __read_mostly;
233EXPORT_SYMBOL(nf_ct_destroy); 233EXPORT_SYMBOL(nf_ct_destroy);
234 234
235void nf_conntrack_destroy(struct nf_conntrack *nfct) 235void nf_conntrack_destroy(struct nf_conntrack *nfct)
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 46e8966912b1..cab196cf428c 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -482,7 +482,7 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
482 struct hlist_node *n; 482 struct hlist_node *n;
483 483
484 for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { 484 for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
485 n = rcu_dereference(net->ct.expect_hash[st->bucket].first); 485 n = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
486 if (n) 486 if (n)
487 return n; 487 return n;
488 } 488 }
@@ -495,11 +495,11 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
495 struct net *net = seq_file_net(seq); 495 struct net *net = seq_file_net(seq);
496 struct ct_expect_iter_state *st = seq->private; 496 struct ct_expect_iter_state *st = seq->private;
497 497
498 head = rcu_dereference(head->next); 498 head = rcu_dereference(hlist_next_rcu(head));
499 while (head == NULL) { 499 while (head == NULL) {
500 if (++st->bucket >= nf_ct_expect_hsize) 500 if (++st->bucket >= nf_ct_expect_hsize)
501 return NULL; 501 return NULL;
502 head = rcu_dereference(net->ct.expect_hash[st->bucket].first); 502 head = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
503 } 503 }
504 return head; 504 return head;
505} 505}
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index dc7bb74110df..03b56a0fff30 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -166,6 +166,7 @@ static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto
166int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) 166int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
167{ 167{
168 int ret = 0; 168 int ret = 0;
169 struct nf_conntrack_l3proto *old;
169 170
170 if (proto->l3proto >= AF_MAX) 171 if (proto->l3proto >= AF_MAX)
171 return -EBUSY; 172 return -EBUSY;
@@ -174,7 +175,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
174 return -EINVAL; 175 return -EINVAL;
175 176
176 mutex_lock(&nf_ct_proto_mutex); 177 mutex_lock(&nf_ct_proto_mutex);
177 if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { 178 old = rcu_dereference_protected(nf_ct_l3protos[proto->l3proto],
179 lockdep_is_held(&nf_ct_proto_mutex));
180 if (old != &nf_conntrack_l3proto_generic) {
178 ret = -EBUSY; 181 ret = -EBUSY;
179 goto out_unlock; 182 goto out_unlock;
180 } 183 }
@@ -201,7 +204,9 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
201 BUG_ON(proto->l3proto >= AF_MAX); 204 BUG_ON(proto->l3proto >= AF_MAX);
202 205
203 mutex_lock(&nf_ct_proto_mutex); 206 mutex_lock(&nf_ct_proto_mutex);
204 BUG_ON(nf_ct_l3protos[proto->l3proto] != proto); 207 BUG_ON(rcu_dereference_protected(nf_ct_l3protos[proto->l3proto],
208 lockdep_is_held(&nf_ct_proto_mutex)
209 ) != proto);
205 rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], 210 rcu_assign_pointer(nf_ct_l3protos[proto->l3proto],
206 &nf_conntrack_l3proto_generic); 211 &nf_conntrack_l3proto_generic);
207 nf_ct_l3proto_unregister_sysctl(proto); 212 nf_ct_l3proto_unregister_sysctl(proto);
@@ -299,8 +304,10 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
299 smp_wmb(); 304 smp_wmb();
300 305
301 nf_ct_protos[l4proto->l3proto] = proto_array; 306 nf_ct_protos[l4proto->l3proto] = proto_array;
302 } else if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != 307 } else if (rcu_dereference_protected(
303 &nf_conntrack_l4proto_generic) { 308 nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
309 lockdep_is_held(&nf_ct_proto_mutex)
310 ) != &nf_conntrack_l4proto_generic) {
304 ret = -EBUSY; 311 ret = -EBUSY;
305 goto out_unlock; 312 goto out_unlock;
306 } 313 }
@@ -331,7 +338,10 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
331 BUG_ON(l4proto->l3proto >= PF_MAX); 338 BUG_ON(l4proto->l3proto >= PF_MAX);
332 339
333 mutex_lock(&nf_ct_proto_mutex); 340 mutex_lock(&nf_ct_proto_mutex);
334 BUG_ON(nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != l4proto); 341 BUG_ON(rcu_dereference_protected(
342 nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
343 lockdep_is_held(&nf_ct_proto_mutex)
344 ) != l4proto);
335 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], 345 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
336 &nf_conntrack_l4proto_generic); 346 &nf_conntrack_l4proto_generic);
337 nf_ct_l4proto_unregister_sysctl(l4proto); 347 nf_ct_l4proto_unregister_sysctl(l4proto);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 0fb65705b44b..328f1d2a51f8 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -29,6 +29,7 @@
29#include <net/netfilter/nf_conntrack_helper.h> 29#include <net/netfilter/nf_conntrack_helper.h>
30#include <net/netfilter/nf_conntrack_acct.h> 30#include <net/netfilter/nf_conntrack_acct.h>
31#include <net/netfilter/nf_conntrack_zones.h> 31#include <net/netfilter/nf_conntrack_zones.h>
32#include <linux/rculist_nulls.h>
32 33
33MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
34 35
@@ -56,7 +57,7 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq)
56 for (st->bucket = 0; 57 for (st->bucket = 0;
57 st->bucket < net->ct.htable_size; 58 st->bucket < net->ct.htable_size;
58 st->bucket++) { 59 st->bucket++) {
59 n = rcu_dereference(net->ct.hash[st->bucket].first); 60 n = rcu_dereference(hlist_nulls_first_rcu(&net->ct.hash[st->bucket]));
60 if (!is_a_nulls(n)) 61 if (!is_a_nulls(n))
61 return n; 62 return n;
62 } 63 }
@@ -69,13 +70,15 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq,
69 struct net *net = seq_file_net(seq); 70 struct net *net = seq_file_net(seq);
70 struct ct_iter_state *st = seq->private; 71 struct ct_iter_state *st = seq->private;
71 72
72 head = rcu_dereference(head->next); 73 head = rcu_dereference(hlist_nulls_next_rcu(head));
73 while (is_a_nulls(head)) { 74 while (is_a_nulls(head)) {
74 if (likely(get_nulls_value(head) == st->bucket)) { 75 if (likely(get_nulls_value(head) == st->bucket)) {
75 if (++st->bucket >= net->ct.htable_size) 76 if (++st->bucket >= net->ct.htable_size)
76 return NULL; 77 return NULL;
77 } 78 }
78 head = rcu_dereference(net->ct.hash[st->bucket].first); 79 head = rcu_dereference(
80 hlist_nulls_first_rcu(
81 &net->ct.hash[st->bucket]));
79 } 82 }
80 return head; 83 return head;
81} 84}
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index b07393eab88e..20c775cff2a8 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -161,7 +161,8 @@ static int seq_show(struct seq_file *s, void *v)
161 struct nf_logger *t; 161 struct nf_logger *t;
162 int ret; 162 int ret;
163 163
164 logger = nf_loggers[*pos]; 164 logger = rcu_dereference_protected(nf_loggers[*pos],
165 lockdep_is_held(&nf_log_mutex));
165 166
166 if (!logger) 167 if (!logger)
167 ret = seq_printf(s, "%2lld NONE (", *pos); 168 ret = seq_printf(s, "%2lld NONE (", *pos);
@@ -249,7 +250,8 @@ static int nf_log_proc_dostring(ctl_table *table, int write,
249 mutex_unlock(&nf_log_mutex); 250 mutex_unlock(&nf_log_mutex);
250 } else { 251 } else {
251 mutex_lock(&nf_log_mutex); 252 mutex_lock(&nf_log_mutex);
252 logger = nf_loggers[tindex]; 253 logger = rcu_dereference_protected(nf_loggers[tindex],
254 lockdep_is_held(&nf_log_mutex));
253 if (!logger) 255 if (!logger)
254 table->data = "NONE"; 256 table->data = "NONE";
255 else 257 else
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 74aebed5bd28..1876f7411561 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -27,14 +27,17 @@ static DEFINE_MUTEX(queue_handler_mutex);
27int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) 27int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
28{ 28{
29 int ret; 29 int ret;
30 const struct nf_queue_handler *old;
30 31
31 if (pf >= ARRAY_SIZE(queue_handler)) 32 if (pf >= ARRAY_SIZE(queue_handler))
32 return -EINVAL; 33 return -EINVAL;
33 34
34 mutex_lock(&queue_handler_mutex); 35 mutex_lock(&queue_handler_mutex);
35 if (queue_handler[pf] == qh) 36 old = rcu_dereference_protected(queue_handler[pf],
37 lockdep_is_held(&queue_handler_mutex));
38 if (old == qh)
36 ret = -EEXIST; 39 ret = -EEXIST;
37 else if (queue_handler[pf]) 40 else if (old)
38 ret = -EBUSY; 41 ret = -EBUSY;
39 else { 42 else {
40 rcu_assign_pointer(queue_handler[pf], qh); 43 rcu_assign_pointer(queue_handler[pf], qh);
@@ -49,11 +52,15 @@ EXPORT_SYMBOL(nf_register_queue_handler);
49/* The caller must flush their queue before this */ 52/* The caller must flush their queue before this */
50int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) 53int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
51{ 54{
55 const struct nf_queue_handler *old;
56
52 if (pf >= ARRAY_SIZE(queue_handler)) 57 if (pf >= ARRAY_SIZE(queue_handler))
53 return -EINVAL; 58 return -EINVAL;
54 59
55 mutex_lock(&queue_handler_mutex); 60 mutex_lock(&queue_handler_mutex);
56 if (queue_handler[pf] && queue_handler[pf] != qh) { 61 old = rcu_dereference_protected(queue_handler[pf],
62 lockdep_is_held(&queue_handler_mutex));
63 if (old && old != qh) {
57 mutex_unlock(&queue_handler_mutex); 64 mutex_unlock(&queue_handler_mutex);
58 return -EINVAL; 65 return -EINVAL;
59 } 66 }
@@ -73,7 +80,10 @@ void nf_unregister_queue_handlers(const struct nf_queue_handler *qh)
73 80
74 mutex_lock(&queue_handler_mutex); 81 mutex_lock(&queue_handler_mutex);
75 for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++) { 82 for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++) {
76 if (queue_handler[pf] == qh) 83 if (rcu_dereference_protected(
84 queue_handler[pf],
85 lockdep_is_held(&queue_handler_mutex)
86 ) == qh)
77 rcu_assign_pointer(queue_handler[pf], NULL); 87 rcu_assign_pointer(queue_handler[pf], NULL);
78 } 88 }
79 mutex_unlock(&queue_handler_mutex); 89 mutex_unlock(&queue_handler_mutex);
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 6a1572b0ab41..91592da504b9 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -874,19 +874,19 @@ static struct hlist_node *get_first(struct iter_state *st)
874 874
875 for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { 875 for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
876 if (!hlist_empty(&instance_table[st->bucket])) 876 if (!hlist_empty(&instance_table[st->bucket]))
877 return rcu_dereference_bh(instance_table[st->bucket].first); 877 return rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket]));
878 } 878 }
879 return NULL; 879 return NULL;
880} 880}
881 881
882static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h) 882static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h)
883{ 883{
884 h = rcu_dereference_bh(h->next); 884 h = rcu_dereference_bh(hlist_next_rcu(h));
885 while (!h) { 885 while (!h) {
886 if (++st->bucket >= INSTANCE_BUCKETS) 886 if (++st->bucket >= INSTANCE_BUCKETS)
887 return NULL; 887 return NULL;
888 888
889 h = rcu_dereference_bh(instance_table[st->bucket].first); 889 h = rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket]));
890 } 890 }
891 return h; 891 return h;
892} 892}