[PATCH 2/2] net/sock: Propagate WF_SYNC only when requested
From: Srikar Dronamraju <hidden>
Date: 2026-07-14 01:41:04
Also in:
linux-sctp, lkml
Subsystem:
networking [general], networking [sockets], networking [unix sockets], sctp protocol, shared memory communications (smc) sockets, the rest, tipc network layer · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Kuniyuki Iwashima, Willem de Bruijn, Marcelo Ricardo Leitner, Xin Long, D. Wythe, Dust Li, Sidraya Jayagond, Wenjia Zhang, Linus Torvalds, Jon Maloy
Use SOCK_SYNC_WAKEUP to select between synchronous and asynchronous wakeup wakeup APIs. This avoids propagating WF_SYNC when no blocking waiter is expected. All wakeup locations in networking code that currently issue synchronous poll-style wakeups unconditionally are updated. Signed-off-by: Srikar Dronamraju <redacted> --- net/core/sock.c | 31 ++++++++++++++++++++++++------- net/sctp/socket.c | 10 ++++++++-- net/smc/af_smc.c | 4 ++-- net/smc/smc_rx.c | 10 ++++++++-- net/tipc/socket.c | 22 +++++++++++++++++----- net/unix/af_unix.c | 26 ++++++++++++++++++-------- 6 files changed, 77 insertions(+), 26 deletions(-)
diff --git a/net/core/sock.c b/net/core/sock.c
index 8a59bfaa8096..a214e883b14b 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c@@ -3652,9 +3652,15 @@ void sock_def_readable(struct sock *sk) rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); - if (skwq_has_sleeper(wq)) - wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | EPOLLPRI | + if (skwq_has_sleeper(wq)) { + if (sock_flag(sk, SOCK_SYNC_WAKEUP)) { + wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | EPOLLPRI | + EPOLLRDNORM | EPOLLRDBAND); + } else { + wake_up_interruptible_poll(&wq->wait, EPOLLIN | EPOLLPRI | EPOLLRDNORM | EPOLLRDBAND); + } + } sk_wake_async_rcu(sk, SOCK_WAKE_WAITD, POLL_IN); rcu_read_unlock(); }
@@ -3670,9 +3676,15 @@ static void sock_def_write_space(struct sock *sk) */ if (sock_writeable(sk)) { wq = rcu_dereference(sk->sk_wq); - if (skwq_has_sleeper(wq)) - wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT | + if (skwq_has_sleeper(wq)) { + if (sock_flag(sk, SOCK_SYNC_WAKEUP)) { + wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT | + EPOLLWRNORM | EPOLLWRBAND); + } else { + wake_up_interruptible_poll(&wq->wait, EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND); + } + } /* Should agree with poll, otherwise some programs break */ sk_wake_async_rcu(sk, SOCK_WAKE_SPACE, POLL_OUT);
@@ -3695,10 +3707,15 @@ static void sock_def_write_space_wfree(struct sock *sk, int wmem_alloc) /* rely on refcount_sub from sock_wfree() */ smp_mb__after_atomic(); - if (wq && waitqueue_active(&wq->wait)) - wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT | + if (wq && waitqueue_active(&wq->wait)) { + if (sock_flag(sk, SOCK_SYNC_WAKEUP)) { + wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND); - + } else { + wake_up_interruptible_poll(&wq->wait, EPOLLOUT | + EPOLLWRNORM | EPOLLWRBAND); + } + } /* Should agree with poll, otherwise some programs break */ sk_wake_async_rcu(sk, SOCK_WAKE_SPACE, POLL_OUT); }
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c7b9e325ec1c..9cb3432f065a 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c@@ -9348,9 +9348,15 @@ void sctp_data_ready(struct sock *sk) rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); - if (skwq_has_sleeper(wq)) - wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | + if (skwq_has_sleeper(wq)) { + if (sock_flag(sk, SOCK_SYNC_WAKEUP)) { + wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | + EPOLLRDNORM | EPOLLRDBAND); + } else { + wake_up_interruptible_poll(&wq->wait, EPOLLIN | EPOLLRDNORM | EPOLLRDBAND); + } + } sk_wake_async_rcu(sk, SOCK_WAKE_WAITD, POLL_IN); rcu_read_unlock(); }
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index b5db69073e20..1a6ea2e30769 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c@@ -819,10 +819,10 @@ static void smc_fback_wakeup_waitqueue(struct smc_sock *smc, void *key) wake_up_interruptible_all(&wq->wait); } else { flags = key_to_poll(key); - if (flags & (EPOLLIN | EPOLLOUT)) + if (flags & (EPOLLIN | EPOLLOUT) && sock_flag(&smc->sk, SOCK_SYNC_WAKEUP)) /* sk_data_ready or sk_write_space */ wake_up_interruptible_sync_poll(&wq->wait, flags); - else if (flags & EPOLLERR) + else /* sk_error_report */ wake_up_interruptible_poll(&wq->wait, flags); }
diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c
index c1d9b923938d..4e288a2364d2 100644
--- a/net/smc/smc_rx.c
+++ b/net/smc/smc_rx.c@@ -39,9 +39,15 @@ static void smc_rx_wake_up(struct sock *sk) /* called already in smc_listen_work() */ rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); - if (skwq_has_sleeper(wq)) - wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | EPOLLPRI | + if (skwq_has_sleeper(wq)) { + if (sock_flag(sk, SOCK_SYNC_WAKEUP)) { + wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | EPOLLPRI | EPOLLRDNORM | EPOLLRDBAND); + } else { + wake_up_interruptible_poll(&wq->wait, EPOLLIN | EPOLLPRI | + EPOLLRDNORM | EPOLLRDBAND); + } + } sk_wake_async_rcu(sk, SOCK_WAKE_WAITD, POLL_IN); if ((sk->sk_shutdown == SHUTDOWN_MASK) || (sk->sk_state == SMC_CLOSED))
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index e564341e0216..9fa83a89882c 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c@@ -2116,9 +2116,15 @@ static void tipc_write_space(struct sock *sk) rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); - if (skwq_has_sleeper(wq)) - wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT | + if (skwq_has_sleeper(wq)) { + if (sock_flag(sk, SOCK_SYNC_WAKEUP)) { + wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND); + } else { + wake_up_interruptible_poll(&wq->wait, EPOLLOUT | + EPOLLWRNORM | EPOLLWRBAND); + } + } rcu_read_unlock(); }
@@ -2134,9 +2140,15 @@ static void tipc_data_ready(struct sock *sk) rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); - if (skwq_has_sleeper(wq)) - wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | - EPOLLRDNORM | EPOLLRDBAND); + if (skwq_has_sleeper(wq)) { + if (sock_flag(sk, SOCK_SYNC_WAKEUP)) { + wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | + EPOLLRDNORM | EPOLLRDBAND); + } else { + wake_up_interruptible_poll(&wq->wait, EPOLLIN | + EPOLLRDNORM | EPOLLRDBAND); + } + } rcu_read_unlock(); }
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index f7a9d55eee8a..15ebcc2d9d58 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c@@ -601,9 +601,15 @@ static void unix_write_space(struct sock *sk) rcu_read_lock(); if (unix_writable(sk, READ_ONCE(sk->sk_state))) { wq = rcu_dereference(sk->sk_wq); - if (skwq_has_sleeper(wq)) - wake_up_interruptible_sync_poll(&wq->wait, - EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND); + if (skwq_has_sleeper(wq)) { + if (sock_flag(sk, SOCK_SYNC_WAKEUP)) { + wake_up_interruptible_sync_poll(&wq->wait, + EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND); + } else { + wake_up_interruptible_poll(&wq->wait, + EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND); + } + } sk_wake_async_rcu(sk, SOCK_WAKE_SPACE, POLL_OUT); } rcu_read_unlock();
@@ -2603,11 +2609,15 @@ int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size, goto out; } - if (wq_has_sleeper(&u->peer_wait)) - wake_up_interruptible_sync_poll(&u->peer_wait, - EPOLLOUT | EPOLLWRNORM | - EPOLLWRBAND); - + if (wq_has_sleeper(&u->peer_wait)) { + if (sock_flag(sk, SOCK_SYNC_WAKEUP)) { + wake_up_interruptible_sync_poll(&u->peer_wait, + EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND); + } else { + wake_up_interruptible_poll(&u->peer_wait, + EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND); + } + } if (msg->msg_name) { unix_copy_addr(msg, skb->sk);
--
2.52.0