aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-07-16 16:54:21 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-20 23:41:14 -0400
commitd39bbd445dc44259c77bbbc8aadcce7dcdba39cc (patch)
treec82e8d60ae0426c7e0605374e285bf606fdd4ed8 /net/tipc/link.c
parentd3a43b907ae688af6cb753c53cd7de05f3c1ba85 (diff)
tipc: move link input queue to tipc_node
At present, the link input queue and the name distributor receive queues are fields aggregated in struct tipc_link. This is a hazard, because a link might be deleted while a receiving socket still keeps reference to one of the queues. This commit fixes this bug. However, rather than adding yet another reference counter to the critical data path, we move the two queues to safe ground inside struct tipc_node, which is already protected, and let the link code only handle references to the queues. This is also in line with planned later changes in this area. Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 03372a7e98df..f8e0e2ceceb4 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -227,7 +227,9 @@ static void link_set_timer(struct tipc_link *link, unsigned long time)
227 */ 227 */
228struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, 228struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
229 struct tipc_bearer *b_ptr, 229 struct tipc_bearer *b_ptr,
230 const struct tipc_media_addr *media_addr) 230 const struct tipc_media_addr *media_addr,
231 struct sk_buff_head *inputq,
232 struct sk_buff_head *namedq)
231{ 233{
232 struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id); 234 struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id);
233 struct tipc_link *l_ptr; 235 struct tipc_link *l_ptr;
@@ -289,8 +291,9 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
289 __skb_queue_head_init(&l_ptr->backlogq); 291 __skb_queue_head_init(&l_ptr->backlogq);
290 __skb_queue_head_init(&l_ptr->deferdq); 292 __skb_queue_head_init(&l_ptr->deferdq);
291 skb_queue_head_init(&l_ptr->wakeupq); 293 skb_queue_head_init(&l_ptr->wakeupq);
292 skb_queue_head_init(&l_ptr->inputq); 294 l_ptr->inputq = inputq;
293 skb_queue_head_init(&l_ptr->namedq); 295 l_ptr->namedq = namedq;
296 skb_queue_head_init(l_ptr->inputq);
294 link_reset_statistics(l_ptr); 297 link_reset_statistics(l_ptr);
295 tipc_node_attach_link(n_ptr, l_ptr); 298 tipc_node_attach_link(n_ptr, l_ptr);
296 setup_timer(&l_ptr->timer, link_timeout, (unsigned long)l_ptr); 299 setup_timer(&l_ptr->timer, link_timeout, (unsigned long)l_ptr);
@@ -391,8 +394,8 @@ void link_prepare_wakeup(struct tipc_link *l)
391 if ((pnd[imp] + l->backlog[imp].len) >= lim) 394 if ((pnd[imp] + l->backlog[imp].len) >= lim)
392 break; 395 break;
393 skb_unlink(skb, &l->wakeupq); 396 skb_unlink(skb, &l->wakeupq);
394 skb_queue_tail(&l->inputq, skb); 397 skb_queue_tail(l->inputq, skb);
395 l->owner->inputq = &l->inputq; 398 l->owner->inputq = l->inputq;
396 l->owner->action_flags |= TIPC_MSG_EVT; 399 l->owner->action_flags |= TIPC_MSG_EVT;
397 } 400 }
398} 401}
@@ -465,7 +468,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
465 __skb_queue_purge(&l_ptr->transmq); 468 __skb_queue_purge(&l_ptr->transmq);
466 __skb_queue_purge(&l_ptr->deferdq); 469 __skb_queue_purge(&l_ptr->deferdq);
467 if (!owner->inputq) 470 if (!owner->inputq)
468 owner->inputq = &l_ptr->inputq; 471 owner->inputq = l_ptr->inputq;
469 skb_queue_splice_init(&l_ptr->wakeupq, owner->inputq); 472 skb_queue_splice_init(&l_ptr->wakeupq, owner->inputq);
470 if (!skb_queue_empty(owner->inputq)) 473 if (!skb_queue_empty(owner->inputq))
471 owner->action_flags |= TIPC_MSG_EVT; 474 owner->action_flags |= TIPC_MSG_EVT;
@@ -962,7 +965,7 @@ static bool link_synch(struct tipc_link *l)
962 965
963 /* Is it still in the input queue ? */ 966 /* Is it still in the input queue ? */
964 post_synch = mod(pl->rcv_nxt - l->synch_point) - 1; 967 post_synch = mod(pl->rcv_nxt - l->synch_point) - 1;
965 if (skb_queue_len(&pl->inputq) > post_synch) 968 if (skb_queue_len(pl->inputq) > post_synch)
966 return false; 969 return false;
967synched: 970synched:
968 l->flags &= ~LINK_SYNCHING; 971 l->flags &= ~LINK_SYNCHING;
@@ -1141,16 +1144,16 @@ static bool tipc_data_input(struct tipc_link *link, struct sk_buff *skb)
1141 case TIPC_HIGH_IMPORTANCE: 1144 case TIPC_HIGH_IMPORTANCE:
1142 case TIPC_CRITICAL_IMPORTANCE: 1145 case TIPC_CRITICAL_IMPORTANCE:
1143 case CONN_MANAGER: 1146 case CONN_MANAGER:
1144 if (tipc_skb_queue_tail(&link->inputq, skb, dport)) { 1147 if (tipc_skb_queue_tail(link->inputq, skb, dport)) {
1145 node->inputq = &link->inputq; 1148 node->inputq = link->inputq;
1146 node->action_flags |= TIPC_MSG_EVT; 1149 node->action_flags |= TIPC_MSG_EVT;
1147 } 1150 }
1148 return true; 1151 return true;
1149 case NAME_DISTRIBUTOR: 1152 case NAME_DISTRIBUTOR:
1150 node->bclink.recv_permitted = true; 1153 node->bclink.recv_permitted = true;
1151 node->namedq = &link->namedq; 1154 node->namedq = link->namedq;
1152 skb_queue_tail(&link->namedq, skb); 1155 skb_queue_tail(link->namedq, skb);
1153 if (skb_queue_len(&link->namedq) == 1) 1156 if (skb_queue_len(link->namedq) == 1)
1154 node->action_flags |= TIPC_NAMED_MSG_EVT; 1157 node->action_flags |= TIPC_NAMED_MSG_EVT;
1155 return true; 1158 return true;
1156 case MSG_BUNDLER: 1159 case MSG_BUNDLER: