diff options
| author | Kretschmer, Mathias <mathias.kretschmer@fokus.fraunhofer.de> | 2015-05-08 09:44:37 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-05-10 19:40:08 -0400 |
| commit | fbf33a2802f71dba06faa948af805884ff16a2ab (patch) | |
| tree | 94a5d1b3c78f23b9a82bfbbdf97c17c9cfa29abc /net/packet | |
| parent | cd9c39977754d9602b5783a44f4af09530a58254 (diff) | |
af_packet / TX_RING not fully non-blocking (w/ MSG_DONTWAIT).
This patch fixes an issue where the send(MSG_DONTWAIT) call
on a TX_RING is not fully non-blocking in cases where the device's sndBuf is
full. We pass nonblock=true to sock_alloc_send_skb() and return any possibly
occuring error code (most likely EGAIN) to the caller. As the fast-path stays
as it is, we keep the unlikely() around skb == NULL.
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet')
| -rw-r--r-- | net/packet/af_packet.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 5102c3cc4eec..b5989c6ee551 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -2311,11 +2311,14 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 2311 | tlen = dev->needed_tailroom; | 2311 | tlen = dev->needed_tailroom; |
| 2312 | skb = sock_alloc_send_skb(&po->sk, | 2312 | skb = sock_alloc_send_skb(&po->sk, |
| 2313 | hlen + tlen + sizeof(struct sockaddr_ll), | 2313 | hlen + tlen + sizeof(struct sockaddr_ll), |
| 2314 | 0, &err); | 2314 | !need_wait, &err); |
| 2315 | 2315 | ||
| 2316 | if (unlikely(skb == NULL)) | 2316 | if (unlikely(skb == NULL)) { |
| 2317 | /* we assume the socket was initially writeable ... */ | ||
| 2318 | if (likely(len_sum > 0)) | ||
| 2319 | err = len_sum; | ||
| 2317 | goto out_status; | 2320 | goto out_status; |
| 2318 | 2321 | } | |
| 2319 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, | 2322 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, |
| 2320 | addr, hlen); | 2323 | addr, hlen); |
| 2321 | if (tp_len > dev->mtu + dev->hard_header_len) { | 2324 | if (tp_len > dev->mtu + dev->hard_header_len) { |
