Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'tpacket_snd-bugs' into main

Yun Lu says:

====================
fix two issues and optimize code on tpacket_snd()

This series fix two issues and optimize the code on tpacket_snd():
1, fix the SO_SNDTIMEO constraint not effective due to the changes in
commit 581073f626e3;
2, fix a soft lockup issue on a specific edge case, and also optimize
the loop logic to be clearer and more obvious;

---
Changes in v5:
- Still combine fix and optimization together, change to while(1).
Thanks: Willem de Bruijn.
- Link to v4: https://lore.kernel.org/all/20250710102639.280932-1-luyun_611@163.com/

Changes in v4:
- Fix a typo and add the missing semicolon. Thanks: Simon Horman.
- Split the second patch into two, one to fix, another to optimize.
Thanks: Willem de Bruijn
- Link to v3: https://lore.kernel.org/all/20250709095653.62469-1-luyun_611@163.com/

Changes in v3:
- Split in two different patches.
- Simplify the code and reuse ph to continue. Thanks: Eric Dumazet.
- Link to v2: https://lore.kernel.org/all/20250708020642.27838-1-luyun_611@163.com/

Changes in v2:
- Add a Fixes tag.
- Link to v1: https://lore.kernel.org/all/20250707081629.10344-1-luyun_611@163.com/
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+13 -14
+13 -14
net/packet/af_packet.c
··· 2785 2785 int len_sum = 0; 2786 2786 int status = TP_STATUS_AVAILABLE; 2787 2787 int hlen, tlen, copylen = 0; 2788 - long timeo = 0; 2788 + long timeo; 2789 2789 2790 2790 mutex_lock(&po->pg_vec_lock); 2791 2791 ··· 2839 2839 if ((size_max > dev->mtu + reserve + VLAN_HLEN) && !vnet_hdr_sz) 2840 2840 size_max = dev->mtu + reserve + VLAN_HLEN; 2841 2841 2842 + timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT); 2842 2843 reinit_completion(&po->skb_completion); 2843 2844 2844 2845 do { 2845 2846 ph = packet_current_frame(po, &po->tx_ring, 2846 2847 TP_STATUS_SEND_REQUEST); 2847 2848 if (unlikely(ph == NULL)) { 2848 - if (need_wait && skb) { 2849 - timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT); 2849 + /* Note: packet_read_pending() might be slow if we 2850 + * have to call it as it's per_cpu variable, but in 2851 + * fast-path we don't have to call it, only when ph 2852 + * is NULL, we need to check the pending_refcnt. 2853 + */ 2854 + if (need_wait && packet_read_pending(&po->tx_ring)) { 2850 2855 timeo = wait_for_completion_interruptible_timeout(&po->skb_completion, timeo); 2851 2856 if (timeo <= 0) { 2852 2857 err = !timeo ? -ETIMEDOUT : -ERESTARTSYS; 2853 2858 goto out_put; 2854 2859 } 2855 - } 2856 - /* check for additional frames */ 2857 - continue; 2860 + /* check for additional frames */ 2861 + continue; 2862 + } else 2863 + break; 2858 2864 } 2859 2865 2860 2866 skb = NULL; ··· 2949 2943 } 2950 2944 packet_increment_head(&po->tx_ring); 2951 2945 len_sum += tp_len; 2952 - } while (likely((ph != NULL) || 2953 - /* Note: packet_read_pending() might be slow if we have 2954 - * to call it as it's per_cpu variable, but in fast-path 2955 - * we already short-circuit the loop with the first 2956 - * condition, and luckily don't have to go that path 2957 - * anyway. 2958 - */ 2959 - (need_wait && packet_read_pending(&po->tx_ring)))); 2946 + } while (1); 2960 2947 2961 2948 err = len_sum; 2962 2949 goto out_put;