| From d5818b4d2a150f5e1715c568651dda195322d27d Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Wed, 12 Jun 2019 09:52:32 -0700 |
| Subject: [PATCH] net/packet: remove locking from packet_rcv_has_room() |
| |
| commit 3a2bb84e4aeab5c90d16e1cd17dbaa17631af529 upstream. |
| |
| __packet_rcv_has_room() can now be run without lock being held. |
| |
| po->pressure is only a non persistent hint, we can mark |
| all read/write accesses with READ_ONCE()/WRITE_ONCE() |
| to document the fact that the field could be written |
| without any synchronization. |
| |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c |
| index beb6770c1bec..d0ab6bbbb75c 100644 |
| --- a/net/packet/af_packet.c |
| +++ b/net/packet/af_packet.c |
| @@ -1262,15 +1262,13 @@ static int __packet_rcv_has_room(const struct packet_sock *po, |
| |
| static int packet_rcv_has_room(struct packet_sock *po, struct sk_buff *skb) |
| { |
| - int ret; |
| - bool has_room; |
| + int pressure, ret; |
| |
| - spin_lock_bh(&po->sk.sk_receive_queue.lock); |
| ret = __packet_rcv_has_room(po, skb); |
| - has_room = ret == ROOM_NORMAL; |
| - if (po->pressure == has_room) |
| - po->pressure = !has_room; |
| - spin_unlock_bh(&po->sk.sk_receive_queue.lock); |
| + pressure = ret != ROOM_NORMAL; |
| + |
| + if (READ_ONCE(po->pressure) != pressure) |
| + WRITE_ONCE(po->pressure, pressure); |
| |
| return ret; |
| } |
| @@ -1361,7 +1359,7 @@ static unsigned int fanout_demux_rollover(struct packet_fanout *f, |
| i = j = min_t(int, po->rollover->sock, num - 1); |
| do { |
| po_next = pkt_sk(f->arr[i]); |
| - if (po_next != po_skip && !po_next->pressure && |
| + if (po_next != po_skip && !READ_ONCE(po_next->pressure) && |
| packet_rcv_has_room(po_next, skb) == ROOM_NORMAL) { |
| if (i != j) |
| po->rollover->sock = i; |
| @@ -3351,7 +3349,7 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, |
| if (skb == NULL) |
| goto out; |
| |
| - if (pkt_sk(sk)->pressure) |
| + if (READ_ONCE(pkt_sk(sk)->pressure)) |
| packet_rcv_has_room(pkt_sk(sk), NULL); |
| |
| if (pkt_sk(sk)->has_vnet_hdr) { |
| @@ -4170,8 +4168,8 @@ static __poll_t packet_poll(struct file *file, struct socket *sock, |
| TP_STATUS_KERNEL)) |
| mask |= EPOLLIN | EPOLLRDNORM; |
| } |
| - if (po->pressure && __packet_rcv_has_room(po, NULL) == ROOM_NORMAL) |
| - po->pressure = 0; |
| + if (READ_ONCE(po->pressure) && __packet_rcv_has_room(po, NULL) == ROOM_NORMAL) |
| + WRITE_ONCE(po->pressure, 0); |
| spin_unlock_bh(&sk->sk_receive_queue.lock); |
| spin_lock_bh(&sk->sk_write_queue.lock); |
| if (po->tx_ring.pg_vec) { |
| -- |
| 2.27.0 |
| |