aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/bearer.c
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2014-04-20 22:55:46 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-22 21:17:53 -0400
commit7a2f7d18e79b09c5c5a65fb1fa0e31ad046b3116 (patch)
treeef3267297c7ea8509ec816e2e195debf3c037def /net/tipc/bearer.c
parentf8322dfce5766c8e26d9224cbcaf6fdc0b2eb04d (diff)
tipc: decouple the relationship between bearer and link
Currently on both paths of message transmission and reception, the read lock of tipc_net_lock must be held before bearer is accessed, while the write lock of tipc_net_lock has to be taken before bearer is configured. Although it can ensure that bearer is always valid on the two data paths, link and bearer is closely bound together. So as the part of effort of removing tipc_net_lock, the locking policy of bearer protection will be adjusted as below: on the two data paths, RCU is used, and on the configuration path of bearer, RTNL lock is applied. Now RCU just covers the path of message reception. To make it possible to protect the path of message transmission with RCU, link should not use its stored bearer pointer to access bearer, but it should use the bearer identity of its attached bearer as index to get bearer instance from bearer_list array, which can help us decouple the relationship between bearer and link. As a result, bearer on the path of message transmission can be safely protected by RCU when we access bearer_list array within RCU lock protection. 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.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 65b17639e43d..e0625e9e2c72 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -215,18 +215,32 @@ struct sk_buff *tipc_bearer_get_names(void)
215 return buf; 215 return buf;
216} 216}
217 217
218void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest) 218void tipc_bearer_add_dest(u32 bearer_id, u32 dest)
219{ 219{
220 tipc_nmap_add(&b_ptr->nodes, dest); 220 struct tipc_bearer *b_ptr;
221 tipc_bcbearer_sort(); 221
222 tipc_disc_add_dest(b_ptr->link_req); 222 rcu_read_lock();
223 b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
224 if (b_ptr) {
225 tipc_nmap_add(&b_ptr->nodes, dest);
226 tipc_bcbearer_sort();
227 tipc_disc_add_dest(b_ptr->link_req);
228 }
229 rcu_read_unlock();
223} 230}
224 231
225void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) 232void tipc_bearer_remove_dest(u32 bearer_id, u32 dest)
226{ 233{
227 tipc_nmap_remove(&b_ptr->nodes, dest); 234 struct tipc_bearer *b_ptr;
228 tipc_bcbearer_sort(); 235
229 tipc_disc_remove_dest(b_ptr->link_req); 236 rcu_read_lock();
237 b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
238 if (b_ptr) {
239 tipc_nmap_remove(&b_ptr->nodes, dest);
240 tipc_bcbearer_sort();
241 tipc_disc_remove_dest(b_ptr->link_req);
242 }
243 rcu_read_unlock();
230} 244}
231 245
232/** 246/**
@@ -507,10 +521,16 @@ int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
507 * The media send routine must not alter the buffer being passed in 521 * The media send routine must not alter the buffer being passed in
508 * as it may be needed for later retransmission! 522 * as it may be needed for later retransmission!
509 */ 523 */
510void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf, 524void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf,
511 struct tipc_media_addr *dest) 525 struct tipc_media_addr *dest)
512{ 526{
513 b->media->send_msg(buf, b, dest); 527 struct tipc_bearer *b_ptr;
528
529 rcu_read_lock();
530 b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]);
531 if (likely(b_ptr))
532 b_ptr->media->send_msg(buf, b_ptr, dest);
533 rcu_read_unlock();
514} 534}
515 535
516/** 536/**