diff options
author | Patrick McHardy <kaber@trash.net> | 2007-02-12 11:12:57 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-02-12 11:12:57 -0800 |
commit | 923f4902fefdf4e89b0fb32c4e069d4f57d704f5 (patch) | |
tree | 2fad9f83c0e6da178f5167f6efb2b75cbe28c68e /net/netfilter/nf_conntrack_proto.c | |
parent | 642d628b2c92e5283bbd3c849c7099c64ab68856 (diff) | |
download | op-kernel-dev-923f4902fefdf4e89b0fb32c4e069d4f57d704f5.zip op-kernel-dev-923f4902fefdf4e89b0fb32c4e069d4f57d704f5.tar.gz |
[NETFILTER]: nf_conntrack: properly use RCU API for nf_ct_protos/nf_ct_l3protos arrays
Replace preempt_{enable,disable} based RCU by proper use of the
RCU API and add missing rcu_read_lock/rcu_read_unlock calls in
all paths not obviously only used within packet process context
(nfnetlink_conntrack).
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter/nf_conntrack_proto.c')
-rw-r--r-- | net/netfilter/nf_conntrack_proto.c | 33 |
1 files changed, 14 insertions, 19 deletions
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 1a61b72..4dab3fa 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -66,7 +66,7 @@ __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto) if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL)) return &nf_conntrack_l4proto_generic; - return nf_ct_protos[l3proto][l4proto]; + return rcu_dereference(nf_ct_protos[l3proto][l4proto]); } EXPORT_SYMBOL_GPL(__nf_ct_l4proto_find); @@ -77,11 +77,11 @@ nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto) { struct nf_conntrack_l4proto *p; - preempt_disable(); + rcu_read_lock(); p = __nf_ct_l4proto_find(l3proto, l4proto); if (!try_module_get(p->me)) p = &nf_conntrack_l4proto_generic; - preempt_enable(); + rcu_read_unlock(); return p; } @@ -98,11 +98,11 @@ nf_ct_l3proto_find_get(u_int16_t l3proto) { struct nf_conntrack_l3proto *p; - preempt_disable(); + rcu_read_lock(); p = __nf_ct_l3proto_find(l3proto); if (!try_module_get(p->me)) p = &nf_conntrack_l3proto_generic; - preempt_enable(); + rcu_read_unlock(); return p; } @@ -137,10 +137,8 @@ void nf_ct_l3proto_module_put(unsigned short l3proto) { struct nf_conntrack_l3proto *p; - preempt_disable(); + /* rcu_read_lock not necessary since the caller holds a reference */ p = __nf_ct_l3proto_find(l3proto); - preempt_enable(); - module_put(p->me); } EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); @@ -202,7 +200,7 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) ret = -EBUSY; goto out_unlock; } - nf_ct_l3protos[proto->l3proto] = proto; + rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto); write_unlock_bh(&nf_conntrack_lock); ret = nf_ct_l3proto_register_sysctl(proto); @@ -233,14 +231,13 @@ int nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) goto out; } - nf_ct_l3protos[proto->l3proto] = &nf_conntrack_l3proto_generic; + rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], + &nf_conntrack_l3proto_generic); write_unlock_bh(&nf_conntrack_lock); + synchronize_rcu(); nf_ct_l3proto_unregister_sysctl(proto); - /* Somebody could be still looking at the proto in bh. */ - synchronize_net(); - /* Remove all contrack entries for this protocol */ nf_ct_iterate_cleanup(kill_l3proto, proto); @@ -356,7 +353,7 @@ retry: goto retry; } - nf_ct_protos[l4proto->l3proto][l4proto->l4proto] = l4proto; + rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], l4proto); write_unlock_bh(&nf_conntrack_lock); ret = nf_ct_l4proto_register_sysctl(l4proto); @@ -392,15 +389,13 @@ int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) ret = -EBUSY; goto out; } - nf_ct_protos[l4proto->l3proto][l4proto->l4proto] - = &nf_conntrack_l4proto_generic; + rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], + &nf_conntrack_l4proto_generic); write_unlock_bh(&nf_conntrack_lock); + synchronize_rcu(); nf_ct_l4proto_unregister_sysctl(l4proto); - /* Somebody could be still looking at the proto in bh. */ - synchronize_net(); - /* Remove all contrack entries for this protocol */ nf_ct_iterate_cleanup(kill_l4proto, l4proto); |