On Wed, Jun 17, 2026 at 03:23:54AM -0700, Breno Leitao wrote:
> Measured it to _just be sure_, 1-byte ping-pong (perf bench sched pipe -s 1):
>
> baseline: 2.674 usecs/op
> patched: 2.710 usecs/op (+1.3%, within run-to-run noise)
>
Can you try this:
diff --git a/fs/fcntl.c b/fs/fcntl.c
index c158f082f1da..012d9d87f827 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -1118,11 +1118,14 @@ int fasync_helper(int fd, struct file * filp, int on,
struct fasync_struct **fap
EXPORT_SYMBOL(fasync_helper);
-/*
- * rcu_read_lock() is held
- */
-static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band)
+void __kill_fasync(struct fasync_struct **fp, int sig, int band)
{
+ struct fasync_struct *fa;
+
+ guard(rcu)();
+
+ fa = rcu_dereference(*fp);
+
while (fa) {
struct fown_struct *fown;
unsigned long flags;
@@ -1148,19 +1151,7 @@ static void kill_fasync_rcu(struct fasync_struct *fa,
int sig, int band)
fa = rcu_dereference(fa->fa_next);
}
}
-
-void kill_fasync(struct fasync_struct **fp, int sig, int band)
-{
- /* First a quick test without locking: usually
- * the list is empty.
- */
- if (*fp) {
- rcu_read_lock();
- kill_fasync_rcu(rcu_dereference(*fp), sig, band);
- rcu_read_unlock();
- }
-}
-EXPORT_SYMBOL(kill_fasync);
+EXPORT_SYMBOL(__kill_fasync);
static int __init fcntl_init(void)
{
diff --git a/fs/pipe.c b/fs/pipe.c
index 429b0714ec57..bea4e92bf0a8 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -426,7 +426,7 @@ anon_pipe_read(struct kiocb *iocb, struct iov_iter *to)
}
error = pipe_buf_confirm(pipe, buf);
- if (error) {
+ if (unlikely(error)) {
if (!ret)
ret = error;
break;
@@ -541,7 +541,7 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
* the same time, we could set up lockdep annotations for that, but
* since we don't actually need that, it's simpler to just bail here.
*/
- if (pipe_has_watch_queue(pipe))
+ if (unlikely(pipe_has_watch_queue(pipe)))
return -EXDEV;
/* Null write succeeds. */
@@ -552,7 +552,7 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
mutex_lock(&pipe->mutex);
- if (!pipe->readers) {
+ if (unlikely(!pipe->readers)) {
if ((iocb->ki_flags & IOCB_NOSIGNAL) == 0)
send_sig(SIGPIPE, current, 0);
ret = -EPIPE;
@@ -593,7 +593,7 @@ anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
}
for (;;) {
- if (!pipe->readers) {
+ if (unlikely(!pipe->readers)) {
if ((iocb->ki_flags & IOCB_NOSIGNAL) == 0)
send_sig(SIGPIPE, current, 0);
if (!ret)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d10897b3a1e3..6f86d1fe7589 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1383,7 +1383,12 @@ extern struct fasync_struct *fasync_alloc(void);
extern void fasync_free(struct fasync_struct *);
/* can be called from interrupts */
-extern void kill_fasync(struct fasync_struct **, int, int);
+void __kill_fasync(struct fasync_struct **fp, int sig, int band);
+static inline void kill_fasync(struct fasync_struct **fp, int sig, int band)
+{
+ if (unlikely(*fp))
+ __kill_fasync(fp, sig, band);
+}
extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int
force);
extern int f_setown(struct file *filp, int who, int force);