* [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules
@ 2025-04-23 8:52 Zhang Yi
2025-04-23 8:52 ` [PATCH 1/9] ext4: ext4: unify EXT4_EX_NOCACHE|NOFAIL flags in ext4_ext_remove_space() Zhang Yi
` (9 more replies)
0 siblings, 10 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
This patch series addresses the potential problems discussed with Jan
Kara regarding the modification rules for mapping extents[1]. Preparing
for the buffered I/O conversion for regular files.
This change includes:
Patch 1-5 fixes problems related to stale extent status entries that
may arise during the collapsing of ranges, the insertion of ranges, or
file truncation when these operations compete with concurrent writeback,
fiemap, or get extent cache.
Patch 6-8 adds a helper function to verify whether the context for
modifying extents is safe when EXT4_DEBUG is enabled. It primarily
checks the inode's i_rwsem and the mapping's invalidate_lock.
Patch 9 adds a comment to clarify the rules for loading, mapping,
modifying, and removing extents.
Please refer to the following patches for details.
[1] https://lore.kernel.org/linux-ext4/20241211160047.qnxvodmbzngo3jtr@quack3/
Thanks,
Yi.
Zhang Yi (9):
ext4: ext4: unify EXT4_EX_NOCACHE|NOFAIL flags in
ext4_ext_remove_space()
ext4: generalize EXT4_GET_BLOCKS_IO_SUBMIT flag usage
ext4: prevent stale extent cache entries caused by concurrent I/O
writeback
ext4: prevent stale extent cache entries caused by concurrent fiemap
ext4: prevent stale extent cache entries caused by concurrent get
es_cache
ext4: factor out is_special_ino()
ext4: introduce ext4_check_map_extents_env() debug helper
ext4: check env when mapping and modifying extents
ext4: clairfy the rules for modifying extents
fs/ext4/ext4.h | 26 ++++++++++++---
fs/ext4/extents.c | 54 ++++++++++++++++++++----------
fs/ext4/extents_status.c | 35 ++++++++++++++++++--
fs/ext4/fast_commit.c | 4 ++-
fs/ext4/inode.c | 71 +++++++++++++++++++++++++++++++---------
fs/ext4/ioctl.c | 8 ++++-
6 files changed, 157 insertions(+), 41 deletions(-)
--
2.46.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/9] ext4: ext4: unify EXT4_EX_NOCACHE|NOFAIL flags in ext4_ext_remove_space()
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
@ 2025-04-23 8:52 ` Zhang Yi
2025-04-23 8:52 ` [PATCH 2/9] ext4: generalize EXT4_GET_BLOCKS_IO_SUBMIT flag usage Zhang Yi
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
From: Zhang Yi <yi.zhang@huawei.com>
When removing space, we should use EXT4_EX_NOCACHE because we don't
need to cache extents, and we should also use EXT4_EX_NOFAIL to prevent
metadata inconsistencies that may arise from memory allocation failures.
While ext4_ext_remove_space() already uses these two flags in most
places, they are missing in ext4_ext_search_right() and
read_extent_tree_block() calls. Unify the flags to ensure consistent
behavior throughout the extent removal process.
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
fs/ext4/extents.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index c616a16a9f36..d8eac736cc9a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1530,7 +1530,7 @@ static int ext4_ext_search_left(struct inode *inode,
static int ext4_ext_search_right(struct inode *inode,
struct ext4_ext_path *path,
ext4_lblk_t *logical, ext4_fsblk_t *phys,
- struct ext4_extent *ret_ex)
+ struct ext4_extent *ret_ex, int flags)
{
struct buffer_head *bh = NULL;
struct ext4_extent_header *eh;
@@ -1604,7 +1604,8 @@ static int ext4_ext_search_right(struct inode *inode,
ix++;
while (++depth < path->p_depth) {
/* subtract from p_depth to get proper eh_depth */
- bh = read_extent_tree_block(inode, ix, path->p_depth - depth, 0);
+ bh = read_extent_tree_block(inode, ix, path->p_depth - depth,
+ flags);
if (IS_ERR(bh))
return PTR_ERR(bh);
eh = ext_block_hdr(bh);
@@ -1612,7 +1613,7 @@ static int ext4_ext_search_right(struct inode *inode,
put_bh(bh);
}
- bh = read_extent_tree_block(inode, ix, path->p_depth - depth, 0);
+ bh = read_extent_tree_block(inode, ix, path->p_depth - depth, flags);
if (IS_ERR(bh))
return PTR_ERR(bh);
eh = ext_block_hdr(bh);
@@ -2821,6 +2822,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
struct partial_cluster partial;
handle_t *handle;
int i = 0, err = 0;
+ int flags = EXT4_EX_NOCACHE | EXT4_EX_NOFAIL;
partial.pclu = 0;
partial.lblk = 0;
@@ -2851,8 +2853,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
ext4_fsblk_t pblk;
/* find extent for or closest extent to this block */
- path = ext4_find_extent(inode, end, NULL,
- EXT4_EX_NOCACHE | EXT4_EX_NOFAIL);
+ path = ext4_find_extent(inode, end, NULL, flags);
if (IS_ERR(path)) {
ext4_journal_stop(handle);
return PTR_ERR(path);
@@ -2918,7 +2919,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
*/
lblk = ex_end + 1;
err = ext4_ext_search_right(inode, path, &lblk, &pblk,
- NULL);
+ NULL, flags);
if (err < 0)
goto out;
if (pblk) {
@@ -2994,8 +2995,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
i + 1, ext4_idx_pblock(path[i].p_idx));
memset(path + i + 1, 0, sizeof(*path));
bh = read_extent_tree_block(inode, path[i].p_idx,
- depth - i - 1,
- EXT4_EX_NOCACHE);
+ depth - i - 1, flags);
if (IS_ERR(bh)) {
/* should we reset i_size? */
err = PTR_ERR(bh);
@@ -4314,7 +4314,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
if (err)
goto out;
ar.lright = map->m_lblk;
- err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright, &ex2);
+ err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright,
+ &ex2, 0);
if (err < 0)
goto out;
--
2.46.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/9] ext4: generalize EXT4_GET_BLOCKS_IO_SUBMIT flag usage
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
2025-04-23 8:52 ` [PATCH 1/9] ext4: ext4: unify EXT4_EX_NOCACHE|NOFAIL flags in ext4_ext_remove_space() Zhang Yi
@ 2025-04-23 8:52 ` Zhang Yi
2025-04-23 8:52 ` [PATCH 3/9] ext4: prevent stale extent cache entries caused by concurrent I/O writeback Zhang Yi
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
From: Zhang Yi <yi.zhang@huawei.com>
Currently, the EXT4_GET_BLOCKS_IO_SUBMIT flag is only used during data
writeback to indicate that in ordered mode, the journal commit thread
should skip re-submitting data and simply wait for I/O completion.
To prepare for later patches that need to detect I/O submission context
in ext4_map_blocks(), generalizes the meaning of
EXT4_GET_BLOCKS_IO_SUBMIT. This flag will be set during:
1) data I/O writeback,
2) I/O completion extents conversion,
3) journal performing commit in fast_commit.
This change doesn't affect current usage of this flag and provides a
clear way to identify I/O submission context.
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
fs/ext4/ext4.h | 13 ++++++++-----
fs/ext4/fast_commit.c | 3 ++-
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 5a20e9cd7184..ad39bfe4b5d2 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -706,9 +706,6 @@ enum {
#define EXT4_GET_BLOCKS_CONVERT 0x0010
#define EXT4_GET_BLOCKS_IO_CREATE_EXT (EXT4_GET_BLOCKS_PRE_IO|\
EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT)
- /* Convert extent to initialized after IO complete */
-#define EXT4_GET_BLOCKS_IO_CONVERT_EXT (EXT4_GET_BLOCKS_CONVERT|\
- EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT)
/* Eventual metadata allocation (due to growing extent tree)
* should not fail, so try to use reserved blocks for that.*/
#define EXT4_GET_BLOCKS_METADATA_NOFAIL 0x0020
@@ -720,9 +717,15 @@ enum {
#define EXT4_GET_BLOCKS_ZERO 0x0200
#define EXT4_GET_BLOCKS_CREATE_ZERO (EXT4_GET_BLOCKS_CREATE |\
EXT4_GET_BLOCKS_ZERO)
- /* Caller will submit data before dropping transaction handle. This
- * allows jbd2 to avoid submitting data before commit. */
+ /* Caller is in the context of data submission, such as writeback,
+ * fsync, etc. Especially, in the generic writeback path, caller will
+ * submit data before dropping transaction handle. This allows jbd2
+ * to avoid submitting data before commit. */
#define EXT4_GET_BLOCKS_IO_SUBMIT 0x0400
+ /* Convert extent to initialized after IO complete */
+#define EXT4_GET_BLOCKS_IO_CONVERT_EXT (EXT4_GET_BLOCKS_CONVERT |\
+ EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT |\
+ EXT4_GET_BLOCKS_IO_SUBMIT)
/* Caller is in the atomic contex, find extent if it has been cached */
#define EXT4_GET_BLOCKS_CACHED_NOWAIT 0x0800
diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index da4263a14a20..11c42b39478b 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -910,7 +910,8 @@ static int ext4_fc_write_inode_data(struct inode *inode, u32 *crc)
while (cur_lblk_off <= new_blk_size) {
map.m_lblk = cur_lblk_off;
map.m_len = new_blk_size - cur_lblk_off + 1;
- ret = ext4_map_blocks(NULL, inode, &map, 0);
+ ret = ext4_map_blocks(NULL, inode, &map,
+ EXT4_GET_BLOCKS_IO_SUBMIT);
if (ret < 0)
return -ECANCELED;
--
2.46.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/9] ext4: prevent stale extent cache entries caused by concurrent I/O writeback
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
2025-04-23 8:52 ` [PATCH 1/9] ext4: ext4: unify EXT4_EX_NOCACHE|NOFAIL flags in ext4_ext_remove_space() Zhang Yi
2025-04-23 8:52 ` [PATCH 2/9] ext4: generalize EXT4_GET_BLOCKS_IO_SUBMIT flag usage Zhang Yi
@ 2025-04-23 8:52 ` Zhang Yi
2025-04-23 8:52 ` [PATCH 4/9] ext4: prevent stale extent cache entries caused by concurrent fiemap Zhang Yi
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
From: Zhang Yi <yi.zhang@huawei.com>
Currently, in the I/O writeback path, ext4_map_blocks() may attempt to
cache additional unrelated extents in the extent status tree without
holding the inode's i_rwsem and the mapping's invalidate_lock. This can
lead to stale extent status entries remaining in certain scenarios,
potentially causing data corruption.
For example, when performing a collapse range in ext4_collapse_range(),
it clears the extent cache and dirty pages before removing blocks and
shifting extents. It also holds the i_data_sem during these two
operations. However, both ext4_ext_remove_space() and
ext4_ext_shift_extents() may briefly release the i_data_sem if journal
credits are insufficient (ext4_datasem_ensure_credits()). If another
writeback process writes dirty pages from other regions during this
interval, it may cache extents that are about to be modified. Unless
ext4_collapse_range() explicitly clears the extent cache again, these
cached entries can become stale and inconsistent with the actual
extents.
0 a n b c m
| | | | | |
[www][wwwwww][wwwwwwww]...[wwwww][wwww]...
| |
N M
Assume that block a is dirty. The collapse range operation is removing
data from n to m and drops i_data_sem immediately after removing the
extent from b to c. At the same time, a concurrent writeback begins to
write back block a; it will reloads the extent from [n, b) into the
extent status tree since it does not hold the i_rwsem or the
invalidate_lock. After the collapse range operation, it left the stale
extent [n, b), which points logical block n to N, but the actual
physical block of n should be M.
Similarly, both ext4_insert_range() and ext4_truncate() have the same
problem. ext4_punch_hole() survived since it re-add a hole extent entry
after removing space since commit 9f1118223aa0 ("ext4: add a hole extent
entry in cache after punch").
In most cases, during dirty page writeback, the block mapping
information is likely to be found in the extent cache, making it less
necessary to search for physical extents. Consequently, loading
unrelated extent caches during writeback appears to be ineffective.
Therefore, fix this by adds EXT4_EX_NOCACHE in the writeback path to
prevent caching of unrelated extents, eliminating this potential source
of corruption.
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
fs/ext4/ext4.h | 1 +
fs/ext4/extents.c | 12 +++++++++---
fs/ext4/fast_commit.c | 3 ++-
fs/ext4/inode.c | 28 ++++++++++++++++++++--------
4 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index ad39bfe4b5d2..f04cad83d74b 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -741,6 +741,7 @@ enum {
#define EXT4_EX_NOCACHE 0x40000000
#define EXT4_EX_FORCE_CACHE 0x20000000
#define EXT4_EX_NOFAIL 0x10000000
+#define EXT4_EX_FILTER 0x70000000
/*
* Flags used by ext4_free_blocks
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index d8eac736cc9a..8a5724b2dc51 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4202,7 +4202,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
/* find extent for this block */
- path = ext4_find_extent(inode, map->m_lblk, NULL, 0);
+ path = ext4_find_extent(inode, map->m_lblk, NULL, flags);
if (IS_ERR(path)) {
err = PTR_ERR(path);
goto out;
@@ -4315,7 +4315,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
goto out;
ar.lright = map->m_lblk;
err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright,
- &ex2, 0);
+ &ex2, flags);
if (err < 0)
goto out;
@@ -4820,8 +4820,14 @@ int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
break;
}
}
+ /*
+ * Do not cache any unrelated extents, as it does not hold the
+ * i_rwsem or invalidate_lock, which could corrupt the extent
+ * status tree.
+ */
ret = ext4_map_blocks(handle, inode, &map,
- EXT4_GET_BLOCKS_IO_CONVERT_EXT);
+ EXT4_GET_BLOCKS_IO_CONVERT_EXT |
+ EXT4_EX_NOCACHE);
if (ret <= 0)
ext4_warning(inode->i_sb,
"inode #%lu: block %u: len %u: "
diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index 11c42b39478b..ea4ec1ce9c85 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -911,7 +911,8 @@ static int ext4_fc_write_inode_data(struct inode *inode, u32 *crc)
map.m_lblk = cur_lblk_off;
map.m_len = new_blk_size - cur_lblk_off + 1;
ret = ext4_map_blocks(NULL, inode, &map,
- EXT4_GET_BLOCKS_IO_SUBMIT);
+ EXT4_GET_BLOCKS_IO_SUBMIT |
+ EXT4_EX_NOCACHE);
if (ret < 0)
return -ECANCELED;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 94c7d2d828a6..02eac9ee36f5 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -463,15 +463,16 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
#endif /* ES_AGGRESSIVE_TEST */
static int ext4_map_query_blocks(handle_t *handle, struct inode *inode,
- struct ext4_map_blocks *map)
+ struct ext4_map_blocks *map, int flags)
{
unsigned int status;
int retval;
+ flags &= EXT4_EX_FILTER;
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
- retval = ext4_ext_map_blocks(handle, inode, map, 0);
+ retval = ext4_ext_map_blocks(handle, inode, map, flags);
else
- retval = ext4_ind_map_blocks(handle, inode, map, 0);
+ retval = ext4_ind_map_blocks(handle, inode, map, flags);
if (retval <= 0)
return retval;
@@ -622,6 +623,13 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS))
return -EFSCORRUPTED;
+ /*
+ * Do not allow caching of unrelated ranges of extents during I/O
+ * submission.
+ */
+ if (flags & EXT4_GET_BLOCKS_IO_SUBMIT)
+ WARN_ON_ONCE(!(flags & EXT4_EX_NOCACHE));
+
/* Lookup extent status tree firstly */
if (!(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY) &&
ext4_es_lookup_extent(inode, map->m_lblk, NULL, &es)) {
@@ -667,7 +675,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
* file system block.
*/
down_read(&EXT4_I(inode)->i_data_sem);
- retval = ext4_map_query_blocks(handle, inode, map);
+ retval = ext4_map_query_blocks(handle, inode, map, flags);
up_read((&EXT4_I(inode)->i_data_sem));
found:
@@ -1805,7 +1813,7 @@ static int ext4_da_map_blocks(struct inode *inode, struct ext4_map_blocks *map)
if (ext4_has_inline_data(inode))
retval = 0;
else
- retval = ext4_map_query_blocks(NULL, inode, map);
+ retval = ext4_map_query_blocks(NULL, inode, map, 0);
up_read(&EXT4_I(inode)->i_data_sem);
if (retval)
return retval < 0 ? retval : 0;
@@ -1828,7 +1836,7 @@ static int ext4_da_map_blocks(struct inode *inode, struct ext4_map_blocks *map)
goto found;
}
} else if (!ext4_has_inline_data(inode)) {
- retval = ext4_map_query_blocks(NULL, inode, map);
+ retval = ext4_map_query_blocks(NULL, inode, map, 0);
if (retval) {
up_write(&EXT4_I(inode)->i_data_sem);
return retval < 0 ? retval : 0;
@@ -2212,11 +2220,15 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
* previously reserved. However we must not fail because we're in
* writeback and there is nothing we can do about it so it might result
* in data loss. So use reserved blocks to allocate metadata if
- * possible.
+ * possible. In addition, do not cache any unrelated extents, as it
+ * only holds the folio lock but does not hold the i_rwsem or
+ * invalidate_lock, which could corrupt the extent status tree.
*/
get_blocks_flags = EXT4_GET_BLOCKS_CREATE |
EXT4_GET_BLOCKS_METADATA_NOFAIL |
- EXT4_GET_BLOCKS_IO_SUBMIT;
+ EXT4_GET_BLOCKS_IO_SUBMIT |
+ EXT4_EX_NOCACHE;
+
dioread_nolock = ext4_should_dioread_nolock(inode);
if (dioread_nolock)
get_blocks_flags |= EXT4_GET_BLOCKS_IO_CREATE_EXT;
--
2.46.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/9] ext4: prevent stale extent cache entries caused by concurrent fiemap
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
` (2 preceding siblings ...)
2025-04-23 8:52 ` [PATCH 3/9] ext4: prevent stale extent cache entries caused by concurrent I/O writeback Zhang Yi
@ 2025-04-23 8:52 ` Zhang Yi
2025-04-23 8:52 ` [PATCH 5/9] ext4: prevent stale extent cache entries caused by concurrent get es_cache Zhang Yi
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
From: Zhang Yi <yi.zhang@huawei.com>
The ext4_fiemap() currently invokes ext4_ext_precache() and
iomap_fiemap() to preload the extent cache and query mapping information
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_fiemap() 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 in ext4_fiemap().
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
fs/ext4/extents.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 8a5724b2dc51..3adf05fbdd59 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4963,10 +4963,11 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
{
int error = 0;
+ inode_lock_shared(inode);
if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) {
error = ext4_ext_precache(inode);
if (error)
- return error;
+ goto unlock;
fieinfo->fi_flags &= ~FIEMAP_FLAG_CACHE;
}
@@ -4977,15 +4978,19 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
*/
error = ext4_fiemap_check_ranges(inode, start, &len);
if (error)
- return error;
+ goto unlock;
if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
fieinfo->fi_flags &= ~FIEMAP_FLAG_XATTR;
- return iomap_fiemap(inode, fieinfo, start, len,
- &ext4_iomap_xattr_ops);
+ error = iomap_fiemap(inode, fieinfo, start, len,
+ &ext4_iomap_xattr_ops);
+ } else {
+ error = iomap_fiemap(inode, fieinfo, start, len,
+ &ext4_iomap_report_ops);
}
-
- return iomap_fiemap(inode, fieinfo, start, len, &ext4_iomap_report_ops);
+unlock:
+ inode_unlock_shared(inode);
+ return error;
}
int ext4_get_es_cache(struct inode *inode, struct fiemap_extent_info *fieinfo,
--
2.46.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/9] ext4: prevent stale extent cache entries caused by concurrent get es_cache
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
` (3 preceding siblings ...)
2025-04-23 8:52 ` [PATCH 4/9] ext4: prevent stale extent cache entries caused by concurrent fiemap Zhang Yi
@ 2025-04-23 8:52 ` Zhang Yi
2025-04-23 8:52 ` [PATCH 6/9] ext4: factor out is_special_ino() Zhang Yi
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
From: Zhang Yi <yi.zhang@huawei.com>
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>
---
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 3adf05fbdd59..b5eb89ef7ae2 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -5011,7 +5011,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 d17207386ead..0e240013c84d 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -1505,8 +1505,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.46.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/9] ext4: factor out is_special_ino()
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
` (4 preceding siblings ...)
2025-04-23 8:52 ` [PATCH 5/9] ext4: prevent stale extent cache entries caused by concurrent get es_cache Zhang Yi
@ 2025-04-23 8:52 ` Zhang Yi
2025-04-23 8:52 ` [PATCH 7/9] ext4: introduce ext4_check_map_extents_env() debug helper Zhang Yi
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
From: Zhang Yi <yi.zhang@huawei.com>
Factor out the helper is_special_ino() to facilitate the checking of
special inodes in the subsequent patches.
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
fs/ext4/ext4.h | 11 +++++++++++
fs/ext4/inode.c | 7 +------
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f04cad83d74b..ccc1de1e23a9 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3054,6 +3054,17 @@ extern void ext4_da_update_reserve_space(struct inode *inode,
extern int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk,
ext4_fsblk_t pblk, ext4_lblk_t len);
+static inline bool is_special_ino(struct super_block *sb, unsigned long ino)
+{
+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+
+ return (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) ||
+ ino == le32_to_cpu(es->s_usr_quota_inum) ||
+ ino == le32_to_cpu(es->s_grp_quota_inum) ||
+ ino == le32_to_cpu(es->s_prj_quota_inum) ||
+ ino == le32_to_cpu(es->s_orphan_file_inum);
+}
+
/* indirect.c */
extern int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
struct ext4_map_blocks *map, int flags);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 02eac9ee36f5..51801f6d23ef 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4793,12 +4793,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
gid_t i_gid;
projid_t i_projid;
- if ((!(flags & EXT4_IGET_SPECIAL) &&
- ((ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) ||
- ino == le32_to_cpu(es->s_usr_quota_inum) ||
- ino == le32_to_cpu(es->s_grp_quota_inum) ||
- ino == le32_to_cpu(es->s_prj_quota_inum) ||
- ino == le32_to_cpu(es->s_orphan_file_inum))) ||
+ if ((!(flags & EXT4_IGET_SPECIAL) && is_special_ino(sb, ino)) ||
(ino < EXT4_ROOT_INO) ||
(ino > le32_to_cpu(es->s_inodes_count))) {
if (flags & EXT4_IGET_HANDLE)
--
2.46.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 7/9] ext4: introduce ext4_check_map_extents_env() debug helper
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
` (5 preceding siblings ...)
2025-04-23 8:52 ` [PATCH 6/9] ext4: factor out is_special_ino() Zhang Yi
@ 2025-04-23 8:52 ` Zhang Yi
2025-04-23 8:52 ` [PATCH 8/9] ext4: check env when mapping and modifying extents Zhang Yi
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
From: Zhang Yi <yi.zhang@huawei.com>
Loading and modifying the extents tree and extent status tree without
holding the inode's i_rwsem or the mapping's invalidate_lock is not
permitted, except during the I/O writeback. Add a new debug helper
ext4_check_map_extents_env(), it will verify whether the extent
loading/modifying context is safe.
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
fs/ext4/ext4.h | 1 +
fs/ext4/inode.c | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index ccc1de1e23a9..3b1bf52737e3 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2977,6 +2977,7 @@ static inline bool ext4_mb_cr_expensive(enum criteria cr)
void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw,
struct ext4_inode_info *ei);
int ext4_inode_is_fast_symlink(struct inode *inode);
+void ext4_check_map_extents_env(struct inode *inode);
struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int);
struct buffer_head *ext4_bread(handle_t *, struct inode *, ext4_lblk_t, int);
int ext4_bread_batch(struct inode *inode, ext4_lblk_t block, int bh_count,
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 51801f6d23ef..74c7a902a41d 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -416,6 +416,32 @@ int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,
return ret;
}
+/*
+ * For generic regular files, when updating the extent tree, Ext4 should
+ * hold the i_rwsem and invalidate_lock exclusively. This ensures
+ * exclusion against concurrent page faults, as well as reads and writes.
+ */
+#ifdef CONFIG_EXT4_DEBUG
+void ext4_check_map_extents_env(struct inode *inode)
+{
+ if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
+ return;
+
+ if (!S_ISREG(inode->i_mode) ||
+ IS_NOQUOTA(inode) || IS_VERITY(inode) ||
+ is_special_ino(inode->i_sb, inode->i_ino) ||
+ (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) ||
+ ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
+ ext4_verity_in_progress(inode))
+ return;
+
+ WARN_ON_ONCE(!inode_is_locked(inode) &&
+ !rwsem_is_locked(&inode->i_mapping->invalidate_lock));
+}
+#else
+void ext4_check_map_extents_env(struct inode *inode) {}
+#endif
+
#define check_block_validity(inode, map) \
__check_block_validity((inode), __func__, __LINE__, (map))
--
2.46.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 8/9] ext4: check env when mapping and modifying extents
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
` (6 preceding siblings ...)
2025-04-23 8:52 ` [PATCH 7/9] ext4: introduce ext4_check_map_extents_env() debug helper Zhang Yi
@ 2025-04-23 8:52 ` Zhang Yi
2025-04-23 8:52 ` [PATCH 9/9] ext4: clairfy the rules for " Zhang Yi
2025-05-20 14:40 ` [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Theodore Ts'o
9 siblings, 0 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
From: Zhang Yi <yi.zhang@huawei.com>
Add ext4_check_map_extents_env() to the places where loading extents,
mapping blocks, removing blocks, and modifying extents, excluding the
I/O writeback context. This function will verify whether the locking
mechanisms in place are adequate.
Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
fs/ext4/extents.c | 6 ++++++
fs/ext4/inode.c | 14 +++++++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index b5eb89ef7ae2..52bfc042bf4e 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -611,6 +611,8 @@ int ext4_ext_precache(struct inode *inode)
if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
return 0; /* not an extent-mapped inode */
+ ext4_check_map_extents_env(inode);
+
down_read(&ei->i_data_sem);
depth = ext_depth(inode);
@@ -5342,6 +5344,8 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
start_lblk = offset >> inode->i_blkbits;
end_lblk = (offset + len) >> inode->i_blkbits;
+ ext4_check_map_extents_env(inode);
+
down_write(&EXT4_I(inode)->i_data_sem);
ext4_discard_preallocations(inode);
ext4_es_remove_extent(inode, start_lblk, EXT_MAX_BLOCKS - start_lblk);
@@ -5443,6 +5447,8 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
start_lblk = offset >> inode->i_blkbits;
len_lblk = len >> inode->i_blkbits;
+ ext4_check_map_extents_env(inode);
+
down_write(&EXT4_I(inode)->i_data_sem);
ext4_discard_preallocations(inode);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 74c7a902a41d..1211ad7fa98d 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -650,11 +650,14 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
return -EFSCORRUPTED;
/*
- * Do not allow caching of unrelated ranges of extents during I/O
- * submission.
+ * Callers from the context of data submission are the only exceptions
+ * for regular files that do not hold the i_rwsem or invalidate_lock.
+ * However, caching unrelated ranges is not permitted.
*/
if (flags & EXT4_GET_BLOCKS_IO_SUBMIT)
WARN_ON_ONCE(!(flags & EXT4_EX_NOCACHE));
+ else
+ ext4_check_map_extents_env(inode);
/* Lookup extent status tree firstly */
if (!(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY) &&
@@ -1799,6 +1802,8 @@ static int ext4_da_map_blocks(struct inode *inode, struct ext4_map_blocks *map)
ext_debug(inode, "max_blocks %u, logical block %lu\n", map->m_len,
(unsigned long) map->m_lblk);
+ ext4_check_map_extents_env(inode);
+
/* Lookup extent status tree firstly */
if (ext4_es_lookup_extent(inode, map->m_lblk, NULL, &es)) {
map->m_len = min_t(unsigned int, map->m_len,
@@ -4110,6 +4115,8 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
if (end_lblk > start_lblk) {
ext4_lblk_t hole_len = end_lblk - start_lblk;
+ ext4_check_map_extents_env(inode);
+
down_write(&EXT4_I(inode)->i_data_sem);
ext4_discard_preallocations(inode);
@@ -4262,8 +4269,9 @@ int ext4_truncate(struct inode *inode)
if (err)
goto out_stop;
- down_write(&EXT4_I(inode)->i_data_sem);
+ ext4_check_map_extents_env(inode);
+ down_write(&EXT4_I(inode)->i_data_sem);
ext4_discard_preallocations(inode);
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
--
2.46.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 9/9] ext4: clairfy the rules for modifying extents
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
` (7 preceding siblings ...)
2025-04-23 8:52 ` [PATCH 8/9] ext4: check env when mapping and modifying extents Zhang Yi
@ 2025-04-23 8:52 ` Zhang Yi
2025-05-20 14:40 ` [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Theodore Ts'o
9 siblings, 0 replies; 11+ messages in thread
From: Zhang Yi @ 2025-04-23 8:52 UTC (permalink / raw)
To: linux-ext4
Cc: linux-fsdevel, linux-kernel, tytso, adilger.kernel, jack,
yi.zhang, yi.zhang, libaokun1, yukuai3, yangerkun
From: Zhang Yi <yi.zhang@huawei.com>
Add a comment at the beginning of extents_status.c to clarify the rules
for loading, mapping, modifying, and removing extents and blocks.
Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
fs/ext4/extents_status.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index d1401d4a5513..31dc0496f8d0 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -120,9 +120,40 @@
* memory. Hence, we will reclaim written/unwritten/hole extents from
* the tree under a heavy memory pressure.
*
+ * ==========================================================================
+ * 3. Assurance of Ext4 extent status tree consistency
+ *
+ * When mapping blocks, Ext4 queries the extent status tree first and should
+ * always trusts that the extent status tree is consistent and up to date.
+ * Therefore, it is important to adheres to the following rules when createing,
+ * modifying and removing extents.
+ *
+ * 1. Besides fastcommit replay, when Ext4 creates or queries block mappings,
+ * the extent information should always be processed through the extent
+ * status tree instead of being organized manually through the on-disk
+ * extent tree.
+ *
+ * 2. When updating the extent tree, Ext4 should acquire the i_data_sem
+ * exclusively and update the extent status tree atomically. If the extents
+ * to be modified are large enough to exceed the range that a single
+ * i_data_sem can process (as ext4_datasem_ensure_credits() may drop
+ * i_data_sem to restart a transaction), it must (e.g. as ext4_punch_hole()
+ * does):
+ *
+ * a) Hold the i_rwsem and invalidate_lock exclusively. This ensures
+ * exclusion against page faults, as well as reads and writes that may
+ * concurrently modify the extent status tree.
+ * b) Evict all page cache in the affected range and recommend rebuilding
+ * or dropping the extent status tree after modifying the on-disk
+ * extent tree. This ensures exclusion against concurrent writebacks
+ * that do not hold those locks but only holds a folio lock.
+ *
+ * 3. Based on the rules above, when querying block mappings, Ext4 should at
+ * least hold the i_rwsem or invalidate_lock or folio lock(s) for the
+ * specified querying range.
*
* ==========================================================================
- * 3. Performance analysis
+ * 4. Performance analysis
*
* -- overhead
* 1. There is a cache extent for write access, so if writes are
@@ -134,7 +165,7 @@
*
*
* ==========================================================================
- * 4. TODO list
+ * 5. TODO list
*
* -- Refactor delayed space reservation
*
--
2.46.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
` (8 preceding siblings ...)
2025-04-23 8:52 ` [PATCH 9/9] ext4: clairfy the rules for " Zhang Yi
@ 2025-05-20 14:40 ` Theodore Ts'o
9 siblings, 0 replies; 11+ messages in thread
From: Theodore Ts'o @ 2025-05-20 14:40 UTC (permalink / raw)
To: linux-ext4, Zhang Yi
Cc: Theodore Ts'o, linux-fsdevel, linux-kernel, adilger.kernel,
jack, yi.zhang, libaokun1, yukuai3, yangerkun
On Wed, 23 Apr 2025 16:52:48 +0800, Zhang Yi wrote:
> This patch series addresses the potential problems discussed with Jan
> Kara regarding the modification rules for mapping extents[1]. Preparing
> for the buffered I/O conversion for regular files.
>
> This change includes:
>
> Patch 1-5 fixes problems related to stale extent status entries that
> may arise during the collapsing of ranges, the insertion of ranges, or
> file truncation when these operations compete with concurrent writeback,
> fiemap, or get extent cache.
>
> [...]
Applied, thanks!
[1/9] ext4: ext4: unify EXT4_EX_NOCACHE|NOFAIL flags in ext4_ext_remove_space()
commit: 53ce42accd2002cc490fc86000ac532530507a74
[2/9] ext4: generalize EXT4_GET_BLOCKS_IO_SUBMIT flag usage
commit: 86b349ce0312a397a6961e457108556e44a3d211
[3/9] ext4: prevent stale extent cache entries caused by concurrent I/O writeback
commit: 402e38e6b71f5739119ca3107f375e112d63c7c5
[4/9] ext4: prevent stale extent cache entries caused by concurrent fiemap
commit: 151ff9325e5e17c97839a00b740726656b04647b
[5/9] ext4: prevent stale extent cache entries caused by concurrent get es_cache
commit: f22a0ef2231a7d8374bb021eb86404d0e9de5a02
[6/9] ext4: factor out is_special_ino()
commit: 0b8e0bd45007d5740391e658c2581bd614207387
[7/9] ext4: introduce ext4_check_map_extents_env() debug helper
commit: 7871da20d484d5c7e536bfd52845b6be4488ff30
[8/9] ext4: check env when mapping and modifying extents
commit: 1b4d2a0b794669e54914e3f429c08e49ea40b40c
[9/9] ext4: clairfy the rules for modifying extents
commit: 24b7a2331fcdf6de103ea85e67eede43c0372f77
Best regards,
--
Theodore Ts'o <tytso@mit.edu>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-05-20 14:40 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-23 8:52 [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Zhang Yi
2025-04-23 8:52 ` [PATCH 1/9] ext4: ext4: unify EXT4_EX_NOCACHE|NOFAIL flags in ext4_ext_remove_space() Zhang Yi
2025-04-23 8:52 ` [PATCH 2/9] ext4: generalize EXT4_GET_BLOCKS_IO_SUBMIT flag usage Zhang Yi
2025-04-23 8:52 ` [PATCH 3/9] ext4: prevent stale extent cache entries caused by concurrent I/O writeback Zhang Yi
2025-04-23 8:52 ` [PATCH 4/9] ext4: prevent stale extent cache entries caused by concurrent fiemap Zhang Yi
2025-04-23 8:52 ` [PATCH 5/9] ext4: prevent stale extent cache entries caused by concurrent get es_cache Zhang Yi
2025-04-23 8:52 ` [PATCH 6/9] ext4: factor out is_special_ino() Zhang Yi
2025-04-23 8:52 ` [PATCH 7/9] ext4: introduce ext4_check_map_extents_env() debug helper Zhang Yi
2025-04-23 8:52 ` [PATCH 8/9] ext4: check env when mapping and modifying extents Zhang Yi
2025-04-23 8:52 ` [PATCH 9/9] ext4: clairfy the rules for " Zhang Yi
2025-05-20 14:40 ` [PATCH 0/9] ext4: fix stale extent status entries and clairfy rules Theodore Ts'o
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).