From 41304bf063e1e148c1e988ad2423ac7869c08bec Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 15 Jan 2014 16:25:35 +0100 Subject: [PATCH] packet: don't unconditionally schedule() in case of MSG_DONTWAIT In tpacket_snd(), when we've discovered a first frame that is not in status TP_STATUS_SEND_REQUEST, and return a NULL buffer, we exit the send routine in case of MSG_DONTWAIT, since we've finished traversing the mmaped send ring buffer and don't care about pending frames. While doing so, we still unconditionally call an expensive schedule() in the packet_current_frame() "error" path, which is unnecessary in this case since it's enough to just quit the function. Also, in case MSG_DONTWAIT is not set, we should rather test for need_resched() first and do schedule() only if necessary since meanwhile pending frames could already have finished processing and called skb destructor. Change-Id: Ic83ad580914e70fbffb871ded8ee9045f4679da4 Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/packet/af_packet.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 43098bcf18de..26474e8f1e0f 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2103,6 +2103,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) int err, reserve = 0; void *ph; struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; + bool need_wait = !(msg->msg_flags & MSG_DONTWAIT); unsigned char *addr = NULL; int tp_len, size_max; int len_sum = 0; @@ -2150,10 +2151,10 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) do { ph = packet_current_frame(po, &po->tx_ring, - TP_STATUS_SEND_REQUEST); - + TP_STATUS_SEND_REQUEST); if (unlikely(ph == NULL)) { - schedule(); + if (need_wait && need_resched()) + schedule(); continue; } @@ -2206,10 +2207,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) } packet_increment_head(&po->tx_ring); len_sum += tp_len; - } while (likely((ph != NULL) || - ((!(msg->msg_flags & MSG_DONTWAIT)) && - (atomic_read(&po->tx_ring.pending)))) - ); + } while (likely((ph != NULL) || (need_wait && + atomic_read(&po->tx_ring.pending)))); err = len_sum; goto out_put;