* [PATCH] fuse: fix the bug of missing EPOLLET event wakeup
@ 2025-12-25 11:03 Zhang Tianci
2026-01-07 3:11 ` Zhang Tianci
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Zhang Tianci @ 2025-12-25 11:03 UTC (permalink / raw)
To: miklos
Cc: linux-fsdevel, linux-kernel, Zhang Tianci, Geng Xueyu, Wang Jian,
Xie Yongji
Users using Go have reported an issue to us:
When performing read/write operations with goroutines,
since fuse's file->f_ops->poll is not empty,
read/write operations are conducted via epoll.
Additionally, goroutines use the EPOLLET wake-up mode.
Currently, the implementation of fuse_file_poll has
the following problem:
After receiving EAGAIN during read/write operations,
the goroutine calls epoll_wait again, but then results in
permanent blocking. This is because a wake-up event
is required in EPOLLET mode.
The modification idea of this patch is based on the
implementation of epoll_wait:
After epoll_wait calls ->poll() for EPOLLET events,
it does not reinsert them into the ready list.
In this case, ep_poll_callback() needs to be used to
reinsert them into the ready list, so that the behavior
of EPOLLET is consistent with that of non-EPOLLET.
Reported-by: Geng Xueyu <gengxueyu.520@bytedance.com>
Reported-by: Wang Jian <wangjian.pg@bytedance.com>
Suggested-by: Xie Yongji <xieyongji@bytedance.com>
Signed-off-by: Zhang Tianci <zhangtianci.1997@bytedance.com>
---
Here is the reproducer for the bug:
1. Change libfuse/example/passthrough.c's xmp_read() to
always return -EAGAIN and mount it on /mnt_fuse.
2. Then create test file:
dd if=/dev/zero of=/mnt_fuse/test_poll bs=1M count=10
3. compile and run the following test case.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/epoll.h>
#define MAX_EVENTS 10
#define BUF_SIZE 4096
int main() {
int epfd, nfds, fd;
struct epoll_event ev, events[MAX_EVENTS];
char buffer[BUF_SIZE];
fd = open("/mnt_fuse/test_poll", O_RDWR|O_NONBLOCK|O_CREAT, 0644);
if (fd == -1) {
perror("open");
return -1;
}
epfd = epoll_create1(0);
if (epfd == -1) {
perror("epoll_create1");
return -1;
}
ev.data.fd = fd;
ev.events = EPOLLIN | EPOLLET;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
perror("epoll_ctl: fd");
return -1;
}
printf("Epoll is monitoring fd=%d.\n", fd);
while (1) {
nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
if (errno == EINTR) {
continue;
}
perror("epoll_wait");
return -1;
}
for (int i = 0; i < nfds; ++i) {
int current_fd = events[i].data.fd;
if (current_fd == fd) {
printf("[Notification] Data arrived on fd\n", fd);
while (1) {
ssize_t count = read(current_fd, buffer, BUF_SIZE);
if (count == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
printf("[Info] Buffer is empty, waiting for next event...\n");
break;
} else {
perror("read");
close(current_fd);
return -1;
}
} else if (count == 0) {
printf("[Info] EOF detected. Closing.\n");
close(current_fd);
return 0;
}
printf(">>> Read %zd bytes\n", count);
}
}
}
}
close(epfd);
return 0;
}
fs/fuse/file.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 01bc894e9c2ba..025eea58232c2 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2735,10 +2735,11 @@ __poll_t fuse_file_poll(struct file *file, poll_table *wait)
FUSE_ARGS(args);
int err;
+ poll_wait(file, &ff->poll_wait, wait);
+
if (fm->fc->no_poll)
- return DEFAULT_POLLMASK;
+ goto no_poll;
- poll_wait(file, &ff->poll_wait, wait);
inarg.events = mangle_poll(poll_requested_events(wait));
/*
@@ -2764,9 +2765,13 @@ __poll_t fuse_file_poll(struct file *file, poll_table *wait)
return demangle_poll(outarg.revents);
if (err == -ENOSYS) {
fm->fc->no_poll = 1;
- return DEFAULT_POLLMASK;
+ goto no_poll;
}
return EPOLLERR;
+
+no_poll:
+ wake_up_interruptible_sync(&ff->poll_wait);
+ return DEFAULT_POLLMASK;
}
EXPORT_SYMBOL_GPL(fuse_file_poll);
--
2.39.5
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fuse: fix the bug of missing EPOLLET event wakeup
2025-12-25 11:03 [PATCH] fuse: fix the bug of missing EPOLLET event wakeup Zhang Tianci
@ 2026-01-07 3:11 ` Zhang Tianci
2026-01-27 6:41 ` Zhang Tianci
2026-01-27 10:37 ` Miklos Szeredi
2026-01-27 16:23 ` Markus Elfring
2 siblings, 1 reply; 5+ messages in thread
From: Zhang Tianci @ 2026-01-07 3:11 UTC (permalink / raw)
To: miklos; +Cc: linux-fsdevel, linux-kernel, Geng Xueyu, Wang Jian, Xie Yongji
gently ping...
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fuse: fix the bug of missing EPOLLET event wakeup
2026-01-07 3:11 ` Zhang Tianci
@ 2026-01-27 6:41 ` Zhang Tianci
0 siblings, 0 replies; 5+ messages in thread
From: Zhang Tianci @ 2026-01-27 6:41 UTC (permalink / raw)
To: miklos; +Cc: linux-fsdevel, linux-kernel, Geng Xueyu, Wang Jian, Xie Yongji
gently ping...
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fuse: fix the bug of missing EPOLLET event wakeup
2025-12-25 11:03 [PATCH] fuse: fix the bug of missing EPOLLET event wakeup Zhang Tianci
2026-01-07 3:11 ` Zhang Tianci
@ 2026-01-27 10:37 ` Miklos Szeredi
2026-01-27 16:23 ` Markus Elfring
2 siblings, 0 replies; 5+ messages in thread
From: Miklos Szeredi @ 2026-01-27 10:37 UTC (permalink / raw)
To: Zhang Tianci
Cc: linux-fsdevel, linux-kernel, Geng Xueyu, Wang Jian, Xie Yongji
On Thu, 25 Dec 2025 at 12:03, Zhang Tianci
<zhangtianci.1997@bytedance.com> wrote:
>
> Users using Go have reported an issue to us:
> When performing read/write operations with goroutines,
> since fuse's file->f_ops->poll is not empty,
Another one of those historical mistakes...
> read/write operations are conducted via epoll.
> Additionally, goroutines use the EPOLLET wake-up mode.
>
> Currently, the implementation of fuse_file_poll has
> the following problem:
> After receiving EAGAIN during read/write operations,
Why is read/write returning EAGAIN?
Thanks,
Miklos
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fuse: fix the bug of missing EPOLLET event wakeup
2025-12-25 11:03 [PATCH] fuse: fix the bug of missing EPOLLET event wakeup Zhang Tianci
2026-01-07 3:11 ` Zhang Tianci
2026-01-27 10:37 ` Miklos Szeredi
@ 2026-01-27 16:23 ` Markus Elfring
2 siblings, 0 replies; 5+ messages in thread
From: Markus Elfring @ 2026-01-27 16:23 UTC (permalink / raw)
To: Zhang Tianci, linux-fsdevel
Cc: LKML, Geng Xueyu, Miklos Szeredi, Wang Jian, Xie Yongji
…
> After receiving EAGAIN during read/write operations,
> the goroutine calls epoll_wait again, but then results in
> permanent blocking. This is because a wake-up event
> is required in EPOLLET mode.
…
You may occasionally put more than 57 characters into text lines
of such a change description.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.19-rc7#n659
Regards,
Markus
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-01-27 16:23 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-25 11:03 [PATCH] fuse: fix the bug of missing EPOLLET event wakeup Zhang Tianci
2026-01-07 3:11 ` Zhang Tianci
2026-01-27 6:41 ` Zhang Tianci
2026-01-27 10:37 ` Miklos Szeredi
2026-01-27 16:23 ` Markus Elfring
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®