Skip to content

Commit 22d85c7

Browse files
Jon Paul Maloydavem330
authored andcommitted
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>
1 parent 36e78a4 commit 22d85c7

File tree

3 files changed

+37
-40
lines changed

3 files changed

+37
-40
lines changed

net/tipc/bcast.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,9 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list)
358358

359359
/* Prepare clone of message for local node */
360360
skb = tipc_msg_reassemble(list);
361-
if (unlikely(!skb)) {
362-
__skb_queue_purge(list);
361+
if (unlikely(!skb))
363362
return -EHOSTUNREACH;
364-
}
363+
365364
/* Broadcast to all nodes */
366365
if (likely(bclink)) {
367366
tipc_bclink_lock(net);

net/tipc/link.c

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ void tipc_link_delete_list(struct net *net, unsigned int bearer_id)
340340
* @link: congested link
341341
* @list: message that was attempted sent
342342
* 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
344344
*/
345345
static int link_schedule_user(struct tipc_link *link, struct sk_buff_head *list)
346346
{
@@ -354,7 +354,7 @@ static int link_schedule_user(struct tipc_link *link, struct sk_buff_head *list)
354354
if (unlikely(imp > TIPC_CRITICAL_IMPORTANCE)) {
355355
pr_warn("%s<%s>, send queue full", link_rst_msg, link->name);
356356
tipc_link_reset(link);
357-
goto err;
357+
return -ENOBUFS;
358358
}
359359
/* Non-blocking sender: */
360360
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)
364364
skb = tipc_msg_create(SOCK_WAKEUP, 0, INT_H_SIZE, 0,
365365
addr, addr, oport, 0, 0);
366366
if (!skb)
367-
goto err;
367+
return -ENOBUFS;
368368
TIPC_SKB_CB(skb)->chain_sz = skb_queue_len(list);
369369
TIPC_SKB_CB(skb)->chain_imp = imp;
370370
skb_queue_tail(&link->wakeupq, skb);
371371
link->stats.link_congs++;
372372
return -ELINKCONG;
373-
err:
374-
__skb_queue_purge(list);
375-
return -ENOBUFS;
376373
}
377374

378375
/**
@@ -641,8 +638,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
641638
* @link: link to use
642639
* @list: chain of buffers containing message
643640
*
644-
* Consumes the buffer chain, except when returning -ELINKCONG,
645-
* since the caller then may want to make more send attempts.
641+
* Consumes the buffer chain, except when returning an error code,
646642
* Returns 0 if success, or errno: -ELINKCONG, -EMSGSIZE or -ENOBUFS
647643
* Messages at TIPC_SYSTEM_IMPORTANCE are always accepted
648644
*/
@@ -666,10 +662,9 @@ int __tipc_link_xmit(struct net *net, struct tipc_link *link,
666662
if (unlikely(link->backlog[i].len >= link->backlog[i].limit))
667663
return link_schedule_user(link, list);
668664
}
669-
if (unlikely(msg_size(msg) > mtu)) {
670-
__skb_queue_purge(list);
665+
if (unlikely(msg_size(msg) > mtu))
671666
return -EMSGSIZE;
672-
}
667+
673668
/* Prepare each packet for sending, and add to relevant queue: */
674669
while (skb_queue_len(list)) {
675670
skb = skb_peek(list);
@@ -722,7 +717,7 @@ static int __tipc_link_xmit_skb(struct tipc_link *link, struct sk_buff *skb)
722717

723718
/* tipc_link_xmit_skb(): send single buffer to destination
724719
* 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
726721
* The only exception is datagram messages rerouted after secondary
727722
* lookup, which are rare and safe to dispose of anyway.
728723
* 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,
736731

737732
skb2list(skb, &head);
738733
rc = tipc_link_xmit(net, &head, dnode, selector);
739-
if (rc == -ELINKCONG)
734+
if (rc)
740735
kfree_skb(skb);
741736
return 0;
742737
}
@@ -748,7 +743,7 @@ int tipc_link_xmit_skb(struct net *net, struct sk_buff *skb, u32 dnode,
748743
* @dsz: amount of user data to be sent
749744
* @dnode: address of destination node
750745
* @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
752747
* Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE
753748
*/
754749
int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dnode,

net/tipc/socket.c

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -686,21 +686,22 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq,
686686

687687
do {
688688
rc = tipc_bclink_xmit(net, pktchain);
689-
if (likely(rc >= 0)) {
690-
rc = dsz;
691-
break;
689+
if (likely(!rc))
690+
return dsz;
691+
692+
if (rc == -ELINKCONG) {
693+
tsk->link_cong = 1;
694+
rc = tipc_wait_for_sndmsg(sock, &timeo);
695+
if (!rc)
696+
continue;
692697
}
698+
__skb_queue_purge(pktchain);
693699
if (rc == -EMSGSIZE) {
694700
msg->msg_iter = save;
695701
goto new_mtu;
696702
}
697-
if (rc != -ELINKCONG)
698-
break;
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);
703+
break;
704+
} while (1);
704705
return rc;
705706
}
706707

@@ -925,23 +926,24 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz)
925926
skb = skb_peek(pktchain);
926927
TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong;
927928
rc = tipc_link_xmit(net, pktchain, dnode, tsk->portid);
928-
if (likely(rc >= 0)) {
929+
if (likely(!rc)) {
929930
if (sock->state != SS_READY)
930931
sock->state = SS_CONNECTING;
931-
rc = dsz;
932-
break;
932+
return dsz;
933933
}
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);
934941
if (rc == -EMSGSIZE) {
935942
m->msg_iter = save;
936943
goto new_mtu;
937944
}
938-
if (rc != -ELINKCONG)
939-
break;
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+
break;
946+
} while (1);
945947

946948
return rc;
947949
}
@@ -1048,24 +1050,25 @@ static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz)
10481050
tsk->sent_unacked++;
10491051
sent += send;
10501052
if (sent == dsz)
1051-
break;
1053+
return dsz;
10521054
goto next;
10531055
}
10541056
if (rc == -EMSGSIZE) {
1057+
__skb_queue_purge(pktchain);
10551058
tsk->max_pkt = tipc_node_get_mtu(net, dnode,
10561059
portid);
10571060
m->msg_iter = save;
10581061
goto next;
10591062
}
10601063
if (rc != -ELINKCONG)
10611064
break;
1065+
10621066
tsk->link_cong = 1;
10631067
}
10641068
rc = tipc_wait_for_sndpkt(sock, &timeo);
1065-
if (rc)
1066-
__skb_queue_purge(pktchain);
10671069
} while (!rc);
10681070

1071+
__skb_queue_purge(pktchain);
10691072
return sent ? sent : rc;
10701073
}
10711074

0 commit comments

Comments
 (0)