diff options
author | Ying Xue <ying.xue@windriver.com> | 2014-04-20 22:55:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-04-22 21:17:53 -0400 |
commit | 2231c5af451e4b7ae3cc56eaa4653af6ede51109 (patch) | |
tree | 7c7e78e9adc9f746f64290530d40ce7a9b155fb7 /net/tipc/bearer.c | |
parent | 7a2f7d18e79b09c5c5a65fb1fa0e31ad046b3116 (diff) |
tipc: use RCU to protect media_ptr pointer
Now the media_ptr pointer is protected with tipc_net_lock write lock
on write side; tipc_net_lock read lock is used to read side. As the
part of effort of eliminating tipc_net_lock, we decide to adjust the
locking policy of media_ptr pointer protection: on write side, RTNL
lock is use while on read side RCU read lock is applied.
Signed-off-by: Ying Xue <ying.xue@windriver.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Tested-by: Erik Hugne <erik.hugne@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/bearer.c')
-rw-r--r-- | net/tipc/bearer.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index e0625e9e2c72..c24a35114fd7 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -458,7 +458,7 @@ int tipc_enable_l2_media(struct tipc_bearer *b) | |||
458 | return -ENODEV; | 458 | return -ENODEV; |
459 | 459 | ||
460 | /* Associate TIPC bearer with Ethernet bearer */ | 460 | /* Associate TIPC bearer with Ethernet bearer */ |
461 | b->media_ptr = dev; | 461 | rcu_assign_pointer(b->media_ptr, dev); |
462 | memset(b->bcast_addr.value, 0, sizeof(b->bcast_addr.value)); | 462 | memset(b->bcast_addr.value, 0, sizeof(b->bcast_addr.value)); |
463 | memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len); | 463 | memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len); |
464 | b->bcast_addr.media_id = b->media->type_id; | 464 | b->bcast_addr.media_id = b->media->type_id; |
@@ -477,7 +477,10 @@ int tipc_enable_l2_media(struct tipc_bearer *b) | |||
477 | */ | 477 | */ |
478 | void tipc_disable_l2_media(struct tipc_bearer *b) | 478 | void tipc_disable_l2_media(struct tipc_bearer *b) |
479 | { | 479 | { |
480 | struct net_device *dev = (struct net_device *)b->media_ptr; | 480 | struct net_device *dev; |
481 | |||
482 | dev = (struct net_device *)rtnl_dereference(b->media_ptr); | ||
483 | RCU_INIT_POINTER(b->media_ptr, NULL); | ||
481 | RCU_INIT_POINTER(dev->tipc_ptr, NULL); | 484 | RCU_INIT_POINTER(dev->tipc_ptr, NULL); |
482 | dev_put(dev); | 485 | dev_put(dev); |
483 | } | 486 | } |
@@ -492,8 +495,12 @@ int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b, | |||
492 | struct tipc_media_addr *dest) | 495 | struct tipc_media_addr *dest) |
493 | { | 496 | { |
494 | struct sk_buff *clone; | 497 | struct sk_buff *clone; |
498 | struct net_device *dev; | ||
495 | int delta; | 499 | int delta; |
496 | struct net_device *dev = (struct net_device *)b->media_ptr; | 500 | |
501 | dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr); | ||
502 | if (!dev) | ||
503 | return 0; | ||
497 | 504 | ||
498 | clone = skb_clone(buf, GFP_ATOMIC); | 505 | clone = skb_clone(buf, GFP_ATOMIC); |
499 | if (!clone) | 506 | if (!clone) |