diff options
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 14bc654b6842..1d58ce829dca 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -388,7 +388,7 @@ static int compute_score(struct sock *sk, struct net *net, | |||
388 | return -1; | 388 | return -1; |
389 | score += 4; | 389 | score += 4; |
390 | 390 | ||
391 | if (sk->sk_incoming_cpu == raw_smp_processor_id()) | 391 | if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) |
392 | score++; | 392 | score++; |
393 | return score; | 393 | return score; |
394 | } | 394 | } |
@@ -1316,6 +1316,20 @@ static void udp_set_dev_scratch(struct sk_buff *skb) | |||
1316 | scratch->_tsize_state |= UDP_SKB_IS_STATELESS; | 1316 | scratch->_tsize_state |= UDP_SKB_IS_STATELESS; |
1317 | } | 1317 | } |
1318 | 1318 | ||
1319 | static void udp_skb_csum_unnecessary_set(struct sk_buff *skb) | ||
1320 | { | ||
1321 | /* We come here after udp_lib_checksum_complete() returned 0. | ||
1322 | * This means that __skb_checksum_complete() might have | ||
1323 | * set skb->csum_valid to 1. | ||
1324 | * On 64bit platforms, we can set csum_unnecessary | ||
1325 | * to true, but only if the skb is not shared. | ||
1326 | */ | ||
1327 | #if BITS_PER_LONG == 64 | ||
1328 | if (!skb_shared(skb)) | ||
1329 | udp_skb_scratch(skb)->csum_unnecessary = true; | ||
1330 | #endif | ||
1331 | } | ||
1332 | |||
1319 | static int udp_skb_truesize(struct sk_buff *skb) | 1333 | static int udp_skb_truesize(struct sk_buff *skb) |
1320 | { | 1334 | { |
1321 | return udp_skb_scratch(skb)->_tsize_state & ~UDP_SKB_IS_STATELESS; | 1335 | return udp_skb_scratch(skb)->_tsize_state & ~UDP_SKB_IS_STATELESS; |
@@ -1550,10 +1564,7 @@ static struct sk_buff *__first_packet_length(struct sock *sk, | |||
1550 | *total += skb->truesize; | 1564 | *total += skb->truesize; |
1551 | kfree_skb(skb); | 1565 | kfree_skb(skb); |
1552 | } else { | 1566 | } else { |
1553 | /* the csum related bits could be changed, refresh | 1567 | udp_skb_csum_unnecessary_set(skb); |
1554 | * the scratch area | ||
1555 | */ | ||
1556 | udp_set_dev_scratch(skb); | ||
1557 | break; | 1568 | break; |
1558 | } | 1569 | } |
1559 | } | 1570 | } |
@@ -1577,7 +1588,7 @@ static int first_packet_length(struct sock *sk) | |||
1577 | 1588 | ||
1578 | spin_lock_bh(&rcvq->lock); | 1589 | spin_lock_bh(&rcvq->lock); |
1579 | skb = __first_packet_length(sk, rcvq, &total); | 1590 | skb = __first_packet_length(sk, rcvq, &total); |
1580 | if (!skb && !skb_queue_empty(sk_queue)) { | 1591 | if (!skb && !skb_queue_empty_lockless(sk_queue)) { |
1581 | spin_lock(&sk_queue->lock); | 1592 | spin_lock(&sk_queue->lock); |
1582 | skb_queue_splice_tail_init(sk_queue, rcvq); | 1593 | skb_queue_splice_tail_init(sk_queue, rcvq); |
1583 | spin_unlock(&sk_queue->lock); | 1594 | spin_unlock(&sk_queue->lock); |
@@ -1650,7 +1661,7 @@ struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags, | |||
1650 | return skb; | 1661 | return skb; |
1651 | } | 1662 | } |
1652 | 1663 | ||
1653 | if (skb_queue_empty(sk_queue)) { | 1664 | if (skb_queue_empty_lockless(sk_queue)) { |
1654 | spin_unlock_bh(&queue->lock); | 1665 | spin_unlock_bh(&queue->lock); |
1655 | goto busy_check; | 1666 | goto busy_check; |
1656 | } | 1667 | } |
@@ -1676,7 +1687,7 @@ busy_check: | |||
1676 | break; | 1687 | break; |
1677 | 1688 | ||
1678 | sk_busy_loop(sk, flags & MSG_DONTWAIT); | 1689 | sk_busy_loop(sk, flags & MSG_DONTWAIT); |
1679 | } while (!skb_queue_empty(sk_queue)); | 1690 | } while (!skb_queue_empty_lockless(sk_queue)); |
1680 | 1691 | ||
1681 | /* sk_queue is empty, reader_queue may contain peeked packets */ | 1692 | /* sk_queue is empty, reader_queue may contain peeked packets */ |
1682 | } while (timeo && | 1693 | } while (timeo && |
@@ -2712,7 +2723,7 @@ __poll_t udp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
2712 | __poll_t mask = datagram_poll(file, sock, wait); | 2723 | __poll_t mask = datagram_poll(file, sock, wait); |
2713 | struct sock *sk = sock->sk; | 2724 | struct sock *sk = sock->sk; |
2714 | 2725 | ||
2715 | if (!skb_queue_empty(&udp_sk(sk)->reader_queue)) | 2726 | if (!skb_queue_empty_lockless(&udp_sk(sk)->reader_queue)) |
2716 | mask |= EPOLLIN | EPOLLRDNORM; | 2727 | mask |= EPOLLIN | EPOLLRDNORM; |
2717 | 2728 | ||
2718 | /* Check for false positives due to checksum errors */ | 2729 | /* Check for false positives due to checksum errors */ |