udp: fix poll()
Michael reported an UDP breakage caused by the commitb65ac44674
("udp: try to avoid 2 cache miss on dequeue"). The function __first_packet_length() can update the checksum bits of the pending skb, making the scratched area out-of-sync, and setting skb->csum, if the skb was previously in need of checksum validation. On later recvmsg() for such skb, checksum validation will be invoked again - due to the wrong udp_skb_csum_unnecessary() value - and will fail, causing the valid skb to be dropped. This change addresses the issue refreshing the scratch area in __first_packet_length() after the possible checksum update. Fixes:b65ac44674
("udp: try to avoid 2 cache miss on dequeue") Reported-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4b943faedf
commit
9bd780f5e0
1 changed files with 17 additions and 10 deletions
|
@ -1446,16 +1446,23 @@ static struct sk_buff *__first_packet_length(struct sock *sk,
|
|||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
while ((skb = skb_peek(rcvq)) != NULL &&
|
||||
udp_lib_checksum_complete(skb)) {
|
||||
__UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS,
|
||||
IS_UDPLITE(sk));
|
||||
__UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS,
|
||||
IS_UDPLITE(sk));
|
||||
atomic_inc(&sk->sk_drops);
|
||||
__skb_unlink(skb, rcvq);
|
||||
*total += skb->truesize;
|
||||
kfree_skb(skb);
|
||||
while ((skb = skb_peek(rcvq)) != NULL) {
|
||||
if (udp_lib_checksum_complete(skb)) {
|
||||
__UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS,
|
||||
IS_UDPLITE(sk));
|
||||
__UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS,
|
||||
IS_UDPLITE(sk));
|
||||
atomic_inc(&sk->sk_drops);
|
||||
__skb_unlink(skb, rcvq);
|
||||
*total += skb->truesize;
|
||||
kfree_skb(skb);
|
||||
} else {
|
||||
/* the csum related bits could be changed, refresh
|
||||
* the scratch area
|
||||
*/
|
||||
udp_set_dev_scratch(skb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return skb;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue