Re: [PATCH 2/2] net/sock: Propagate WF_SYNC only when requested
From: Shrikanth Hegde <hidden>
Date: 2026-07-21 04:50:36
Also in:
linux-sctp, lkml
Hi Srikar, On 7/14/26 7:09 AM, Srikar Dronamraju wrote:
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.
You can also add the performance data in the cover-letter to this patch.
quoted hunk ↗ jump to hunk
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);
Would it make sense to write a macro or a wrapper function do the same instead of sprinkling the same at all the places? similar comment for patch 1. IMHO, it would make it easier to read.