aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-10-24 16:10:00 -0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2007-11-07 11:39:27 -0500
commit0ed90fb0f668fd07f14ae2007a809e8b26cd27a6 (patch)
tree114e48301b89a8e82f7238d8b691880607842947
parentb6157d8e03e1e780660a328f7183bcbfa4a93a19 (diff)
SCTP: Update RCU handling during the ADD-IP case
After learning more about rcu, it looks like the ADD-IP hadling doesn't need to call call_rcu_bh. All the rcu critical sections use rcu_read_lock, so using call_rcu_bh is wrong here. Now, restore the local_bh_disable() code blocks and use normal call_rcu() calls. Also restore the missing return statement. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
-rw-r--r--include/net/sctp/structs.h4
-rw-r--r--net/sctp/bind_addr.c13
-rw-r--r--net/sctp/sm_make_chunk.c6
-rw-r--r--net/sctp/socket.c2
4 files changed, 10 insertions, 15 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 482c2aab3d67..a17701740624 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1185,9 +1185,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
1185 int flags); 1185 int flags);
1186int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, 1186int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
1187 __u8 use_as_src, gfp_t gfp); 1187 __u8 use_as_src, gfp_t gfp);
1188int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *, 1188int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
1189 void fastcall (*rcu_call)(struct rcu_head *,
1190 void (*func)(struct rcu_head *)));
1191int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, 1189int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
1192 struct sctp_sock *); 1190 struct sctp_sock *);
1193union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, 1191union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index dfffa94fb9f6..cae95af9a8cc 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -180,9 +180,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
180/* Delete an address from the bind address list in the SCTP_bind_addr 180/* Delete an address from the bind address list in the SCTP_bind_addr
181 * structure. 181 * structure.
182 */ 182 */
183int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr, 183int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
184 void fastcall (*rcu_call)(struct rcu_head *head,
185 void (*func)(struct rcu_head *head)))
186{ 184{
187 struct sctp_sockaddr_entry *addr, *temp; 185 struct sctp_sockaddr_entry *addr, *temp;
188 186
@@ -198,15 +196,10 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr,
198 } 196 }
199 } 197 }
200 198
201 /* Call the rcu callback provided in the args. This function is
202 * called by both BH packet processing and user side socket option
203 * processing, but it works on different lists in those 2 contexts.
204 * Each context provides it's own callback, whether call_rcu_bh()
205 * or call_rcu(), to make sure that we wait for an appropriate time.
206 */
207 if (addr && !addr->valid) { 199 if (addr && !addr->valid) {
208 rcu_call(&addr->rcu, sctp_local_addr_free); 200 call_rcu(&addr->rcu, sctp_local_addr_free);
209 SCTP_DBG_OBJCNT_DEC(addr); 201 SCTP_DBG_OBJCNT_DEC(addr);
202 return 0;
210 } 203 }
211 204
212 return -EINVAL; 205 return -EINVAL;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 5de4729fe993..c60564dd169d 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -2953,13 +2953,17 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
2953 /* This is always done in BH context with a socket lock 2953 /* This is always done in BH context with a socket lock
2954 * held, so the list can not change. 2954 * held, so the list can not change.
2955 */ 2955 */
2956 local_bh_disable();
2956 list_for_each_entry(saddr, &bp->address_list, list) { 2957 list_for_each_entry(saddr, &bp->address_list, list) {
2957 if (sctp_cmp_addr_exact(&saddr->a, &addr)) 2958 if (sctp_cmp_addr_exact(&saddr->a, &addr))
2958 saddr->use_as_src = 1; 2959 saddr->use_as_src = 1;
2959 } 2960 }
2961 local_bh_enable();
2960 break; 2962 break;
2961 case SCTP_PARAM_DEL_IP: 2963 case SCTP_PARAM_DEL_IP:
2962 retval = sctp_del_bind_addr(bp, &addr, call_rcu_bh); 2964 local_bh_disable();
2965 retval = sctp_del_bind_addr(bp, &addr);
2966 local_bh_enable();
2963 list_for_each(pos, &asoc->peer.transport_addr_list) { 2967 list_for_each(pos, &asoc->peer.transport_addr_list) {
2964 transport = list_entry(pos, struct sctp_transport, 2968 transport = list_entry(pos, struct sctp_transport,
2965 transports); 2969 transports);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index a7ecf3159e53..6ce9b490fad5 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -660,7 +660,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
660 * socket routing and failover schemes. Refer to comments in 660 * socket routing and failover schemes. Refer to comments in
661 * sctp_do_bind(). -daisy 661 * sctp_do_bind(). -daisy
662 */ 662 */
663 retval = sctp_del_bind_addr(bp, sa_addr, call_rcu); 663 retval = sctp_del_bind_addr(bp, sa_addr);
664 664
665 addr_buf += af->sockaddr_len; 665 addr_buf += af->sockaddr_len;
666err_bindx_rem: 666err_bindx_rem: