Archive-only list for patches
 help / color / mirror / Atom feed
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


  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