diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-09-16 19:03:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-09-16 19:03:28 -0400 |
commit | 559cf710b07c5e2cfa3fb8d8f4a1320fd84c53f9 (patch) | |
tree | deb74aea811a7d7c7e203f3743fd15372f8a6589 /net/sctp/ipv6.c | |
parent | 293035479942400a7fe8e4f72465d4e4e466b91a (diff) |
[SCTP]: Convert bind_addr_list locking to RCU
Since the sctp_sockaddr_entry is now RCU enabled as part of
the patch to synchronize sctp_localaddr_list, it makes sense to
change all handling of these entries to RCU. This includes the
sctp_bind_addrs structure and it's list of bound addresses.
This list is currently protected by an external rw_lock and that
looks like an overkill. There are only 2 writers to the list:
bind()/bindx() calls, and BH processing of ASCONF-ACK chunks.
These are already seriealized via the socket lock, so they will
not step on each other. These are also relatively rare, so we
should be good with RCU.
The readers are varied and they are easily converted to RCU.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Sridhar Samdurala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/ipv6.c')
-rw-r--r-- | net/sctp/ipv6.c | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index e12fa0a91da4..670fd2740b89 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -302,9 +302,7 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, | |||
302 | union sctp_addr *saddr) | 302 | union sctp_addr *saddr) |
303 | { | 303 | { |
304 | struct sctp_bind_addr *bp; | 304 | struct sctp_bind_addr *bp; |
305 | rwlock_t *addr_lock; | ||
306 | struct sctp_sockaddr_entry *laddr; | 305 | struct sctp_sockaddr_entry *laddr; |
307 | struct list_head *pos; | ||
308 | sctp_scope_t scope; | 306 | sctp_scope_t scope; |
309 | union sctp_addr *baddr = NULL; | 307 | union sctp_addr *baddr = NULL; |
310 | __u8 matchlen = 0; | 308 | __u8 matchlen = 0; |
@@ -324,14 +322,14 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, | |||
324 | scope = sctp_scope(daddr); | 322 | scope = sctp_scope(daddr); |
325 | 323 | ||
326 | bp = &asoc->base.bind_addr; | 324 | bp = &asoc->base.bind_addr; |
327 | addr_lock = &asoc->base.addr_lock; | ||
328 | 325 | ||
329 | /* Go through the bind address list and find the best source address | 326 | /* Go through the bind address list and find the best source address |
330 | * that matches the scope of the destination address. | 327 | * that matches the scope of the destination address. |
331 | */ | 328 | */ |
332 | sctp_read_lock(addr_lock); | 329 | rcu_read_lock(); |
333 | list_for_each(pos, &bp->address_list) { | 330 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { |
334 | laddr = list_entry(pos, struct sctp_sockaddr_entry, list); | 331 | if (!laddr->valid) |
332 | continue; | ||
335 | if ((laddr->use_as_src) && | 333 | if ((laddr->use_as_src) && |
336 | (laddr->a.sa.sa_family == AF_INET6) && | 334 | (laddr->a.sa.sa_family == AF_INET6) && |
337 | (scope <= sctp_scope(&laddr->a))) { | 335 | (scope <= sctp_scope(&laddr->a))) { |
@@ -353,7 +351,7 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, | |||
353 | __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); | 351 | __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); |
354 | } | 352 | } |
355 | 353 | ||
356 | sctp_read_unlock(addr_lock); | 354 | rcu_read_unlock(); |
357 | } | 355 | } |
358 | 356 | ||
359 | /* Make a copy of all potential local addresses. */ | 357 | /* Make a copy of all potential local addresses. */ |