Re: [PATCH 5.15] fuse: Fix race condition in writethrough path A race

From: Miklos Szeredi

Date: Wed Oct 15 2025 - 10:09:53 EST


On Wed, 15 Oct 2025 at 06:00, lu gu <giveme.gulu@xxxxxxxxx> wrote:
>
> > Attaching a test patch, minimally tested.
> Since I only have a test environment for kernel 5.15, I ported this
> patch to the FUSE module in 5.15. I ran the previous LTP test cases
> more than ten times, and the data inconsistency issue did not reoccur.
> However, a deadlock occur. Below is the specific stack trace.

This is does not reproduce for me on 6.17 even after running the test
for hours. Without seeing your backport it is difficult to say
anything about the reason for the deadlock.

Attaching an updated patch that takes care of i_wb initialization on
CONFIG_CGROUP_WRITEBACK=y.

Thanks,
Miklos
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index f1ef77a0be05..042c35f0466e 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1126,9 +1126,6 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
bool short_write;
int err;

- for (i = 0; i < ap->num_folios; i++)
- folio_wait_writeback(ap->folios[i]);
-
fuse_write_args_fill(ia, ff, pos, count);
ia->write.in.flags = fuse_write_flags(iocb);
if (fm->fc->handle_killpriv_v2 && !capable(CAP_FSETID))
@@ -1158,6 +1155,8 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
}
if (ia->write.folio_locked && (i == ap->num_folios - 1))
folio_unlock(folio);
+ else
+ folio_end_writeback_no_dropbehind(folio);
folio_put(folio);
}

@@ -1236,7 +1235,9 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
if (tmp == folio_size(folio))
folio_mark_uptodate(folio);

+ folio_wait_writeback(folio);
if (folio_test_uptodate(folio)) {
+ folio_start_writeback(folio);
folio_unlock(folio);
} else {
ia->write.folio_locked = true;
@@ -1268,6 +1269,8 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, struct iov_iter *ii)
int err = 0;
ssize_t res = 0;

+ inode_attach_wb(inode, NULL);
+
if (inode->i_size < pos + iov_iter_count(ii))
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);