aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
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
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')
-rw-r--r--net/tipc/bcast.c8
-rw-r--r--net/tipc/bearer.c40
-rw-r--r--net/tipc/bearer.h6
-rw-r--r--net/tipc/discover.c17
-rw-r--r--net/tipc/link.c49
-rw-r--r--net/tipc/link.h6
-rw-r--r--net/tipc/node.c8
7 files changed, 88 insertions, 46 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 223a19929024..51dab96ddd5f 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -321,7 +321,7 @@ void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent)
321 : n_ptr->bclink.last_sent); 321 : n_ptr->bclink.last_sent);
322 322
323 spin_lock_bh(&bc_lock); 323 spin_lock_bh(&bc_lock);
324 tipc_bearer_send(&bcbearer->bearer, buf, NULL); 324 tipc_bearer_send(MAX_BEARERS, buf, NULL);
325 bcl->stats.sent_nacks++; 325 bcl->stats.sent_nacks++;
326 spin_unlock_bh(&bc_lock); 326 spin_unlock_bh(&bc_lock);
327 kfree_skb(buf); 327 kfree_skb(buf);
@@ -627,13 +627,13 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1,
627 627
628 if (bp_index == 0) { 628 if (bp_index == 0) {
629 /* Use original buffer for first bearer */ 629 /* Use original buffer for first bearer */
630 tipc_bearer_send(b, buf, &b->bcast_addr); 630 tipc_bearer_send(b->identity, buf, &b->bcast_addr);
631 } else { 631 } else {
632 /* Avoid concurrent buffer access */ 632 /* Avoid concurrent buffer access */
633 tbuf = pskb_copy(buf, GFP_ATOMIC); 633 tbuf = pskb_copy(buf, GFP_ATOMIC);
634 if (!tbuf) 634 if (!tbuf)
635 break; 635 break;
636 tipc_bearer_send(b, tbuf, &b->bcast_addr); 636 tipc_bearer_send(b->identity, tbuf, &b->bcast_addr);
637 kfree_skb(tbuf); /* Bearer keeps a clone */ 637 kfree_skb(tbuf); /* Bearer keeps a clone */
638 } 638 }
639 639
@@ -786,7 +786,7 @@ void tipc_bclink_init(void)
786 bcl->owner = &bclink->node; 786 bcl->owner = &bclink->node;
787 bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; 787 bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
788 tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); 788 tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
789 bcl->b_ptr = &bcbearer->bearer; 789 bcl->bearer_id = MAX_BEARERS;
790 rcu_assign_pointer(bearer_list[MAX_BEARERS], &bcbearer->bearer); 790 rcu_assign_pointer(bearer_list[MAX_BEARERS], &bcbearer->bearer);
791 bcl->state = WORKING_WORKING; 791 bcl->state = WORKING_WORKING;
792 strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); 792 strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME);
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/**
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index b67b7ea4cc36..2fa86bd67c0a 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -183,14 +183,14 @@ int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
183 struct tipc_media_addr *dest); 183 struct tipc_media_addr *dest);
184 184
185struct sk_buff *tipc_bearer_get_names(void); 185struct sk_buff *tipc_bearer_get_names(void);
186void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest); 186void tipc_bearer_add_dest(u32 bearer_id, u32 dest);
187void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest); 187void tipc_bearer_remove_dest(u32 bearer_id, u32 dest);
188struct tipc_bearer *tipc_bearer_find(const char *name); 188struct tipc_bearer *tipc_bearer_find(const char *name);
189struct tipc_media *tipc_media_find(const char *name); 189struct tipc_media *tipc_media_find(const char *name);
190int tipc_bearer_setup(void); 190int tipc_bearer_setup(void);
191void tipc_bearer_cleanup(void); 191void tipc_bearer_cleanup(void);
192void tipc_bearer_stop(void); 192void tipc_bearer_stop(void);
193void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf, 193void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf,
194 struct tipc_media_addr *dest); 194 struct tipc_media_addr *dest);
195 195
196#endif /* _TIPC_BEARER_H */ 196#endif /* _TIPC_BEARER_H */
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 542fe3413dc4..3a8f211f08c7 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -46,8 +46,9 @@
46 46
47/** 47/**
48 * struct tipc_link_req - information about an ongoing link setup request 48 * struct tipc_link_req - information about an ongoing link setup request
49 * @bearer: bearer issuing requests 49 * @bearer_id: identity of bearer issuing requests
50 * @dest: destination address for request messages 50 * @dest: destination address for request messages
51 * @domain: network domain to which links can be established
51 * @num_nodes: number of nodes currently discovered (i.e. with an active link) 52 * @num_nodes: number of nodes currently discovered (i.e. with an active link)
52 * @lock: spinlock for controlling access to requests 53 * @lock: spinlock for controlling access to requests
53 * @buf: request message to be (repeatedly) sent 54 * @buf: request message to be (repeatedly) sent
@@ -55,8 +56,9 @@
55 * @timer_intv: current interval between requests (in ms) 56 * @timer_intv: current interval between requests (in ms)
56 */ 57 */
57struct tipc_link_req { 58struct tipc_link_req {
58 struct tipc_bearer *bearer; 59 u32 bearer_id;
59 struct tipc_media_addr dest; 60 struct tipc_media_addr dest;
61 u32 domain;
60 int num_nodes; 62 int num_nodes;
61 spinlock_t lock; 63 spinlock_t lock;
62 struct sk_buff *buf; 64 struct sk_buff *buf;
@@ -241,7 +243,7 @@ void tipc_disc_rcv(struct sk_buff *buf, struct tipc_bearer *b_ptr)
241 if ((type == DSC_REQ_MSG) && !link_fully_up) { 243 if ((type == DSC_REQ_MSG) && !link_fully_up) {
242 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, b_ptr); 244 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, b_ptr);
243 if (rbuf) { 245 if (rbuf) {
244 tipc_bearer_send(b_ptr, rbuf, &media_addr); 246 tipc_bearer_send(b_ptr->identity, rbuf, &media_addr);
245 kfree_skb(rbuf); 247 kfree_skb(rbuf);
246 } 248 }
247 } 249 }
@@ -303,7 +305,7 @@ static void disc_timeout(struct tipc_link_req *req)
303 spin_lock_bh(&req->lock); 305 spin_lock_bh(&req->lock);
304 306
305 /* Stop searching if only desired node has been found */ 307 /* Stop searching if only desired node has been found */
306 if (tipc_node(req->bearer->domain) && req->num_nodes) { 308 if (tipc_node(req->domain) && req->num_nodes) {
307 req->timer_intv = TIPC_LINK_REQ_INACTIVE; 309 req->timer_intv = TIPC_LINK_REQ_INACTIVE;
308 goto exit; 310 goto exit;
309 } 311 }
@@ -315,7 +317,7 @@ static void disc_timeout(struct tipc_link_req *req)
315 * hold at fast polling rate if don't have any associated nodes, 317 * hold at fast polling rate if don't have any associated nodes,
316 * otherwise hold at slow polling rate 318 * otherwise hold at slow polling rate
317 */ 319 */
318 tipc_bearer_send(req->bearer, req->buf, &req->dest); 320 tipc_bearer_send(req->bearer_id, req->buf, &req->dest);
319 321
320 322
321 req->timer_intv *= 2; 323 req->timer_intv *= 2;
@@ -354,14 +356,15 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest)
354 } 356 }
355 357
356 memcpy(&req->dest, dest, sizeof(*dest)); 358 memcpy(&req->dest, dest, sizeof(*dest));
357 req->bearer = b_ptr; 359 req->bearer_id = b_ptr->identity;
360 req->domain = b_ptr->domain;
358 req->num_nodes = 0; 361 req->num_nodes = 0;
359 req->timer_intv = TIPC_LINK_REQ_INIT; 362 req->timer_intv = TIPC_LINK_REQ_INIT;
360 spin_lock_init(&req->lock); 363 spin_lock_init(&req->lock);
361 k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); 364 k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
362 k_start_timer(&req->timer, req->timer_intv); 365 k_start_timer(&req->timer, req->timer_intv);
363 b_ptr->link_req = req; 366 b_ptr->link_req = req;
364 tipc_bearer_send(req->bearer, req->buf, &req->dest); 367 tipc_bearer_send(req->bearer_id, req->buf, &req->dest);
365 return 0; 368 return 0;
366} 369}
367 370
diff --git a/net/tipc/link.c b/net/tipc/link.c
index c5190ab75290..229d478494b9 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -101,9 +101,18 @@ static unsigned int align(unsigned int i)
101 101
102static void link_init_max_pkt(struct tipc_link *l_ptr) 102static void link_init_max_pkt(struct tipc_link *l_ptr)
103{ 103{
104 struct tipc_bearer *b_ptr;
104 u32 max_pkt; 105 u32 max_pkt;
105 106
106 max_pkt = (l_ptr->b_ptr->mtu & ~3); 107 rcu_read_lock();
108 b_ptr = rcu_dereference_rtnl(bearer_list[l_ptr->bearer_id]);
109 if (!b_ptr) {
110 rcu_read_unlock();
111 return;
112 }
113 max_pkt = (b_ptr->mtu & ~3);
114 rcu_read_unlock();
115
107 if (max_pkt > MAX_MSG_SIZE) 116 if (max_pkt > MAX_MSG_SIZE)
108 max_pkt = MAX_MSG_SIZE; 117 max_pkt = MAX_MSG_SIZE;
109 118
@@ -248,7 +257,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
248 l_ptr->owner = n_ptr; 257 l_ptr->owner = n_ptr;
249 l_ptr->checkpoint = 1; 258 l_ptr->checkpoint = 1;
250 l_ptr->peer_session = INVALID_SESSION; 259 l_ptr->peer_session = INVALID_SESSION;
251 l_ptr->b_ptr = b_ptr; 260 l_ptr->bearer_id = b_ptr->identity;
252 link_set_supervision_props(l_ptr, b_ptr->tolerance); 261 link_set_supervision_props(l_ptr, b_ptr->tolerance);
253 l_ptr->state = RESET_UNKNOWN; 262 l_ptr->state = RESET_UNKNOWN;
254 263
@@ -263,6 +272,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
263 l_ptr->priority = b_ptr->priority; 272 l_ptr->priority = b_ptr->priority;
264 tipc_link_set_queue_limits(l_ptr, b_ptr->window); 273 tipc_link_set_queue_limits(l_ptr, b_ptr->window);
265 274
275 l_ptr->net_plane = b_ptr->net_plane;
266 link_init_max_pkt(l_ptr); 276 link_init_max_pkt(l_ptr);
267 277
268 l_ptr->next_out_no = 1; 278 l_ptr->next_out_no = 1;
@@ -426,7 +436,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
426 return; 436 return;
427 437
428 tipc_node_link_down(l_ptr->owner, l_ptr); 438 tipc_node_link_down(l_ptr->owner, l_ptr);
429 tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); 439 tipc_bearer_remove_dest(l_ptr->bearer_id, l_ptr->addr);
430 440
431 if (was_active_link && tipc_node_active_links(l_ptr->owner)) { 441 if (was_active_link && tipc_node_active_links(l_ptr->owner)) {
432 l_ptr->reset_checkpoint = checkpoint; 442 l_ptr->reset_checkpoint = checkpoint;
@@ -477,7 +487,7 @@ static void link_activate(struct tipc_link *l_ptr)
477{ 487{
478 l_ptr->next_in_no = l_ptr->stats.recv_info = 1; 488 l_ptr->next_in_no = l_ptr->stats.recv_info = 1;
479 tipc_node_link_up(l_ptr->owner, l_ptr); 489 tipc_node_link_up(l_ptr->owner, l_ptr);
480 tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); 490 tipc_bearer_add_dest(l_ptr->bearer_id, l_ptr->addr);
481} 491}
482 492
483/** 493/**
@@ -777,7 +787,7 @@ int __tipc_link_xmit(struct tipc_link *l_ptr, struct sk_buff *buf)
777 if (likely(!link_congested(l_ptr))) { 787 if (likely(!link_congested(l_ptr))) {
778 link_add_to_outqueue(l_ptr, buf, msg); 788 link_add_to_outqueue(l_ptr, buf, msg);
779 789
780 tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); 790 tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr);
781 l_ptr->unacked_window = 0; 791 l_ptr->unacked_window = 0;
782 return dsz; 792 return dsz;
783 } 793 }
@@ -941,7 +951,7 @@ static int tipc_link_xmit_fast(struct tipc_link *l_ptr, struct sk_buff *buf,
941 if (likely(!link_congested(l_ptr))) { 951 if (likely(!link_congested(l_ptr))) {
942 if (likely(msg_size(msg) <= l_ptr->max_pkt)) { 952 if (likely(msg_size(msg) <= l_ptr->max_pkt)) {
943 link_add_to_outqueue(l_ptr, buf, msg); 953 link_add_to_outqueue(l_ptr, buf, msg);
944 tipc_bearer_send(l_ptr->b_ptr, buf, 954 tipc_bearer_send(l_ptr->bearer_id, buf,
945 &l_ptr->media_addr); 955 &l_ptr->media_addr);
946 l_ptr->unacked_window = 0; 956 l_ptr->unacked_window = 0;
947 return res; 957 return res;
@@ -1204,7 +1214,7 @@ static u32 tipc_link_push_packet(struct tipc_link *l_ptr)
1204 if (r_q_size && buf) { 1214 if (r_q_size && buf) {
1205 msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); 1215 msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
1206 msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); 1216 msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
1207 tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); 1217 tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr);
1208 l_ptr->retransm_queue_head = mod(++r_q_head); 1218 l_ptr->retransm_queue_head = mod(++r_q_head);
1209 l_ptr->retransm_queue_size = --r_q_size; 1219 l_ptr->retransm_queue_size = --r_q_size;
1210 l_ptr->stats.retransmitted++; 1220 l_ptr->stats.retransmitted++;
@@ -1216,7 +1226,7 @@ static u32 tipc_link_push_packet(struct tipc_link *l_ptr)
1216 if (buf) { 1226 if (buf) {
1217 msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); 1227 msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
1218 msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); 1228 msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
1219 tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); 1229 tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr);
1220 l_ptr->unacked_window = 0; 1230 l_ptr->unacked_window = 0;
1221 kfree_skb(buf); 1231 kfree_skb(buf);
1222 l_ptr->proto_msg_queue = NULL; 1232 l_ptr->proto_msg_queue = NULL;
@@ -1233,7 +1243,8 @@ static u32 tipc_link_push_packet(struct tipc_link *l_ptr)
1233 if (mod(next - first) < l_ptr->queue_limit[0]) { 1243 if (mod(next - first) < l_ptr->queue_limit[0]) {
1234 msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); 1244 msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
1235 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 1245 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
1236 tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); 1246 tipc_bearer_send(l_ptr->bearer_id, buf,
1247 &l_ptr->media_addr);
1237 if (msg_user(msg) == MSG_BUNDLER) 1248 if (msg_user(msg) == MSG_BUNDLER)
1238 msg_set_type(msg, CLOSED_MSG); 1249 msg_set_type(msg, CLOSED_MSG);
1239 l_ptr->next_out = buf->next; 1250 l_ptr->next_out = buf->next;
@@ -1352,7 +1363,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf,
1352 msg = buf_msg(buf); 1363 msg = buf_msg(buf);
1353 msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); 1364 msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
1354 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 1365 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
1355 tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); 1366 tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr);
1356 buf = buf->next; 1367 buf = buf->next;
1357 retransmits--; 1368 retransmits--;
1358 l_ptr->stats.retransmitted++; 1369 l_ptr->stats.retransmitted++;
@@ -1440,7 +1451,7 @@ static int link_recv_buf_validate(struct sk_buff *buf)
1440/** 1451/**
1441 * tipc_rcv - process TIPC packets/messages arriving from off-node 1452 * tipc_rcv - process TIPC packets/messages arriving from off-node
1442 * @head: pointer to message buffer chain 1453 * @head: pointer to message buffer chain
1443 * @tb_ptr: pointer to bearer message arrived on 1454 * @b_ptr: pointer to bearer message arrived on
1444 * 1455 *
1445 * Invoked with no locks held. Bearer pointer must point to a valid bearer 1456 * Invoked with no locks held. Bearer pointer must point to a valid bearer
1446 * structure (i.e. cannot be NULL), but bearer can be inactive. 1457 * structure (i.e. cannot be NULL), but bearer can be inactive.
@@ -1752,7 +1763,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
1752 1763
1753 /* Create protocol message with "out-of-sequence" sequence number */ 1764 /* Create protocol message with "out-of-sequence" sequence number */
1754 msg_set_type(msg, msg_typ); 1765 msg_set_type(msg, msg_typ);
1755 msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); 1766 msg_set_net_plane(msg, l_ptr->net_plane);
1756 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 1767 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
1757 msg_set_last_bcast(msg, tipc_bclink_get_last_sent()); 1768 msg_set_last_bcast(msg, tipc_bclink_get_last_sent());
1758 1769
@@ -1818,7 +1829,7 @@ void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
1818 skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); 1829 skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg));
1819 buf->priority = TC_PRIO_CONTROL; 1830 buf->priority = TC_PRIO_CONTROL;
1820 1831
1821 tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr); 1832 tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr);
1822 l_ptr->unacked_window = 0; 1833 l_ptr->unacked_window = 0;
1823 kfree_skb(buf); 1834 kfree_skb(buf);
1824} 1835}
@@ -1843,9 +1854,9 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf)
1843 /* record unnumbered packet arrival (force mismatch on next timeout) */ 1854 /* record unnumbered packet arrival (force mismatch on next timeout) */
1844 l_ptr->checkpoint--; 1855 l_ptr->checkpoint--;
1845 1856
1846 if (l_ptr->b_ptr->net_plane != msg_net_plane(msg)) 1857 if (l_ptr->net_plane != msg_net_plane(msg))
1847 if (tipc_own_addr > msg_prevnode(msg)) 1858 if (tipc_own_addr > msg_prevnode(msg))
1848 l_ptr->b_ptr->net_plane = msg_net_plane(msg); 1859 l_ptr->net_plane = msg_net_plane(msg);
1849 1860
1850 switch (msg_type(msg)) { 1861 switch (msg_type(msg)) {
1851 1862
@@ -2793,7 +2804,13 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector)
2793 2804
2794static void link_print(struct tipc_link *l_ptr, const char *str) 2805static void link_print(struct tipc_link *l_ptr, const char *str)
2795{ 2806{
2796 pr_info("%s Link %x<%s>:", str, l_ptr->addr, l_ptr->b_ptr->name); 2807 struct tipc_bearer *b_ptr;
2808
2809 rcu_read_lock();
2810 b_ptr = rcu_dereference_rtnl(bearer_list[l_ptr->bearer_id]);
2811 if (b_ptr)
2812 pr_info("%s Link %x<%s>:", str, l_ptr->addr, b_ptr->name);
2813 rcu_read_unlock();
2797 2814
2798 if (link_working_unknown(l_ptr)) 2815 if (link_working_unknown(l_ptr))
2799 pr_cont(":WU\n"); 2816 pr_cont(":WU\n");
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 8c0b49b5b2ee..4b556c181bae 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -107,7 +107,7 @@ struct tipc_stats {
107 * @checkpoint: reference point for triggering link continuity checking 107 * @checkpoint: reference point for triggering link continuity checking
108 * @peer_session: link session # being used by peer end of link 108 * @peer_session: link session # being used by peer end of link
109 * @peer_bearer_id: bearer id used by link's peer endpoint 109 * @peer_bearer_id: bearer id used by link's peer endpoint
110 * @b_ptr: pointer to bearer used by link 110 * @bearer_id: local bearer id used by link
111 * @tolerance: minimum link continuity loss needed to reset link [in ms] 111 * @tolerance: minimum link continuity loss needed to reset link [in ms]
112 * @continuity_interval: link continuity testing interval [in ms] 112 * @continuity_interval: link continuity testing interval [in ms]
113 * @abort_limit: # of unacknowledged continuity probes needed to reset link 113 * @abort_limit: # of unacknowledged continuity probes needed to reset link
@@ -116,6 +116,7 @@ struct tipc_stats {
116 * @proto_msg: template for control messages generated by link 116 * @proto_msg: template for control messages generated by link
117 * @pmsg: convenience pointer to "proto_msg" field 117 * @pmsg: convenience pointer to "proto_msg" field
118 * @priority: current link priority 118 * @priority: current link priority
119 * @net_plane: current link network plane ('A' through 'H')
119 * @queue_limit: outbound message queue congestion thresholds (indexed by user) 120 * @queue_limit: outbound message queue congestion thresholds (indexed by user)
120 * @exp_msg_count: # of tunnelled messages expected during link changeover 121 * @exp_msg_count: # of tunnelled messages expected during link changeover
121 * @reset_checkpoint: seq # of last acknowledged message at time of link reset 122 * @reset_checkpoint: seq # of last acknowledged message at time of link reset
@@ -155,7 +156,7 @@ struct tipc_link {
155 u32 checkpoint; 156 u32 checkpoint;
156 u32 peer_session; 157 u32 peer_session;
157 u32 peer_bearer_id; 158 u32 peer_bearer_id;
158 struct tipc_bearer *b_ptr; 159 u32 bearer_id;
159 u32 tolerance; 160 u32 tolerance;
160 u32 continuity_interval; 161 u32 continuity_interval;
161 u32 abort_limit; 162 u32 abort_limit;
@@ -167,6 +168,7 @@ struct tipc_link {
167 } proto_msg; 168 } proto_msg;
168 struct tipc_msg *pmsg; 169 struct tipc_msg *pmsg;
169 u32 priority; 170 u32 priority;
171 char net_plane;
170 u32 queue_limit[15]; /* queue_limit[0]==window limit */ 172 u32 queue_limit[15]; /* queue_limit[0]==window limit */
171 173
172 /* Changeover */ 174 /* Changeover */
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 1d3a4999a70f..fa6823f6457a 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -148,7 +148,7 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
148 n_ptr->working_links++; 148 n_ptr->working_links++;
149 149
150 pr_info("Established link <%s> on network plane %c\n", 150 pr_info("Established link <%s> on network plane %c\n",
151 l_ptr->name, l_ptr->b_ptr->net_plane); 151 l_ptr->name, l_ptr->net_plane);
152 152
153 if (!active[0]) { 153 if (!active[0]) {
154 active[0] = active[1] = l_ptr; 154 active[0] = active[1] = l_ptr;
@@ -208,11 +208,11 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
208 208
209 if (!tipc_link_is_active(l_ptr)) { 209 if (!tipc_link_is_active(l_ptr)) {
210 pr_info("Lost standby link <%s> on network plane %c\n", 210 pr_info("Lost standby link <%s> on network plane %c\n",
211 l_ptr->name, l_ptr->b_ptr->net_plane); 211 l_ptr->name, l_ptr->net_plane);
212 return; 212 return;
213 } 213 }
214 pr_info("Lost link <%s> on network plane %c\n", 214 pr_info("Lost link <%s> on network plane %c\n",
215 l_ptr->name, l_ptr->b_ptr->net_plane); 215 l_ptr->name, l_ptr->net_plane);
216 216
217 active = &n_ptr->active_links[0]; 217 active = &n_ptr->active_links[0];
218 if (active[0] == l_ptr) 218 if (active[0] == l_ptr)
@@ -239,7 +239,7 @@ int tipc_node_is_up(struct tipc_node *n_ptr)
239 239
240void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 240void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
241{ 241{
242 n_ptr->links[l_ptr->b_ptr->identity] = l_ptr; 242 n_ptr->links[l_ptr->bearer_id] = l_ptr;
243 spin_lock_bh(&node_list_lock); 243 spin_lock_bh(&node_list_lock);
244 tipc_num_links++; 244 tipc_num_links++;
245 spin_unlock_bh(&node_list_lock); 245 spin_unlock_bh(&node_list_lock);