Commit a059ef8e authored by David S. Miller's avatar David S. Miller
Browse files

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 581073f6;
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: default avatarDavid S. Miller <davem@davemloft.net>
parents 5e28d5a3 55f0bfc0
Loading
Loading
Loading
Loading
+13 −14
Original line number Diff line number Diff line
@@ -2785,7 +2785,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
	int len_sum = 0;
	int status = TP_STATUS_AVAILABLE;
	int hlen, tlen, copylen = 0;
	long timeo = 0;
	long timeo;

	mutex_lock(&po->pg_vec_lock);

@@ -2839,22 +2839,28 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
	if ((size_max > dev->mtu + reserve + VLAN_HLEN) && !vnet_hdr_sz)
		size_max = dev->mtu + reserve + VLAN_HLEN;

	timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT);
	reinit_completion(&po->skb_completion);

	do {
		ph = packet_current_frame(po, &po->tx_ring,
					  TP_STATUS_SEND_REQUEST);
		if (unlikely(ph == NULL)) {
			if (need_wait && skb) {
				timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT);
			/* Note: packet_read_pending() might be slow if we
			 * have to call it as it's per_cpu variable, but in
			 * fast-path we don't have to call it, only when ph
			 * is NULL, we need to check the pending_refcnt.
			 */
			if (need_wait && packet_read_pending(&po->tx_ring)) {
				timeo = wait_for_completion_interruptible_timeout(&po->skb_completion, timeo);
				if (timeo <= 0) {
					err = !timeo ? -ETIMEDOUT : -ERESTARTSYS;
					goto out_put;
				}
			}
				/* check for additional frames */
				continue;
			} else
				break;
		}

		skb = NULL;
@@ -2943,14 +2949,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
		}
		packet_increment_head(&po->tx_ring);
		len_sum += tp_len;
	} while (likely((ph != NULL) ||
		/* Note: packet_read_pending() might be slow if we have
		 * to call it as it's per_cpu variable, but in fast-path
		 * we already short-circuit the loop with the first
		 * condition, and luckily don't have to go that path
		 * anyway.
		 */
		 (need_wait && packet_read_pending(&po->tx_ring))));
	} while (1);

	err = len_sum;
	goto out_put;