Patch from Stephen Hemminger IPV4 and IPV6 changes to remove use of brlock. Change from earlier version of the patch is to use barrier() to avoid possible compiler test/usage race. 25-akpm/net/ipv4/af_inet.c | 22 ++++++++++--------- 25-akpm/net/ipv4/icmp.c | 1 25-akpm/net/ipv4/ip_input.c | 4 ++- 25-akpm/net/ipv4/ip_output.c | 9 +++---- 25-akpm/net/ipv4/netfilter/ip_conntrack_core.c | 7 +----- 25-akpm/net/ipv4/netfilter/ip_conntrack_standalone.c | 4 --- 25-akpm/net/ipv4/netfilter/ip_nat_core.c | 1 25-akpm/net/ipv4/netfilter/ip_nat_helper.c | 4 --- 25-akpm/net/ipv4/netfilter/ip_nat_snmp_basic.c | 3 -- 25-akpm/net/ipv4/netfilter/ip_nat_standalone.c | 4 --- 25-akpm/net/ipv4/netfilter/ip_queue.c | 4 --- 25-akpm/net/ipv4/protocol.c | 15 +++++------- 25-akpm/net/ipv6/af_inet6.c | 15 ++++++------ 25-akpm/net/ipv6/icmp.c | 1 25-akpm/net/ipv6/ip6_input.c | 4 ++- 25-akpm/net/ipv6/ipv6_sockglue.c | 9 +++---- 25-akpm/net/ipv6/netfilter/ip6_queue.c | 3 -- 25-akpm/net/ipv6/protocol.c | 12 +++++----- 18 files changed, 53 insertions(+), 69 deletions(-) diff -puN net/ipv4/af_inet.c~brlock-removal-4 net/ipv4/af_inet.c --- 25/net/ipv4/af_inet.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/af_inet.c Thu Mar 13 15:15:45 2003 @@ -94,7 +94,6 @@ #include #include #include -#include #include #include #include @@ -130,6 +129,7 @@ static kmem_cache_t *raw4_sk_cachep; * build a new socket. */ struct list_head inetsw[SOCK_MAX]; +static spinlock_t inetsw_lock = SPIN_LOCK_UNLOCKED; /* New destruction routine */ @@ -337,8 +337,8 @@ static int inet_create(struct socket *so /* Look for the requested type/protocol pair. */ answer = NULL; - br_read_lock_bh(BR_NETPROTO_LOCK); - list_for_each(p, &inetsw[sock->type]) { + rcu_read_lock(); + list_for_each_rcu(p, &inetsw[sock->type]) { answer = list_entry(p, struct inet_protosw, list); /* Check the non-wild match. */ @@ -356,7 +356,7 @@ static int inet_create(struct socket *so } answer = NULL; } - br_read_unlock_bh(BR_NETPROTO_LOCK); + rcu_read_unlock(); err = -ESOCKTNOSUPPORT; if (!answer) @@ -977,7 +977,7 @@ void inet_register_protosw(struct inet_p int protocol = p->protocol; struct list_head *last_perm; - br_write_lock_bh(BR_NETPROTO_LOCK); + spin_lock_bh(&inetsw_lock); if (p->type > SOCK_MAX) goto out_illegal; @@ -1006,9 +1006,9 @@ void inet_register_protosw(struct inet_p * non-permanent entry. This means that when we remove this entry, the * system automatically returns to the old behavior. */ - list_add(&p->list, last_perm); + list_add_rcu(&p->list, last_perm); out: - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inetsw_lock); return; out_permanent: @@ -1030,9 +1030,11 @@ void inet_unregister_protosw(struct inet "Attempt to unregister permanent protocol %d.\n", p->protocol); } else { - br_write_lock_bh(BR_NETPROTO_LOCK); - list_del(&p->list); - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_lock_bh(&inetsw_lock); + list_del_rcu(&p->list); + spin_unlock_bh(&inetsw_lock); + + synchronize_kernel(); } } diff -puN net/ipv4/icmp.c~brlock-removal-4 net/ipv4/icmp.c --- 25/net/ipv4/icmp.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/icmp.c Thu Mar 13 15:15:45 2003 @@ -702,6 +702,7 @@ static void icmp_unreach(struct sk_buff */ ipprot = inet_protos[hash]; + barrier(); if (ipprot && ipprot->err_handler) ipprot->err_handler(skb, info); diff -puN net/ipv4/ip_input.c~brlock-removal-4 net/ipv4/ip_input.c --- 25/net/ipv4/ip_input.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/ip_input.c Thu Mar 13 15:15:45 2003 @@ -232,7 +232,9 @@ static inline int ip_local_deliver_finis if (raw_sk) raw_v4_input(skb, skb->nh.iph, hash); - if ((ipprot = inet_protos[hash]) != NULL) { + ipprot = inet_protos[hash]; + barrier();/* prevent RCU compiler optimization problems */ + if (ipprot) { int ret; if (!ipprot->no_policy && diff -puN net/ipv4/ip_output.c~brlock-removal-4 net/ipv4/ip_output.c --- 25/net/ipv4/ip_output.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/ip_output.c Thu Mar 13 15:15:45 2003 @@ -1261,11 +1261,10 @@ void ip_send_reply(struct sock *sk, stru static struct packet_type ip_packet_type = { - __constant_htons(ETH_P_IP), - NULL, /* All devices */ - ip_rcv, - (void*)1, - NULL, + .type = __constant_htons(ETH_P_IP), + .dev = NULL, /* All devices */ + .func = ip_rcv, + .data = (void*)1, }; /* diff -puN net/ipv4/netfilter/ip_conntrack_core.c~brlock-removal-4 net/ipv4/netfilter/ip_conntrack_core.c --- 25/net/ipv4/netfilter/ip_conntrack_core.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/netfilter/ip_conntrack_core.c Thu Mar 13 15:15:45 2003 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -1160,8 +1159,7 @@ void ip_conntrack_helper_unregister(stru WRITE_UNLOCK(&ip_conntrack_lock); /* Someone could be still looking at the helper in a bh. */ - br_write_lock_bh(BR_NETPROTO_LOCK); - br_write_unlock_bh(BR_NETPROTO_LOCK); + synchronize_kernel(); } /* Refresh conntrack for this many jiffies. */ @@ -1402,8 +1400,7 @@ void ip_conntrack_cleanup(void) /* This makes sure all current packets have passed through netfilter framework. Roll on, two-stage module delete... */ - br_write_lock_bh(BR_NETPROTO_LOCK); - br_write_unlock_bh(BR_NETPROTO_LOCK); + synchronize_kernel(); i_see_dead_people: ip_ct_selective_cleanup(kill_all, NULL); diff -puN net/ipv4/netfilter/ip_conntrack_standalone.c~brlock-removal-4 net/ipv4/netfilter/ip_conntrack_standalone.c --- 25/net/ipv4/netfilter/ip_conntrack_standalone.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/netfilter/ip_conntrack_standalone.c Thu Mar 13 15:15:45 2003 @@ -15,7 +15,6 @@ #include #include #include -#include #include #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock) @@ -342,8 +341,7 @@ void ip_conntrack_protocol_unregister(st WRITE_UNLOCK(&ip_conntrack_lock); /* Somebody could be still looking at the proto in bh. */ - br_write_lock_bh(BR_NETPROTO_LOCK); - br_write_unlock_bh(BR_NETPROTO_LOCK); + synchronize_kernel(); /* Remove all contrack entries for this protocol */ ip_ct_selective_cleanup(kill_proto, &proto->proto); diff -puN net/ipv4/netfilter/ip_nat_core.c~brlock-removal-4 net/ipv4/netfilter/ip_nat_core.c --- 25/net/ipv4/netfilter/ip_nat_core.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/netfilter/ip_nat_core.c Thu Mar 13 15:15:45 2003 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff -puN net/ipv4/netfilter/ip_nat_helper.c~brlock-removal-4 net/ipv4/netfilter/ip_nat_helper.c --- 25/net/ipv4/netfilter/ip_nat_helper.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/netfilter/ip_nat_helper.c Thu Mar 13 15:15:45 2003 @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -545,8 +544,7 @@ void ip_nat_helper_unregister(struct ip_ WRITE_UNLOCK(&ip_nat_lock); /* Someone could be still looking at the helper in a bh. */ - br_write_lock_bh(BR_NETPROTO_LOCK); - br_write_unlock_bh(BR_NETPROTO_LOCK); + synchronize_kernel(); /* Find anything using it, and umm, kill them. We can't turn them into normal connections: if we've adjusted SYNs, then diff -puN net/ipv4/netfilter/ip_nat_snmp_basic.c~brlock-removal-4 net/ipv4/netfilter/ip_nat_snmp_basic.c --- 25/net/ipv4/netfilter/ip_nat_snmp_basic.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/netfilter/ip_nat_snmp_basic.c Thu Mar 13 15:15:45 2003 @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include @@ -1351,8 +1350,6 @@ static void __exit fini(void) { ip_nat_helper_unregister(&snmp); ip_nat_helper_unregister(&snmp_trap); - br_write_lock_bh(BR_NETPROTO_LOCK); - br_write_unlock_bh(BR_NETPROTO_LOCK); } module_init(init); diff -puN net/ipv4/netfilter/ip_nat_standalone.c~brlock-removal-4 net/ipv4/netfilter/ip_nat_standalone.c --- 25/net/ipv4/netfilter/ip_nat_standalone.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/netfilter/ip_nat_standalone.c Thu Mar 13 15:15:45 2003 @@ -24,7 +24,6 @@ #include #include #include -#include #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) @@ -286,8 +285,7 @@ void ip_nat_protocol_unregister(struct i WRITE_UNLOCK(&ip_nat_lock); /* Someone could be still looking at the proto in a bh. */ - br_write_lock_bh(BR_NETPROTO_LOCK); - br_write_unlock_bh(BR_NETPROTO_LOCK); + synchronize_kernel(); } static int init_or_cleanup(int init) diff -puN net/ipv4/netfilter/ip_queue.c~brlock-removal-4 net/ipv4/netfilter/ip_queue.c --- 25/net/ipv4/netfilter/ip_queue.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/netfilter/ip_queue.c Thu Mar 13 15:15:45 2003 @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -685,8 +684,7 @@ init_or_cleanup(int init) cleanup: nf_unregister_queue_handler(PF_INET); - br_write_lock_bh(BR_NETPROTO_LOCK); - br_write_unlock_bh(BR_NETPROTO_LOCK); + ipq_flush(NF_DROP); cleanup_sysctl: diff -puN net/ipv4/protocol.c~brlock-removal-4 net/ipv4/protocol.c --- 25/net/ipv4/protocol.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv4/protocol.c Thu Mar 13 15:15:45 2003 @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -49,6 +48,7 @@ #include struct inet_protocol *inet_protos[MAX_INET_PROTOS]; +static spinlock_t inet_proto_lock = SPIN_LOCK_UNLOCKED; /* * Add a protocol handler to the hash tables @@ -60,16 +60,14 @@ int inet_add_protocol(struct inet_protoc hash = protocol & (MAX_INET_PROTOS - 1); - br_write_lock_bh(BR_NETPROTO_LOCK); - + spin_lock_bh(&inet_proto_lock); if (inet_protos[hash]) { ret = -1; } else { inet_protos[hash] = prot; ret = 0; } - - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inet_proto_lock); return ret; } @@ -84,16 +82,15 @@ int inet_del_protocol(struct inet_protoc hash = protocol & (MAX_INET_PROTOS - 1); - br_write_lock_bh(BR_NETPROTO_LOCK); - + spin_lock_bh(&inet_proto_lock); if (inet_protos[hash] == prot) { inet_protos[hash] = NULL; ret = 0; } else { ret = -1; } - - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inet_proto_lock); + synchronize_kernel(); return ret; } diff -puN net/ipv6/af_inet6.c~brlock-removal-4 net/ipv6/af_inet6.c --- 25/net/ipv6/af_inet6.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv6/af_inet6.c Thu Mar 13 15:15:45 2003 @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -101,6 +100,7 @@ kmem_cache_t *raw6_sk_cachep; * build a new socket. */ struct list_head inetsw6[SOCK_MAX]; +static spinlock_t inetsw6_lock = SPIN_LOCK_UNLOCKED; static void inet6_sock_destruct(struct sock *sk) { @@ -161,8 +161,8 @@ static int inet6_create(struct socket *s /* Look for the requested type/protocol pair. */ answer = NULL; - br_read_lock_bh(BR_NETPROTO_LOCK); - list_for_each(p, &inetsw6[sock->type]) { + rcu_read_lock(); + list_for_each_rcu(p, &inetsw6[sock->type]) { answer = list_entry(p, struct inet_protosw, list); /* Check the non-wild match. */ @@ -180,7 +180,7 @@ static int inet6_create(struct socket *s } answer = NULL; } - br_read_unlock_bh(BR_NETPROTO_LOCK); + rcu_read_unlock(); if (!answer) goto free_and_badtype; @@ -571,8 +571,7 @@ inet6_register_protosw(struct inet_proto int protocol = p->protocol; struct list_head *last_perm; - br_write_lock_bh(BR_NETPROTO_LOCK); - + spin_lock_bh(&inetsw6_lock); if (p->type > SOCK_MAX) goto out_illegal; @@ -600,9 +599,9 @@ inet6_register_protosw(struct inet_proto * non-permanent entry. This means that when we remove this entry, the * system automatically returns to the old behavior. */ - list_add(&p->list, last_perm); + list_add_rcu(&p->list, last_perm); out: - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inetsw6_lock); return; out_permanent: diff -puN net/ipv6/icmp.c~brlock-removal-4 net/ipv6/icmp.c --- 25/net/ipv6/icmp.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv6/icmp.c Thu Mar 13 15:15:45 2003 @@ -441,6 +441,7 @@ static void icmpv6_notify(struct sk_buff hash = nexthdr & (MAX_INET_PROTOS - 1); ipprot = inet6_protos[hash]; + barrier();/* prevent RCU compiler optimization problems */ if (ipprot && ipprot->err_handler) ipprot->err_handler(skb, NULL, type, code, inner_offset, info); diff -puN net/ipv6/ip6_input.c~brlock-removal-4 net/ipv6/ip6_input.c --- 25/net/ipv6/ip6_input.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv6/ip6_input.c Thu Mar 13 15:15:45 2003 @@ -172,7 +172,9 @@ resubmit: ipv6_raw_deliver(skb, nexthdr); hash = nexthdr & (MAX_INET_PROTOS - 1); - if ((ipprot = inet6_protos[hash]) != NULL) { + ipprot = inet6_protos[hash]; + barrier();/* prevent RCU compiler optimization problems */ + if (ipprot) { int ret = ipprot->handler(skb); if (ret < 0) { nexthdr = -ret; diff -puN net/ipv6/ipv6_sockglue.c~brlock-removal-4 net/ipv6/ipv6_sockglue.c --- 25/net/ipv6/ipv6_sockglue.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv6/ipv6_sockglue.c Thu Mar 13 15:15:45 2003 @@ -54,11 +54,10 @@ DEFINE_SNMP_STAT(struct ipv6_mib, ipv6_s static struct packet_type ipv6_packet_type = { - __constant_htons(ETH_P_IPV6), - NULL, /* All devices */ - ipv6_rcv, - (void*)1, - NULL + .type = __constant_htons(ETH_P_IPV6), + .dev = NULL, /* All devices */ + .func = ipv6_rcv, + .data = (void*)1, }; /* diff -puN net/ipv6/netfilter/ip6_queue.c~brlock-removal-4 net/ipv6/netfilter/ip6_queue.c --- 25/net/ipv6/netfilter/ip6_queue.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv6/netfilter/ip6_queue.c Thu Mar 13 15:15:45 2003 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -688,8 +687,6 @@ init_or_cleanup(int init) cleanup: nf_unregister_queue_handler(PF_INET6); - br_write_lock_bh(BR_NETPROTO_LOCK); - br_write_unlock_bh(BR_NETPROTO_LOCK); ipq_flush(NF_DROP); cleanup_sysctl: diff -puN net/ipv6/protocol.c~brlock-removal-4 net/ipv6/protocol.c --- 25/net/ipv6/protocol.c~brlock-removal-4 Thu Mar 13 15:15:45 2003 +++ 25-akpm/net/ipv6/protocol.c Thu Mar 13 15:15:45 2003 @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -41,21 +40,21 @@ #include struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; +static spinlock_t inet6_proto_lock = SPIN_LOCK_UNLOCKED; int inet6_add_protocol(struct inet6_protocol *prot, unsigned char protocol) { int ret, hash = protocol & (MAX_INET_PROTOS - 1); - br_write_lock_bh(BR_NETPROTO_LOCK); + spin_lock_bh(&inet6_proto_lock); if (inet6_protos[hash]) { ret = -1; } else { inet6_protos[hash] = prot; ret = 0; } - - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inet6_proto_lock); return ret; } @@ -68,7 +67,7 @@ int inet6_del_protocol(struct inet6_prot { int ret, hash = protocol & (MAX_INET_PROTOS - 1); - br_write_lock_bh(BR_NETPROTO_LOCK); + spin_lock_bh(&inet6_proto_lock); if (inet6_protos[hash] != prot) { ret = -1; @@ -76,8 +75,9 @@ int inet6_del_protocol(struct inet6_prot inet6_protos[hash] = NULL; ret = 0; } + spin_unlock_bh(&inet6_proto_lock); - br_write_unlock_bh(BR_NETPROTO_LOCK); + synchronize_kernel(); return ret; } _