aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-07-16 16:54:23 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-20 23:41:15 -0400
commit22d85c79428b8ca9a01623aa3e3a1fe29a30a119 (patch)
treebc72ee5256301d591616db2270c45929be2d58d6 /net/tipc
parent36e78a463b26c9b8017a2e11dcd6c4b8e34b4161 (diff)
tipc: change sk_buffer handling in tipc_link_xmit()
When the function tipc_link_xmit() is given a buffer list for transmission, it currently consumes the list both when transmission is successful and when it fails, except for the special case when it encounters link congestion. This behavior is inconsistent, and needs to be corrected if we want to avoid problems in later commits in this series. In this commit, we change this to let the function consume the list only when transmission is successful, and leave the list with the sender in all other cases. We also modifiy the socket code so that it adapts to this change, i.e., purges the list when a non-congestion error code is returned. 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')
-rw-r--r--net/tipc/bcast.c5
-rw-r--r--net/tipc/link.c23
-rw-r--r--net/tipc/socket.c49
3 files changed, 37 insertions, 40 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 59b2f2a538e1..295bdc26f103 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -358,10 +358,9 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list)
358 358
359 /* Prepare clone of message for local node */ 359 /* Prepare clone of message for local node */
360 skb = tipc_msg_reassemble(list); 360 skb = tipc_msg_reassemble(list);
361 if (unlikely(!skb)) { 361 if (unlikely(!skb))
362 __skb_queue_purge(list);
363 return -EHOSTUNREACH; 362 return -EHOSTUNREACH;
364 } 363
365 /* Broadcast to all nodes */ 364 /* Broadcast to all nodes */
366 if (likely(bclink)) { 365 if (likely(bclink)) {
367 tipc_bclink_lock(net); 366 tipc_bclink_lock(net);
diff --git a/net/tipc/link.c b/net/tipc/link.c
index f8e0e2ceceb4..ea32679b6737 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -340,7 +340,7 @@ void tipc_link_delete_list(struct net *net, unsigned int bearer_id)
340 * @link: congested link 340 * @link: congested link
341 * @list: message that was attempted sent 341 * @list: message that was attempted sent
342 * Create pseudo msg to send back to user when congestion abates 342 * Create pseudo msg to send back to user when congestion abates
343 * Only consumes message if there is an error 343 * Does not consume buffer list
344 */ 344 */
345static int link_schedule_user(struct tipc_link *link, struct sk_buff_head *list) 345static int link_schedule_user(struct tipc_link *link, struct sk_buff_head *list)
346{ 346{
@@ -354,7 +354,7 @@ static int link_schedule_user(struct tipc_link *link, struct sk_buff_head *list)
354 if (unlikely(imp > TIPC_CRITICAL_IMPORTANCE)) { 354 if (unlikely(imp > TIPC_CRITICAL_IMPORTANCE)) {
355 pr_warn("%s<%s>, send queue full", link_rst_msg, link->name); 355 pr_warn("%s<%s>, send queue full", link_rst_msg, link->name);
356 tipc_link_reset(link); 356 tipc_link_reset(link);
357 goto err; 357 return -ENOBUFS;
358 } 358 }
359 /* Non-blocking sender: */ 359 /* Non-blocking sender: */
360 if (TIPC_SKB_CB(skb_peek(list))->wakeup_pending) 360 if (TIPC_SKB_CB(skb_peek(list))->wakeup_pending)
@@ -364,15 +364,12 @@ static int link_schedule_user(struct tipc_link *link, struct sk_buff_head *list)
364 skb = tipc_msg_create(SOCK_WAKEUP, 0, INT_H_SIZE, 0, 364 skb = tipc_msg_create(SOCK_WAKEUP, 0, INT_H_SIZE, 0,
365 addr, addr, oport, 0, 0); 365 addr, addr, oport, 0, 0);
366 if (!skb) 366 if (!skb)
367 goto err; 367 return -ENOBUFS;
368 TIPC_SKB_CB(skb)->chain_sz = skb_queue_len(list); 368 TIPC_SKB_CB(skb)->chain_sz = skb_queue_len(list);
369 TIPC_SKB_CB(skb)->chain_imp = imp; 369 TIPC_SKB_CB(skb)->chain_imp = imp;
370 skb_queue_tail(&link->wakeupq, skb); 370 skb_queue_tail(&link->wakeupq, skb);
371 link->stats.link_congs++; 371 link->stats.link_congs++;
372 return -ELINKCONG; 372 return -ELINKCONG;
373err:
374 __skb_queue_purge(list);
375 return -ENOBUFS;
376} 373}
377 374
378/** 375/**
@@ -641,8 +638,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
641 * @link: link to use 638 * @link: link to use
642 * @list: chain of buffers containing message 639 * @list: chain of buffers containing message
643 * 640 *
644 * Consumes the buffer chain, except when returning -ELINKCONG, 641 * Consumes the buffer chain, except when returning an error code,
645 * since the caller then may want to make more send attempts.
646 * Returns 0 if success, or errno: -ELINKCONG, -EMSGSIZE or -ENOBUFS 642 * Returns 0 if success, or errno: -ELINKCONG, -EMSGSIZE or -ENOBUFS
647 * Messages at TIPC_SYSTEM_IMPORTANCE are always accepted 643 * Messages at TIPC_SYSTEM_IMPORTANCE are always accepted
648 */ 644 */
@@ -666,10 +662,9 @@ int __tipc_link_xmit(struct net *net, struct tipc_link *link,
666 if (unlikely(link->backlog[i].len >= link->backlog[i].limit)) 662 if (unlikely(link->backlog[i].len >= link->backlog[i].limit))
667 return link_schedule_user(link, list); 663 return link_schedule_user(link, list);
668 } 664 }
669 if (unlikely(msg_size(msg) > mtu)) { 665 if (unlikely(msg_size(msg) > mtu))
670 __skb_queue_purge(list);
671 return -EMSGSIZE; 666 return -EMSGSIZE;
672 } 667
673 /* Prepare each packet for sending, and add to relevant queue: */ 668 /* Prepare each packet for sending, and add to relevant queue: */
674 while (skb_queue_len(list)) { 669 while (skb_queue_len(list)) {
675 skb = skb_peek(list); 670 skb = skb_peek(list);
@@ -722,7 +717,7 @@ static int __tipc_link_xmit_skb(struct tipc_link *link, struct sk_buff *skb)
722 717
723/* tipc_link_xmit_skb(): send single buffer to destination 718/* tipc_link_xmit_skb(): send single buffer to destination
724 * Buffers sent via this functon are generally TIPC_SYSTEM_IMPORTANCE 719 * Buffers sent via this functon are generally TIPC_SYSTEM_IMPORTANCE
725 * messages, which will not be rejected 720 * messages, which will not cause link congestion
726 * The only exception is datagram messages rerouted after secondary 721 * The only exception is datagram messages rerouted after secondary
727 * lookup, which are rare and safe to dispose of anyway. 722 * lookup, which are rare and safe to dispose of anyway.
728 * TODO: Return real return value, and let callers use 723 * TODO: Return real return value, and let callers use
@@ -736,7 +731,7 @@ int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dnode,
736 731
737 skb2list(skb, &head); 732 skb2list(skb, &head);
738 rc = tipc_link_xmit(net, &head, dnode, selector); 733 rc = tipc_link_xmit(net, &head, dnode, selector);
739 if (rc == -ELINKCONG) 734 if (rc)
740 kfree_skb(skb); 735 kfree_skb(skb);
741 return 0; 736 return 0;
742} 737}
@@ -748,7 +743,7 @@ int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dnode,
748 * @dsz: amount of user data to be sent 743 * @dsz: amount of user data to be sent
749 * @dnode: address of destination node 744 * @dnode: address of destination node
750 * @selector: a number used for deterministic link selection 745 * @selector: a number used for deterministic link selection
751 * Consumes the buffer chain, except when returning -ELINKCONG 746 * Consumes the buffer chain, except when returning error
752 * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE 747 * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE
753 */ 748 */
754int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dnode, 749int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dnode,
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 3a7567f690f3..87fef25f6519 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -686,21 +686,22 @@ new_mtu:
686 686
687 do { 687 do {
688 rc = tipc_bclink_xmit(net, pktchain); 688 rc = tipc_bclink_xmit(net, pktchain);
689 if (likely(rc >= 0)) { 689 if (likely(!rc))
690 rc = dsz; 690 return dsz;
691 break; 691
692 if (rc == -ELINKCONG) {
693 tsk->link_cong = 1;
694 rc = tipc_wait_for_sndmsg(sock, &timeo);
695 if (!rc)
696 continue;
692 } 697 }
698 __skb_queue_purge(pktchain);
693 if (rc == -EMSGSIZE) { 699 if (rc == -EMSGSIZE) {
694 msg->msg_iter = save; 700 msg->msg_iter = save;
695 goto new_mtu; 701 goto new_mtu;
696 } 702 }
697 if (rc != -ELINKCONG) 703 break;
698 break; 704 } while (1);
699 tipc_sk(sk)->link_cong = 1;
700 rc = tipc_wait_for_sndmsg(sock, &timeo);
701 if (rc)
702 __skb_queue_purge(pktchain);
703 } while (!rc);
704 return rc; 705 return rc;
705} 706}
706 707
@@ -925,23 +926,24 @@ new_mtu:
925 skb = skb_peek(pktchain); 926 skb = skb_peek(pktchain);
926 TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong; 927 TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong;
927 rc = tipc_link_xmit(net, pktchain, dnode, tsk->portid); 928 rc = tipc_link_xmit(net, pktchain, dnode, tsk->portid);
928 if (likely(rc >= 0)) { 929 if (likely(!rc)) {
929 if (sock->state != SS_READY) 930 if (sock->state != SS_READY)
930 sock->state = SS_CONNECTING; 931 sock->state = SS_CONNECTING;
931 rc = dsz; 932 return dsz;
932 break;
933 } 933 }
934 if (rc == -ELINKCONG) {
935 tsk->link_cong = 1;
936 rc = tipc_wait_for_sndmsg(sock, &timeo);
937 if (!rc)
938 continue;
939 }
940 __skb_queue_purge(pktchain);
934 if (rc == -EMSGSIZE) { 941 if (rc == -EMSGSIZE) {
935 m->msg_iter = save; 942 m->msg_iter = save;
936 goto new_mtu; 943 goto new_mtu;
937 } 944 }
938 if (rc != -ELINKCONG) 945 break;
939 break; 946 } while (1);
940 tsk->link_cong = 1;
941 rc = tipc_wait_for_sndmsg(sock, &timeo);
942 if (rc)
943 __skb_queue_purge(pktchain);
944 } while (!rc);
945 947
946 return rc; 948 return rc;
947} 949}
@@ -1048,10 +1050,11 @@ next:
1048 tsk->sent_unacked++; 1050 tsk->sent_unacked++;
1049 sent += send; 1051 sent += send;
1050 if (sent == dsz) 1052 if (sent == dsz)
1051 break; 1053 return dsz;
1052 goto next; 1054 goto next;
1053 } 1055 }
1054 if (rc == -EMSGSIZE) { 1056 if (rc == -EMSGSIZE) {
1057 __skb_queue_purge(pktchain);
1055 tsk->max_pkt = tipc_node_get_mtu(net, dnode, 1058 tsk->max_pkt = tipc_node_get_mtu(net, dnode,
1056 portid); 1059 portid);
1057 m->msg_iter = save; 1060 m->msg_iter = save;
@@ -1059,13 +1062,13 @@ next:
1059 } 1062 }
1060 if (rc != -ELINKCONG) 1063 if (rc != -ELINKCONG)
1061 break; 1064 break;
1065
1062 tsk->link_cong = 1; 1066 tsk->link_cong = 1;
1063 } 1067 }
1064 rc = tipc_wait_for_sndpkt(sock, &timeo); 1068 rc = tipc_wait_for_sndpkt(sock, &timeo);
1065 if (rc)
1066 __skb_queue_purge(pktchain);
1067 } while (!rc); 1069 } while (!rc);
1068 1070
1071 __skb_queue_purge(pktchain);
1069 return sent ? sent : rc; 1072 return sent ? sent : rc;
1070} 1073}
1071 1074