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. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									902fefb82e
								
							
						
					
					
						commit
						87a2fd286a
					
				| @ -2156,6 +2156,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); | ||||
| 	int tp_len, size_max; | ||||
| 	unsigned char *addr; | ||||
| 	int len_sum = 0; | ||||
| @ -2198,10 +2199,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; | ||||
| 		} | ||||
| 
 | ||||
| @ -2255,10 +2256,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; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user