From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Zhang Yi <yi.zhang@huawei.com>, Theodore Ts'o <tytso@mit.edu>,
Sasha Levin <sashal@kernel.org>,
adilger.kernel@dilger.ca, linux-ext4@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.1 28/58] ext4: prevent stale extent cache entries caused by concurrent get es_cache
Date: Sun, 1 Jun 2025 19:39:41 -0400 [thread overview]
Message-ID: <20250601234012.3516352-28-sashal@kernel.org> (raw)
In-Reply-To: <20250601234012.3516352-1-sashal@kernel.org>
From: Zhang Yi <yi.zhang@huawei.com>
[ Upstream commit f22a0ef2231a7d8374bb021eb86404d0e9de5a02 ]
The EXT4_IOC_GET_ES_CACHE and EXT4_IOC_PRECACHE_EXTENTS currently
invokes ext4_ext_precache() to preload the extent cache without holding
the inode's i_rwsem. This can result in stale extent cache entries when
competing with operations such as ext4_collapse_range() which calls
ext4_ext_remove_space() or ext4_ext_shift_extents().
The problem arises when ext4_ext_remove_space() temporarily releases
i_data_sem due to insufficient journal credits. During this interval, a
concurrent EXT4_IOC_GET_ES_CACHE or EXT4_IOC_PRECACHE_EXTENTS may cache
extent entries that are about to be deleted. As a result, these cached
entries become stale and inconsistent with the actual extents.
Loading the extents cache without holding the inode's i_rwsem or the
mapping's invalidate_lock is not permitted besides during the writeback.
Fix this by holding the i_rwsem during EXT4_IOC_GET_ES_CACHE and
EXT4_IOC_PRECACHE_EXTENTS.
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Link: https://patch.msgid.link/20250423085257.122685-6-yi.zhang@huaweicloud.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
Based on my comprehensive analysis of this commit and comparison with
the historical similar commits, here is my assessment: **YES** This
commit should be backported to stable kernel trees for the following
reasons: ## Analysis Summary ### **Type of Bug Fix** This commit
addresses a **race condition** that can lead to **stale extent cache
entries** in the ext4 filesystem. The race occurs between: 1.
`EXT4_IOC_GET_ES_CACHE` and `EXT4_IOC_PRECACHE_EXTENTS` operations 2.
Concurrent `ext4_collapse_range()` operations that call
`ext4_ext_remove_space()` or `ext4_ext_shift_extents()` ### **Technical
Details of the Race** The problem stems from the fact that
`ext4_ext_remove_space()` temporarily releases `i_data_sem` when journal
credits are insufficient. During this critical window: - The extent
precaching operations (`ext4_ext_precache()`) can cache extent entries -
These cached entries are about to be deleted by the ongoing
collapse/shift operation - Result: **stale, inconsistent extent cache
entries** ### **Code Changes Analysis** The fix is **minimal and
surgical**: **In `fs/ext4/extents.c` (ext4_get_es_cache function):**
```c if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) { +
inode_lock_shared(inode); error = ext4_ext_precache(inode); +
inode_unlock_shared(inode); if (error) return error; ``` **In
`fs/ext4/ioctl.c` (EXT4_IOC_PRECACHE_EXTENTS case):** ```c case
EXT4_IOC_PRECACHE_EXTENTS: - return ext4_ext_precache(inode); +{ + int
ret; + + inode_lock_shared(inode); + ret = ext4_ext_precache(inode); +
inode_unlock_shared(inode); + return ret; +} ``` ### **Why This
Qualifies for Backporting** 1. **Important Bug Fix**: Stale extent cache
entries can lead to filesystem inconsistencies and potential data
corruption scenarios. 2. **Minimal Risk**: The changes are extremely
small and contained: - Only adds proper locking around existing
operations - Uses shared locking (`inode_lock_shared`) which allows
concurrent readers - No algorithmic changes or new features 3. **Follows
Established Patterns**: Similar commits in the repository (marked with
"Backport Status: YES") show this pattern: - Similar commit #2: "ext4:
fix data races when using cached status extents" - also deals with
extent cache consistency - Similar commit #3: "ext4: convert to
exclusive lock while inserting delalloc extents" - addresses similar
race conditions with proper locking - Similar commit #4: "ext4: do not
polute the extents cache while shifting extents" - prevents extent cache
corruption during shift operations 4. **Clear Impact**: The commit
message explicitly states this prevents "stale extent cache entries"
which can cause inconsistency with actual extents. 5. **Contained to
Subsystem**: Changes are limited to ext4 extent management and don't
affect other kernel subsystems. 6. **Stable Backport Indicators**: - No
"Cc: stable@" tag is present, but the nature of the fix (race condition
leading to corruption) makes it a good candidate - The fix follows
ext4's established locking protocol requirements - Multiple similar
extent cache race condition fixes have been backported ### **Risk
Assessment** - **Very Low Regression Risk**: Only adds locking
protection, doesn't change functional behavior - **Well-understood
Fix**: The locking pattern matches established ext4 conventions -
**Limited Scope**: Only affects two specific ioctl code paths This
commit represents exactly the type of fix that stable trees are meant
for: a small, safe fix for a real bug that can cause filesystem
corruption without introducing new functionality or architectural
changes.
fs/ext4/extents.c | 2 ++
fs/ext4/ioctl.c | 8 +++++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 323ac63a71af2..dafc651c4f55f 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -5042,7 +5042,9 @@ int ext4_get_es_cache(struct inode *inode, struct fiemap_extent_info *fieinfo,
}
if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) {
+ inode_lock_shared(inode);
error = ext4_ext_precache(inode);
+ inode_unlock_shared(inode);
if (error)
return error;
fieinfo->fi_flags &= ~FIEMAP_FLAG_CACHE;
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 3784f70416492..00e8bb8702cfb 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -1499,8 +1499,14 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return 0;
}
case EXT4_IOC_PRECACHE_EXTENTS:
- return ext4_ext_precache(inode);
+ {
+ int ret;
+ inode_lock_shared(inode);
+ ret = ext4_ext_precache(inode);
+ inode_unlock_shared(inode);
+ return ret;
+ }
case FS_IOC_SET_ENCRYPTION_POLICY:
if (!ext4_has_feature_encrypt(sb))
return -EOPNOTSUPP;
--
2.39.5
next prev parent reply other threads:[~2025-06-01 23:41 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-01 23:39 [PATCH AUTOSEL 6.1 01/58] drm/amdgpu/gfx6: fix CSIB handling Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 02/58] drm/dp: add option to disable zero sized address only transactions Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 03/58] sunrpc: update nextcheck time when adding new cache entries Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 04/58] drm/amd/display: DCN32 null data check Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 05/58] drm/bridge: analogix_dp: Add irq flag IRQF_NO_AUTOEN instead of calling disable_irq() Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 06/58] exfat: fix double free in delayed_free Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 07/58] arm64/cpuinfo: only show one cpu's info in c_show() Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 08/58] drm/bridge: anx7625: change the gpiod_set_value API Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 09/58] drm/amdgpu/gfx11: fix CSIB handling Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 10/58] media: i2c: imx334: Enable runtime PM before sub-device registration Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 11/58] drm/msm/hdmi: add runtime PM calls to DDC transfer function Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 12/58] media: uapi: v4l: Fix V4L2_TYPE_IS_OUTPUT condition Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 13/58] drm/amd/display: Add NULL pointer checks in dm_force_atomic_commit() Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 14/58] drm/amd/display: Skip to enable dsc if it has been off Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 15/58] drm/msm/a6xx: Increase HFI response timeout Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 16/58] media: i2c: imx334: Fix runtime PM handling in remove function Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 17/58] drm/amdgpu/gfx10: fix CSIB handling Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 18/58] drm: panel-orientation-quirks: Add ZOTAC Gaming Zone Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 19/58] media: ccs-pll: Better validate VT PLL branch Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 20/58] media: uapi: v4l: Change V4L2_TYPE_IS_CAPTURE condition Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 21/58] drm/amdgpu/gfx7: fix CSIB handling Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 22/58] ext4: ext4: unify EXT4_EX_NOCACHE|NOFAIL flags in ext4_ext_remove_space() Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 23/58] jfs: fix array-index-out-of-bounds read in add_missing_indices Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 24/58] media: ti: cal: Fix wrong goto on error path Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 25/58] media: rkvdec: h264: Use bytesperline and buffer height as virstride Sasha Levin
2025-06-01 23:39 ` Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 26/58] media: rkvdec: Initialize the m2m context before the controls Sasha Levin
2025-06-01 23:39 ` Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 27/58] sunrpc: fix race in cache cleanup causing stale nextcheck time Sasha Levin
2025-06-01 23:39 ` Sasha Levin [this message]
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 29/58] drm/amdgpu/gfx8: fix CSIB handling Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 30/58] drm/amdgpu/gfx9: " Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 31/58] jfs: Fix null-ptr-deref in jfs_ioc_trim Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 32/58] drm/amd/display: Correct prefetch calculation Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 33/58] drm/msm/dpu: don't select single flush for active CTL blocks Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 34/58] drm/amdkfd: Set SDMA_RLCx_IB_CNTL/SWITCH_INSIDE_IB Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 35/58] media: tc358743: ignore video while HPD is low Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 36/58] media: platform: exynos4-is: Add hardware sync wait to fimc_is_hw_change_mode() Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 37/58] media: i2c: imx334: update mode_3840x2160_regs array Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 38/58] nios2: force update_mmu_cache on spurious tlb-permission--related pagefaults Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 39/58] media: rcar-vin: Fix stride setting for RAW8 formats Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 40/58] media: qcom: venus: Fix uninitialized variable warning Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 41/58] ACPI: bus: Bail out if acpi_kobj registration fails Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 42/58] pmdomain: ti: Fix STANDBY handling of PER power domain Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 43/58] PM: runtime: fix denying of auto suspend in pm_suspend_timer_fn() Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 44/58] ASoC: amd: yc: Add quirk for Lenovo Yoga Pro 7 14ASP9 Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 45/58] thermal/drivers/qcom/tsens: Update conditions to strictly evaluate for IP v2+ Sasha Levin
2025-06-01 23:39 ` [PATCH AUTOSEL 6.1 46/58] clocksource/drivers/timer-tegra186: Fix watchdog self-pinging Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 47/58] gpio: pxa: Make irq_chip immutable Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 48/58] gpio: grgpio: " Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 49/58] gpio: xgene-sb: " Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 50/58] mmc: Add quirk to disable DDR50 tuning Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 51/58] clocksource: Fix the CPUs' choice in the watchdog per CPU verification Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 52/58] ACPICA: Avoid sequence overread in call to strncmp() Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 53/58] ACPICA: utilities: Fix overflow check in vsnprintf() Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 54/58] ACPI: EC: Add device to acpi_ec_no_wakeup[] qurik list Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 55/58] ALSA: seq: Remove unused snd_seq_queue_client_leave_cells Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 56/58] cpufreq: Force sync policy boost with global boost on sysfs update Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 57/58] power: supply: bq27xxx: Retrieve again when busy Sasha Levin
2025-06-01 23:40 ` [PATCH AUTOSEL 6.1 58/58] ASoC: tas2770: Power cycle amp on ISENSE/VSENSE change 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=20250601234012.3516352-28-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=adilger.kernel@dilger.ca \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
--cc=tytso@mit.edu \
--cc=yi.zhang@huawei.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.