From: Breno Leitao <leitao@debian.org>
To: Eric Dumazet <edumazet@google.com>,
guohua.yan@unisoc.com, xuewen.yan@unisoc.com,
usama.arif@linux.dev
Cc: davem@davemloft.net, horms@kernel.org, kuba@kernel.org,
kuniyu@google.com, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org, pabeni@redhat.com, willemb@google.com,
shakeel.butt@linux.dev, hannes@cmpxchg.org, riel@surriel.com,
kernel-team@meta.com
Subject: Re: [PATCH] net: use sync wakeups for socket error reports
Date: Fri, 17 Jul 2026 05:20:34 -0700 [thread overview]
Message-ID: <alodxQoCH5A5iVGG@gmail.com> (raw)
In-Reply-To: <CANn89iLc1Bv_wmKvr_9mtGRM3gL7kgoy2Prr2SgtHY4C=ZgfBg@mail.gmail.com>
On Wed, Jul 08, 2026 at 06:32:02PM +0200, Eric Dumazet wrote:
> Perhaps this SYNC heuristic should be a per-socket choice so that
> applications can decide what is best for them.
Something like this?
net: add SO_ERR_WAKE_SYNC for sync error-report wakeups
sock_def_error_report() wakes EPOLLERR waiters with
wake_up_interruptible_poll(), while sock_def_readable() and
sock_def_write_space() already pass the sync hint. A socket with
SO_TIMESTAMPING enabled delivers every TX and ACK timestamp through
sk_error_queue and raises EPOLLERR, so the error path wakes a sleeping
consumer very often.
Without the sync hint the scheduler often places the woken consumer on a
remote CPU, which costs a rescheduling IPI. Usama Arif measured 16,326
such IPIs/min on a 176-core host running a production workload with
SO_TIMESTAMPING enabled. [1]
Switching the error path to a sync wakeup unconditionally is not the
right fix, as there are different requirements for it to be async, see
[2].
Eric suggested that an options is to add SO_ERR_WAKE_SYNC so
applications choose per socket, so a consumer draining a high-rate error
queue can opt in to keep the wakeup local and drop the IPI, using socket
flag SO_ERR_WAKE_SYNC.
Link: https://lore.kernel.org/all/CANn89iLc1Bv_wmKvr_9mtGRM3gL7kgoy2Prr2SgtHY4C=ZgfBg@mail.gmail.com/ [1]
Link: https://lore.kernel.org/netdev/20260526063650.952-1-xuewen.yan@unisoc.com/ [2]
Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Breno Leitao <leitao@debian.org>
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index 5ef57f88df6b3..2a3c27aaf4e95 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -155,6 +155,8 @@
#define SO_INQ 84
#define SCM_INQ SO_INQ
+#define SO_ERR_WAKE_SYNC 85
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 72fb1b006da93..00f31c74a63df 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -166,6 +166,8 @@
#define SO_INQ 84
#define SCM_INQ SO_INQ
+#define SO_ERR_WAKE_SYNC 85
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index c16ec36dfee6b..db5b6cad17d49 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -147,6 +147,8 @@
#define SO_INQ 0x4052
#define SCM_INQ SO_INQ
+#define SO_ERR_WAKE_SYNC 0x4053
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index 71befa109e1cf..5e9ff3634265c 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -148,6 +148,8 @@
#define SO_INQ 0x005d
#define SCM_INQ SO_INQ
+#define SO_ERR_WAKE_SYNC 0x005e
+
#if !defined(__KERNEL__)
diff --git a/include/net/sock.h b/include/net/sock.h
index 51185222aac29..d8ee1dae8ecaf 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1022,6 +1022,7 @@ enum sock_flags {
SOCK_RCVMARK, /* Receive SO_MARK ancillary data with packet */
SOCK_RCVPRIORITY, /* Receive SO_PRIORITY ancillary data with packet */
SOCK_TIMESTAMPING_ANY, /* Copy of sk_tsflags & TSFLAGS_ANY */
+ SOCK_ERR_WAKE_SYNC, /* Sync wakeup on error report, %SO_ERR_WAKE_SYNC */
};
#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 53b5a8c002b1e..5527c9318b40e 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -150,6 +150,8 @@
#define SO_INQ 84
#define SCM_INQ SO_INQ
+#define SO_ERR_WAKE_SYNC 85
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
diff --git a/net/core/sock.c b/net/core/sock.c
index 498a57f34f5b5..59caab6a7223a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1557,6 +1557,10 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
sock_valbool_flag(sk, SOCK_SELECT_ERR_QUEUE, valbool);
break;
+ case SO_ERR_WAKE_SYNC:
+ sock_valbool_flag(sk, SOCK_ERR_WAKE_SYNC, valbool);
+ break;
+
case SO_PASSCRED:
if (sk_may_scm_recv(sk))
sk->sk_scm_credentials = valbool;
@@ -2064,6 +2068,10 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE);
break;
+ case SO_ERR_WAKE_SYNC:
+ v.val = sock_flag(sk, SOCK_ERR_WAKE_SYNC);
+ break;
+
#ifdef CONFIG_NET_RX_BUSY_POLL
case SO_BUSY_POLL:
v.val = READ_ONCE(sk->sk_ll_usec);
@@ -3641,8 +3649,12 @@ static void sock_def_error_report(struct sock *sk)
rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
- if (skwq_has_sleeper(wq))
- wake_up_interruptible_poll(&wq->wait, EPOLLERR);
+ if (skwq_has_sleeper(wq)) {
+ if (sock_flag(sk, SOCK_ERR_WAKE_SYNC))
+ wake_up_interruptible_sync_poll(&wq->wait, EPOLLERR);
+ else
+ wake_up_interruptible_poll(&wq->wait, EPOLLERR);
+ }
sk_wake_async_rcu(sk, SOCK_WAKE_IO, POLL_ERR);
rcu_read_unlock();
}
next prev parent reply other threads:[~2026-07-17 12:21 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-08 13:38 [PATCH] net: use sync wakeups for socket error reports Usama Arif
2026-07-08 15:25 ` Breno Leitao
2026-07-08 16:08 ` Usama Arif
2026-07-08 16:32 ` Eric Dumazet
2026-07-17 12:20 ` Breno Leitao [this message]
2026-07-17 12:31 ` Usama Arif
2026-07-17 13:47 ` Matthew Wilcox
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alodxQoCH5A5iVGG@gmail.com \
--to=leitao@debian.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=guohua.yan@unisoc.com \
--cc=hannes@cmpxchg.org \
--cc=horms@kernel.org \
--cc=kernel-team@meta.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=riel@surriel.com \
--cc=shakeel.butt@linux.dev \
--cc=usama.arif@linux.dev \
--cc=willemb@google.com \
--cc=xuewen.yan@unisoc.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.