| From ca77c9d14a7ce2b3f171996f86fc7788c192f69b Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 4 Feb 2025 14:48:25 +0000 |
| Subject: net: flush_backlog() small changes |
| |
| From: Eric Dumazet <edumazet@google.com> |
| |
| [ Upstream commit cbe08724c18078564abefbf6591078a7c98e5e0f ] |
| |
| Add READ_ONCE() around reads of skb->dev->reg_state, because |
| this field can be changed from other threads/cpus. |
| |
| Instead of calling dev_kfree_skb_irq() and kfree_skb() |
| while interrupts are masked and locks held, |
| use a temporary list and use __skb_queue_purge_reason() |
| |
| Use SKB_DROP_REASON_DEV_READY drop reason to better |
| describe why these skbs are dropped. |
| |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Reviewed-by: Jason Xing <kerneljasonxing@gmail.com> |
| Link: https://patch.msgid.link/20250204144825.316785-1-edumazet@google.com |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/core/dev.c | 12 ++++++++---- |
| 1 file changed, 8 insertions(+), 4 deletions(-) |
| |
| diff --git a/net/core/dev.c b/net/core/dev.c |
| index 2f7f5fd9ffec7..77306b522966c 100644 |
| --- a/net/core/dev.c |
| +++ b/net/core/dev.c |
| @@ -6187,16 +6187,18 @@ EXPORT_SYMBOL(netif_receive_skb_list); |
| static void flush_backlog(struct work_struct *work) |
| { |
| struct sk_buff *skb, *tmp; |
| + struct sk_buff_head list; |
| struct softnet_data *sd; |
| |
| + __skb_queue_head_init(&list); |
| local_bh_disable(); |
| sd = this_cpu_ptr(&softnet_data); |
| |
| backlog_lock_irq_disable(sd); |
| skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { |
| - if (skb->dev->reg_state == NETREG_UNREGISTERING) { |
| + if (READ_ONCE(skb->dev->reg_state) == NETREG_UNREGISTERING) { |
| __skb_unlink(skb, &sd->input_pkt_queue); |
| - dev_kfree_skb_irq(skb); |
| + __skb_queue_tail(&list, skb); |
| rps_input_queue_head_incr(sd); |
| } |
| } |
| @@ -6204,14 +6206,16 @@ static void flush_backlog(struct work_struct *work) |
| |
| local_lock_nested_bh(&softnet_data.process_queue_bh_lock); |
| skb_queue_walk_safe(&sd->process_queue, skb, tmp) { |
| - if (skb->dev->reg_state == NETREG_UNREGISTERING) { |
| + if (READ_ONCE(skb->dev->reg_state) == NETREG_UNREGISTERING) { |
| __skb_unlink(skb, &sd->process_queue); |
| - kfree_skb(skb); |
| + __skb_queue_tail(&list, skb); |
| rps_input_queue_head_incr(sd); |
| } |
| } |
| local_unlock_nested_bh(&softnet_data.process_queue_bh_lock); |
| local_bh_enable(); |
| + |
| + __skb_queue_purge_reason(&list, SKB_DROP_REASON_DEV_READY); |
| } |
| |
| static bool flush_required(int cpu) |
| -- |
| 2.39.5 |
| |