ext4: prevent stale extent cache entries caused by concurrent get es_cache
[ 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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
ce33edfb2f
commit
7bf45d596b
@@ -5034,7 +5034,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;
|
||||
|
||||
@@ -1139,8 +1139,14 @@ resizefs_out:
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user