Commit 0ed90fb0 authored by Vlad Yasevich's avatar Vlad Yasevich

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: default avatarVlad Yasevich <vladislav.yasevich@hp.com>
parent b6157d8e
...@@ -1185,9 +1185,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, ...@@ -1185,9 +1185,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
int flags); int flags);
int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
__u8 use_as_src, gfp_t gfp); __u8 use_as_src, gfp_t gfp);
int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *, int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
void fastcall (*rcu_call)(struct rcu_head *,
void (*func)(struct rcu_head *)));
int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
struct sctp_sock *); struct sctp_sock *);
union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
......
...@@ -180,9 +180,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, ...@@ -180,9 +180,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
/* Delete an address from the bind address list in the SCTP_bind_addr /* Delete an address from the bind address list in the SCTP_bind_addr
* structure. * structure.
*/ */
int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr, int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
void fastcall (*rcu_call)(struct rcu_head *head,
void (*func)(struct rcu_head *head)))
{ {
struct sctp_sockaddr_entry *addr, *temp; struct sctp_sockaddr_entry *addr, *temp;
...@@ -198,15 +196,10 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr, ...@@ -198,15 +196,10 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr,
} }
} }
/* Call the rcu callback provided in the args. This function is
* called by both BH packet processing and user side socket option
* processing, but it works on different lists in those 2 contexts.
* Each context provides it's own callback, whether call_rcu_bh()
* or call_rcu(), to make sure that we wait for an appropriate time.
*/
if (addr && !addr->valid) { if (addr && !addr->valid) {
rcu_call(&addr->rcu, sctp_local_addr_free); call_rcu(&addr->rcu, sctp_local_addr_free);
SCTP_DBG_OBJCNT_DEC(addr); SCTP_DBG_OBJCNT_DEC(addr);
return 0;
} }
return -EINVAL; return -EINVAL;
......
...@@ -2953,13 +2953,17 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, ...@@ -2953,13 +2953,17 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
/* This is always done in BH context with a socket lock /* This is always done in BH context with a socket lock
* held, so the list can not change. * held, so the list can not change.
*/ */
local_bh_disable();
list_for_each_entry(saddr, &bp->address_list, list) { list_for_each_entry(saddr, &bp->address_list, list) {
if (sctp_cmp_addr_exact(&saddr->a, &addr)) if (sctp_cmp_addr_exact(&saddr->a, &addr))
saddr->use_as_src = 1; saddr->use_as_src = 1;
} }
local_bh_enable();
break; break;
case SCTP_PARAM_DEL_IP: case SCTP_PARAM_DEL_IP:
retval = sctp_del_bind_addr(bp, &addr, call_rcu_bh); local_bh_disable();
retval = sctp_del_bind_addr(bp, &addr);
local_bh_enable();
list_for_each(pos, &asoc->peer.transport_addr_list) { list_for_each(pos, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport, transport = list_entry(pos, struct sctp_transport,
transports); transports);
......
...@@ -660,7 +660,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) ...@@ -660,7 +660,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
* socket routing and failover schemes. Refer to comments in * socket routing and failover schemes. Refer to comments in
* sctp_do_bind(). -daisy * sctp_do_bind(). -daisy
*/ */
retval = sctp_del_bind_addr(bp, sa_addr, call_rcu); retval = sctp_del_bind_addr(bp, sa_addr);
addr_buf += af->sockaddr_len; addr_buf += af->sockaddr_len;
err_bindx_rem: err_bindx_rem:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment