From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Bernd Schubert <bschubert@ddn.com>,
Miklos Szeredi <mszeredi@redhat.com>,
Sasha Levin <sashal@kernel.org>,
miklos@szeredi.hu, linux-fsdevel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.18-6.6] fuse: Invalidate the page cache after FOPEN_DIRECT_IO write
Date: Tue, 9 Dec 2025 22:48:51 -0500 [thread overview]
Message-ID: <20251210034915.2268617-10-sashal@kernel.org> (raw)
In-Reply-To: <20251210034915.2268617-1-sashal@kernel.org>
From: Bernd Schubert <bschubert@ddn.com>
[ Upstream commit b359af8275a982a458e8df6c6beab1415be1f795 ]
generic_file_direct_write() also does this and has a large
comment about.
Reproducer here is xfstest's generic/209, which is exactly to
have competing DIO write and cached IO read.
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Analysis Summary
### The Bug
This commit fixes a **data coherency bug** in FUSE when using
`FOPEN_DIRECT_IO`. The problem occurs when:
1. A direct I/O write completes on a FUSE filesystem
2. A concurrent buffered read has populated the page cache with (now
stale) data
3. Without invalidation, the cached read returns **stale data**
The VFS layer handles this in `generic_file_direct_write()`
(mm/filemap.c:4172-4224) by calling
`kiocb_invalidate_post_direct_write()` after direct writes. The comment
in VFS explicitly mentions this is needed to "invalidate clean pages
which might have been cached by non-direct readahead."
### The Fix
The fix adds the same post-write invalidation pattern to FUSE's
`fuse_direct_io()` function:
- After a successful write (`res > 0 && write && fopen_direct_io`)
- Call `invalidate_inode_pages2_range(mapping, idx_from, idx_to)`
- This ensures stale read-ahead pages are invalidated
**Code size:** +9 lines, single function, single file
### Stable Kernel Criteria Assessment
| Criterion | Assessment |
|-----------|------------|
| Obviously correct | ✅ Yes - follows established VFS pattern |
| Fixes real bug | ✅ Yes - stale data reads (data integrity) |
| Has reproducer | ✅ Yes - xfstest generic/209 |
| Small and contained | ✅ Yes - 9 lines in one function |
| No new features | ✅ Correct - pure bug fix |
| Cc: stable tag | ❌ Not present |
| Fixes: tag | ❌ Not present |
### Dependencies and Backport Concerns
**Critical dependency:** This commit requires commit `80e4f25262f9f`
("fuse: invalidate page cache pages before direct write") which
introduced the `fopen_direct_io` variable and `idx_from`/`idx_to`
calculations. That commit was merged in **v6.6-rc1**.
**Backportable to:**
- stable/linux-6.6.y ✅
- stable/linux-6.11.y ✅
- stable/linux-6.12.y ✅
**NOT backportable to:**
- stable/linux-6.1.y ❌ (missing prerequisite code)
- Earlier LTS kernels ❌
### Risk Assessment
**LOW RISK:**
- Very small change (+9 lines)
- Uses existing, well-tested API (`invalidate_inode_pages2_range`)
- Follows the same pattern as the VFS layer
- Error return from invalidation is silently ignored (same as VFS
behavior - "if this invalidation fails, tough, the write still
worked...")
- Only affects FUSE filesystems using `FOPEN_DIRECT_IO` with concurrent
cached reads
### User Impact
- **Severity:** Medium-High - stale data reads are a data integrity
issue
- **Affected users:** FUSE filesystem users enabling `FOPEN_DIRECT_IO`
(including some high-performance storage systems)
- **Reproducer:** Clear, well-known xfstest (generic/209)
### Verdict
Despite lacking explicit stable tags, this is a legitimate data
integrity fix. The bug causes **real user-visible corruption** (stale
data reads), the fix is small and surgical, follows an established VFS
pattern, and has low regression risk. The lack of `Cc: stable` doesn't
disqualify it - many important fixes arrive without explicit tags.
For kernels 6.6+, this should be backported. For earlier kernels, the
prerequisite code doesn't exist, so backporting would require additional
work.
**YES**
fs/fuse/file.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index c5c82b3807911..bb4ecfd469a5e 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1681,6 +1681,15 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
if (res > 0)
*ppos = pos;
+ if (res > 0 && write && fopen_direct_io) {
+ /*
+ * As in generic_file_direct_write(), invalidate after the
+ * write, to invalidate read-ahead cache that may have competed
+ * with the write.
+ */
+ invalidate_inode_pages2_range(mapping, idx_from, idx_to);
+ }
+
return res > 0 ? res : err;
}
EXPORT_SYMBOL_GPL(fuse_direct_io);
--
2.51.0
next prev parent reply other threads:[~2025-12-10 3:49 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-10 3:48 [PATCH AUTOSEL 6.18-6.17] functionfs: fix the open/removal races Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.10] scsi: qla2xxx: Use reinit_completion on mbx_intr_comp Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.10] via_wdt: fix critical boot hang due to unnamed resource allocation Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.10] ti-sysc: allow OMAP2 and OMAP4 timers to be reserved on AM33xx Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.15] scsi: qla2xxx: Fix lost interrupts with qlini_mode=disabled Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-6.12] exfat: zero out post-EOF page cache on file extension Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-6.12] scsi: smartpqi: Add support for Hurray Data new controller PCI device Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-6.12] scsi: ufs: host: mediatek: Fix shutdown/suspend race condition Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.10] powerpc/addnote: Fix overflow on 32-bit builds Sasha Levin
2025-12-10 3:48 ` Sasha Levin [this message]
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.10] ipmi: Fix __scan_channels() failing to rescan channels Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.10] scsi: qla2xxx: Fix initiator mode with qlini_mode=exclusive Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-6.17] um: init cpu_tasks[] earlier Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.10] reset: fix BIT macro reference Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.10] clk: mvebu: cp110 add CLK_IGNORE_UNUSED to pcie_x10, pcie_x11 & pcie_x4 Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-6.6] fuse: Always flush the page cache before FOPEN_DIRECT_IO write Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-5.10] firmware: imx: scu-irq: Init workqueue before request mbox channel Sasha Levin
2025-12-10 3:48 ` [PATCH AUTOSEL 6.18-6.17] scsi: lpfc: Fix reusing an ndlp that is marked NLP_DROPPED during FLOGI Sasha Levin
2025-12-10 3:49 ` [PATCH AUTOSEL 6.18-5.10] exfat: fix remount failure in different process environments Sasha Levin
2025-12-10 3:49 ` [PATCH AUTOSEL 6.18-5.10] ipmi: Fix the race between __scan_channels() and deliver_response() Sasha Levin
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=20251210034915.2268617-10-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=bschubert@ddn.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=mszeredi@redhat.com \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox