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>
This commit is contained in:
committed by
Patrick McHardy
parent
9811600f7c
commit
0e60ebe04c
@@ -265,7 +265,7 @@ struct nf_afinfo {
|
|||||||
int route_key_size;
|
int route_key_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct nf_afinfo *nf_afinfo[NFPROTO_NUMPROTO];
|
extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO];
|
||||||
static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family)
|
static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family)
|
||||||
{
|
{
|
||||||
return rcu_dereference(nf_afinfo[family]);
|
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)
|
|||||||
#endif /*CONFIG_NETFILTER*/
|
#endif /*CONFIG_NETFILTER*/
|
||||||
|
|
||||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||||
extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
|
extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu;
|
||||||
extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
|
extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
|
||||||
extern void (*nf_ct_destroy)(struct nf_conntrack *);
|
extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu;
|
||||||
#else
|
#else
|
||||||
static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
|
static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -67,7 +67,7 @@ struct nf_ct_event_notifier {
|
|||||||
int (*fcn)(unsigned int events, struct nf_ct_event *item);
|
int (*fcn)(unsigned int events, struct nf_ct_event *item);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct nf_ct_event_notifier *nf_conntrack_event_cb;
|
extern struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
|
||||||
extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
|
extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
|
||||||
extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
|
extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ struct nf_exp_event_notifier {
|
|||||||
int (*fcn)(unsigned int events, struct nf_exp_event *item);
|
int (*fcn)(unsigned int events, struct nf_exp_event *item);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct nf_exp_event_notifier *nf_expect_event_cb;
|
extern struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
|
||||||
extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
|
extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
|
||||||
extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
|
extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
|
||||||
|
|
||||||
|
@@ -73,7 +73,7 @@ struct nf_conntrack_l3proto {
|
|||||||
struct module *me;
|
struct module *me;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX];
|
extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
|
||||||
|
|
||||||
/* Protocol registration. */
|
/* Protocol registration. */
|
||||||
extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
|
extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
|
||||||
|
@@ -212,7 +212,7 @@ EXPORT_SYMBOL(skb_make_writable);
|
|||||||
/* This does not belong here, but locally generated errors need it if connection
|
/* This does not belong here, but locally generated errors need it if connection
|
||||||
tracking in use: without this, connection may not be in hash table, and hence
|
tracking in use: without this, connection may not be in hash table, and hence
|
||||||
manufactured ICMP or RST packets will not be associated with it. */
|
manufactured ICMP or RST packets will not be associated with it. */
|
||||||
void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
|
void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu __read_mostly;
|
||||||
EXPORT_SYMBOL(ip_ct_attach);
|
EXPORT_SYMBOL(ip_ct_attach);
|
||||||
|
|
||||||
void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
|
void 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)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nf_ct_attach);
|
EXPORT_SYMBOL(nf_ct_attach);
|
||||||
|
|
||||||
void (*nf_ct_destroy)(struct nf_conntrack *);
|
void (*nf_ct_destroy)(struct nf_conntrack *) __rcu __read_mostly;
|
||||||
EXPORT_SYMBOL(nf_ct_destroy);
|
EXPORT_SYMBOL(nf_ct_destroy);
|
||||||
|
|
||||||
void nf_conntrack_destroy(struct nf_conntrack *nfct)
|
void nf_conntrack_destroy(struct nf_conntrack *nfct)
|
||||||
|
@@ -482,7 +482,7 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
|
|||||||
struct hlist_node *n;
|
struct hlist_node *n;
|
||||||
|
|
||||||
for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
|
for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
|
||||||
n = rcu_dereference(net->ct.expect_hash[st->bucket].first);
|
n = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
|
||||||
if (n)
|
if (n)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@@ -495,11 +495,11 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
|
|||||||
struct net *net = seq_file_net(seq);
|
struct net *net = seq_file_net(seq);
|
||||||
struct ct_expect_iter_state *st = seq->private;
|
struct ct_expect_iter_state *st = seq->private;
|
||||||
|
|
||||||
head = rcu_dereference(head->next);
|
head = rcu_dereference(hlist_next_rcu(head));
|
||||||
while (head == NULL) {
|
while (head == NULL) {
|
||||||
if (++st->bucket >= nf_ct_expect_hsize)
|
if (++st->bucket >= nf_ct_expect_hsize)
|
||||||
return NULL;
|
return NULL;
|
||||||
head = rcu_dereference(net->ct.expect_hash[st->bucket].first);
|
head = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
|
||||||
}
|
}
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
@@ -166,6 +166,7 @@ static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto
|
|||||||
int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
|
int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct nf_conntrack_l3proto *old;
|
||||||
|
|
||||||
if (proto->l3proto >= AF_MAX)
|
if (proto->l3proto >= AF_MAX)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
@@ -174,7 +175,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&nf_ct_proto_mutex);
|
mutex_lock(&nf_ct_proto_mutex);
|
||||||
if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) {
|
old = rcu_dereference_protected(nf_ct_l3protos[proto->l3proto],
|
||||||
|
lockdep_is_held(&nf_ct_proto_mutex));
|
||||||
|
if (old != &nf_conntrack_l3proto_generic) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
@@ -201,7 +204,9 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
|
|||||||
BUG_ON(proto->l3proto >= AF_MAX);
|
BUG_ON(proto->l3proto >= AF_MAX);
|
||||||
|
|
||||||
mutex_lock(&nf_ct_proto_mutex);
|
mutex_lock(&nf_ct_proto_mutex);
|
||||||
BUG_ON(nf_ct_l3protos[proto->l3proto] != proto);
|
BUG_ON(rcu_dereference_protected(nf_ct_l3protos[proto->l3proto],
|
||||||
|
lockdep_is_held(&nf_ct_proto_mutex)
|
||||||
|
) != proto);
|
||||||
rcu_assign_pointer(nf_ct_l3protos[proto->l3proto],
|
rcu_assign_pointer(nf_ct_l3protos[proto->l3proto],
|
||||||
&nf_conntrack_l3proto_generic);
|
&nf_conntrack_l3proto_generic);
|
||||||
nf_ct_l3proto_unregister_sysctl(proto);
|
nf_ct_l3proto_unregister_sysctl(proto);
|
||||||
@@ -299,8 +304,10 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
|
|||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
|
||||||
nf_ct_protos[l4proto->l3proto] = proto_array;
|
nf_ct_protos[l4proto->l3proto] = proto_array;
|
||||||
} else if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] !=
|
} else if (rcu_dereference_protected(
|
||||||
&nf_conntrack_l4proto_generic) {
|
nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
|
||||||
|
lockdep_is_held(&nf_ct_proto_mutex)
|
||||||
|
) != &nf_conntrack_l4proto_generic) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
@@ -331,7 +338,10 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
|
|||||||
BUG_ON(l4proto->l3proto >= PF_MAX);
|
BUG_ON(l4proto->l3proto >= PF_MAX);
|
||||||
|
|
||||||
mutex_lock(&nf_ct_proto_mutex);
|
mutex_lock(&nf_ct_proto_mutex);
|
||||||
BUG_ON(nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != l4proto);
|
BUG_ON(rcu_dereference_protected(
|
||||||
|
nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
|
||||||
|
lockdep_is_held(&nf_ct_proto_mutex)
|
||||||
|
) != l4proto);
|
||||||
rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
|
rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
|
||||||
&nf_conntrack_l4proto_generic);
|
&nf_conntrack_l4proto_generic);
|
||||||
nf_ct_l4proto_unregister_sysctl(l4proto);
|
nf_ct_l4proto_unregister_sysctl(l4proto);
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include <net/netfilter/nf_conntrack_helper.h>
|
#include <net/netfilter/nf_conntrack_helper.h>
|
||||||
#include <net/netfilter/nf_conntrack_acct.h>
|
#include <net/netfilter/nf_conntrack_acct.h>
|
||||||
#include <net/netfilter/nf_conntrack_zones.h>
|
#include <net/netfilter/nf_conntrack_zones.h>
|
||||||
|
#include <linux/rculist_nulls.h>
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq)
|
|||||||
for (st->bucket = 0;
|
for (st->bucket = 0;
|
||||||
st->bucket < net->ct.htable_size;
|
st->bucket < net->ct.htable_size;
|
||||||
st->bucket++) {
|
st->bucket++) {
|
||||||
n = rcu_dereference(net->ct.hash[st->bucket].first);
|
n = rcu_dereference(hlist_nulls_first_rcu(&net->ct.hash[st->bucket]));
|
||||||
if (!is_a_nulls(n))
|
if (!is_a_nulls(n))
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@@ -69,13 +70,15 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq,
|
|||||||
struct net *net = seq_file_net(seq);
|
struct net *net = seq_file_net(seq);
|
||||||
struct ct_iter_state *st = seq->private;
|
struct ct_iter_state *st = seq->private;
|
||||||
|
|
||||||
head = rcu_dereference(head->next);
|
head = rcu_dereference(hlist_nulls_next_rcu(head));
|
||||||
while (is_a_nulls(head)) {
|
while (is_a_nulls(head)) {
|
||||||
if (likely(get_nulls_value(head) == st->bucket)) {
|
if (likely(get_nulls_value(head) == st->bucket)) {
|
||||||
if (++st->bucket >= net->ct.htable_size)
|
if (++st->bucket >= net->ct.htable_size)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
head = rcu_dereference(net->ct.hash[st->bucket].first);
|
head = rcu_dereference(
|
||||||
|
hlist_nulls_first_rcu(
|
||||||
|
&net->ct.hash[st->bucket]));
|
||||||
}
|
}
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
@@ -161,7 +161,8 @@ static int seq_show(struct seq_file *s, void *v)
|
|||||||
struct nf_logger *t;
|
struct nf_logger *t;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
logger = nf_loggers[*pos];
|
logger = rcu_dereference_protected(nf_loggers[*pos],
|
||||||
|
lockdep_is_held(&nf_log_mutex));
|
||||||
|
|
||||||
if (!logger)
|
if (!logger)
|
||||||
ret = seq_printf(s, "%2lld NONE (", *pos);
|
ret = seq_printf(s, "%2lld NONE (", *pos);
|
||||||
@@ -249,7 +250,8 @@ static int nf_log_proc_dostring(ctl_table *table, int write,
|
|||||||
mutex_unlock(&nf_log_mutex);
|
mutex_unlock(&nf_log_mutex);
|
||||||
} else {
|
} else {
|
||||||
mutex_lock(&nf_log_mutex);
|
mutex_lock(&nf_log_mutex);
|
||||||
logger = nf_loggers[tindex];
|
logger = rcu_dereference_protected(nf_loggers[tindex],
|
||||||
|
lockdep_is_held(&nf_log_mutex));
|
||||||
if (!logger)
|
if (!logger)
|
||||||
table->data = "NONE";
|
table->data = "NONE";
|
||||||
else
|
else
|
||||||
|
@@ -27,14 +27,17 @@ static DEFINE_MUTEX(queue_handler_mutex);
|
|||||||
int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
|
int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
const struct nf_queue_handler *old;
|
||||||
|
|
||||||
if (pf >= ARRAY_SIZE(queue_handler))
|
if (pf >= ARRAY_SIZE(queue_handler))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&queue_handler_mutex);
|
mutex_lock(&queue_handler_mutex);
|
||||||
if (queue_handler[pf] == qh)
|
old = rcu_dereference_protected(queue_handler[pf],
|
||||||
|
lockdep_is_held(&queue_handler_mutex));
|
||||||
|
if (old == qh)
|
||||||
ret = -EEXIST;
|
ret = -EEXIST;
|
||||||
else if (queue_handler[pf])
|
else if (old)
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
else {
|
else {
|
||||||
rcu_assign_pointer(queue_handler[pf], qh);
|
rcu_assign_pointer(queue_handler[pf], qh);
|
||||||
@@ -49,11 +52,15 @@ EXPORT_SYMBOL(nf_register_queue_handler);
|
|||||||
/* The caller must flush their queue before this */
|
/* The caller must flush their queue before this */
|
||||||
int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
|
int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
|
||||||
{
|
{
|
||||||
|
const struct nf_queue_handler *old;
|
||||||
|
|
||||||
if (pf >= ARRAY_SIZE(queue_handler))
|
if (pf >= ARRAY_SIZE(queue_handler))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&queue_handler_mutex);
|
mutex_lock(&queue_handler_mutex);
|
||||||
if (queue_handler[pf] && queue_handler[pf] != qh) {
|
old = rcu_dereference_protected(queue_handler[pf],
|
||||||
|
lockdep_is_held(&queue_handler_mutex));
|
||||||
|
if (old && old != qh) {
|
||||||
mutex_unlock(&queue_handler_mutex);
|
mutex_unlock(&queue_handler_mutex);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -73,7 +80,10 @@ void nf_unregister_queue_handlers(const struct nf_queue_handler *qh)
|
|||||||
|
|
||||||
mutex_lock(&queue_handler_mutex);
|
mutex_lock(&queue_handler_mutex);
|
||||||
for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++) {
|
for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++) {
|
||||||
if (queue_handler[pf] == qh)
|
if (rcu_dereference_protected(
|
||||||
|
queue_handler[pf],
|
||||||
|
lockdep_is_held(&queue_handler_mutex)
|
||||||
|
) == qh)
|
||||||
rcu_assign_pointer(queue_handler[pf], NULL);
|
rcu_assign_pointer(queue_handler[pf], NULL);
|
||||||
}
|
}
|
||||||
mutex_unlock(&queue_handler_mutex);
|
mutex_unlock(&queue_handler_mutex);
|
||||||
|
@@ -874,19 +874,19 @@ static struct hlist_node *get_first(struct iter_state *st)
|
|||||||
|
|
||||||
for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
|
for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
|
||||||
if (!hlist_empty(&instance_table[st->bucket]))
|
if (!hlist_empty(&instance_table[st->bucket]))
|
||||||
return rcu_dereference_bh(instance_table[st->bucket].first);
|
return rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket]));
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h)
|
static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h)
|
||||||
{
|
{
|
||||||
h = rcu_dereference_bh(h->next);
|
h = rcu_dereference_bh(hlist_next_rcu(h));
|
||||||
while (!h) {
|
while (!h) {
|
||||||
if (++st->bucket >= INSTANCE_BUCKETS)
|
if (++st->bucket >= INSTANCE_BUCKETS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
h = rcu_dereference_bh(instance_table[st->bucket].first);
|
h = rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket]));
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user