* [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path
@ 2024-08-22 2:35 libaokun
2024-08-22 2:35 ` [PATCH v2 01/25] ext4: refactor ext4_ext_rm_idx() to index 'path' libaokun
` (25 more replies)
0 siblings, 26 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
Hi all!
This patch series is a hardening of ext4 extents path related code.
This is the second version of this patch series. Thank you, Jan Kara and
Ojaswin Mujoo, for the feedback in the previous version. The new version
has no functional changes compared to the previous one, so I've kept the
previous Reviewed-by, please let me know if you have any objections.
The following is a brief overview of the patches, see the patches for
more details.
Patch 1-2: Refactor ext4_ext_rm_idx() as suggested by Jan, and add
appropriate error handling branches to ext4_ext_rm_idx() and
ext4_ext_correct_indexes() to avoid inconsistent extents tree.
PS: This comes from the previous work of my colleague zhanchengbin
(see link), who is no longer in charge of these and I have taken over.
Link: https://lore.kernel.org/r/20230213080514.535568-3-zhanchengbin1@huawei.com/
Patch 3-7: Quick fixes for use-after-free and double-free problems caused
by mixing path(pointer to an extent path) and ppath(pointer to an extent
path pointer).
Patch 8-9: Fix an issue that caused p_bh to be released twice if it wasn't
set to NULL after path->p_bh was released. And add a helper function after
the quick fix to prevent this from happening again.
Patch 10: Fix an issue where the error returned by ext4_find_extent in
ext4_insert_range() was not propagated correctly.
Patch 11-22: Now the use of path and ppath is so confusing that we can
trigger use-after-free or double-free by accessing a stale pointer, or
we can get a memory leak by forgetting to update ppath. And it's very
difficult to read the code. So to make the code more readable, get rid
of ppath and pass path between functions uniformly to avoid these risks.
Patch 23-24: Reduces the consumption of unnecessary memory operations by
avoiding repetitive allocation and release extents path.
Patch 25:Clean up ext4_ext_create_new_leaf() to reduce some unnecessary
indentation and line breaks.
"kvm-xfstests -c ext4/all -g auto" has been executed with no new failures.
Randomly injecting faults(EIO, ENOMEM, Realloc Path) in ext4_find_extent()
while executing xfstests also did not observe new Oops.
Comments and questions are, as always, welcome.
Please let me know what you think.
Thanks,
Baokun
Changes since v1:
* Collect RVB from Honza and Ojaswin.(Thanks for your review!)
* Patch 5: A quick fix has been added for a null pointer or memory leak
that could be caused by ppath remaining NULL when path is reallocated.
* Patch 6: Added a quick fix for the UAF that could be caused by a path
not being updated when the ppath is reallocated.(Spotted by Ojaswin)
* Patch 8: Correct the trace stack in commit message.(Spotted by Ojaswin)
* Patch 10: Quick fixes split from Patch 15 to be easily pulled into
stable.(Suggested by Honza)
* Patch 23: A refactoring split from Patch 16 for easy review.(Suggested
by Ojaswin)
* Patch 24: Modify the patch subject.
* Patch 25: Added cleanup patch to remove unnecessary indentation and
line breaks in ext4_ext_create_new_leaf().(Suggested by Honza)
* Adjust the sequence of patches.
v1: https://lore.kernel.org/r/20240710040654.1714672-1-libaokun@huaweicloud.com
Baokun Li (25):
ext4: refactor ext4_ext_rm_idx() to index 'path'
ext4: prevent partial update of the extents path
ext4: fix slab-use-after-free in ext4_split_extent_at()
ext4: avoid use-after-free in ext4_ext_show_leaf()
ext4: update orig_path in ext4_find_extent()
ext4: aovid use-after-free in ext4_ext_insert_extent()
ext4: drop ppath from ext4_ext_replay_update_ex() to avoid double-free
ext4: fix double brelse() the buffer of the extents path
ext4: add new ext4_ext_path_brelse() helper
ext4: propagate errors from ext4_find_extent() in ext4_insert_range()
ext4: get rid of ppath in ext4_find_extent()
ext4: get rid of ppath in get_ext_path()
ext4: get rid of ppath in ext4_ext_create_new_leaf()
ext4: get rid of ppath in ext4_ext_insert_extent()
ext4: get rid of ppath in ext4_split_extent_at()
ext4: get rid of ppath in ext4_force_split_extent_at()
ext4: get rid of ppath in ext4_split_extent()
ext4: get rid of ppath in ext4_split_convert_extents()
ext4: get rid of ppath in ext4_convert_unwritten_extents_endio()
ext4: get rid of ppath in ext4_ext_convert_to_initialized()
ext4: get rid of ppath in ext4_ext_handle_unwritten_extents()
ext4: get rid of ppath in convert_initialized_extent()
ext4: refactor ext4_swap_extents() to reuse extents path
ext4: make some fast commit functions reuse extents path
ext4: save unnecessary indentation in ext4_ext_create_new_leaf()
fs/ext4/ext4.h | 9 +-
fs/ext4/extents.c | 781 +++++++++++++++++++++++-------------------
fs/ext4/fast_commit.c | 17 +-
fs/ext4/migrate.c | 5 +-
fs/ext4/move_extent.c | 36 +-
5 files changed, 456 insertions(+), 392 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v2 01/25] ext4: refactor ext4_ext_rm_idx() to index 'path'
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 02/25] ext4: prevent partial update of the extents path libaokun
` (24 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
As suggested by Honza in Link,modify ext4_ext_rm_idx() to leave 'path'
alone and just index it like ext4_ext_correct_indexes() does it. This
facilitates adding error handling later. No functional changes.
Suggested-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/all/20230216130305.nrbtd42tppxhbynn@quack3/
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 32 +++++++++++++++-----------------
1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index e067f2dd0335..bff3666c891a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2279,27 +2279,26 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
{
int err;
ext4_fsblk_t leaf;
+ int k = depth - 1;
/* free index block */
- depth--;
- path = path + depth;
- leaf = ext4_idx_pblock(path->p_idx);
- if (unlikely(path->p_hdr->eh_entries == 0)) {
- EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0");
+ leaf = ext4_idx_pblock(path[k].p_idx);
+ if (unlikely(path[k].p_hdr->eh_entries == 0)) {
+ EXT4_ERROR_INODE(inode, "path[%d].p_hdr->eh_entries == 0", k);
return -EFSCORRUPTED;
}
- err = ext4_ext_get_access(handle, inode, path);
+ err = ext4_ext_get_access(handle, inode, path + k);
if (err)
return err;
- if (path->p_idx != EXT_LAST_INDEX(path->p_hdr)) {
- int len = EXT_LAST_INDEX(path->p_hdr) - path->p_idx;
+ if (path[k].p_idx != EXT_LAST_INDEX(path[k].p_hdr)) {
+ int len = EXT_LAST_INDEX(path[k].p_hdr) - path[k].p_idx;
len *= sizeof(struct ext4_extent_idx);
- memmove(path->p_idx, path->p_idx + 1, len);
+ memmove(path[k].p_idx, path[k].p_idx + 1, len);
}
- le16_add_cpu(&path->p_hdr->eh_entries, -1);
- err = ext4_ext_dirty(handle, inode, path);
+ le16_add_cpu(&path[k].p_hdr->eh_entries, -1);
+ err = ext4_ext_dirty(handle, inode, path + k);
if (err)
return err;
ext_debug(inode, "index is empty, remove it, free block %llu\n", leaf);
@@ -2308,15 +2307,14 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
ext4_free_blocks(handle, inode, NULL, leaf, 1,
EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
- while (--depth >= 0) {
- if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr))
+ while (--k >= 0) {
+ if (path[k + 1].p_idx != EXT_FIRST_INDEX(path[k + 1].p_hdr))
break;
- path--;
- err = ext4_ext_get_access(handle, inode, path);
+ err = ext4_ext_get_access(handle, inode, path + k);
if (err)
break;
- path->p_idx->ei_block = (path+1)->p_idx->ei_block;
- err = ext4_ext_dirty(handle, inode, path);
+ path[k].p_idx->ei_block = path[k + 1].p_idx->ei_block;
+ err = ext4_ext_dirty(handle, inode, path + k);
if (err)
break;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 02/25] ext4: prevent partial update of the extents path
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
2024-08-22 2:35 ` [PATCH v2 01/25] ext4: refactor ext4_ext_rm_idx() to index 'path' libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 03/25] ext4: fix slab-use-after-free in ext4_split_extent_at() libaokun
` (23 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li, zhanchengbin
From: Baokun Li <libaokun1@huawei.com>
In ext4_ext_rm_idx() and ext4_ext_correct_indexes(), there is no proper
rollback of already executed updates when updating a level of the extents
path fails, so we may get an inconsistent extents tree, which may trigger
some bad things in errors=continue mode.
Hence clear the verified bit of modified extents buffers if the tree fails
to be updated in ext4_ext_rm_idx() or ext4_ext_correct_indexes(), which
forces the extents buffers to be checked in ext4_valid_extent_entries(),
ensuring that the extents tree is consistent.
Signed-off-by: zhanchengbin <zhanchengbin1@huawei.com>
Link: https://lore.kernel.org/r/20230213080514.535568-3-zhanchengbin1@huawei.com/
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 31 +++++++++++++++++++++++++++----
1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index bff3666c891a..4d589d34b30e 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1749,12 +1749,23 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
break;
err = ext4_ext_get_access(handle, inode, path + k);
if (err)
- break;
+ goto clean;
path[k].p_idx->ei_block = border;
err = ext4_ext_dirty(handle, inode, path + k);
if (err)
- break;
+ goto clean;
}
+ return 0;
+
+clean:
+ /*
+ * The path[k].p_bh is either unmodified or with no verified bit
+ * set (see ext4_ext_get_access()). So just clear the verified bit
+ * of the successfully modified extents buffers, which will force
+ * these extents to be checked to avoid using inconsistent data.
+ */
+ while (++k < depth)
+ clear_buffer_verified(path[k].p_bh);
return err;
}
@@ -2312,12 +2323,24 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
break;
err = ext4_ext_get_access(handle, inode, path + k);
if (err)
- break;
+ goto clean;
path[k].p_idx->ei_block = path[k + 1].p_idx->ei_block;
err = ext4_ext_dirty(handle, inode, path + k);
if (err)
- break;
+ goto clean;
}
+ return 0;
+
+clean:
+ /*
+ * The path[k].p_bh is either unmodified or with no verified bit
+ * set (see ext4_ext_get_access()). So just clear the verified bit
+ * of the successfully modified extents buffers, which will force
+ * these extents to be checked to avoid using inconsistent data.
+ */
+ while (++k < depth)
+ clear_buffer_verified(path[k].p_bh);
+
return err;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 03/25] ext4: fix slab-use-after-free in ext4_split_extent_at()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
2024-08-22 2:35 ` [PATCH v2 01/25] ext4: refactor ext4_ext_rm_idx() to index 'path' libaokun
2024-08-22 2:35 ` [PATCH v2 02/25] ext4: prevent partial update of the extents path libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 04/25] ext4: avoid use-after-free in ext4_ext_show_leaf() libaokun
` (22 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li, stable
From: Baokun Li <libaokun1@huawei.com>
We hit the following use-after-free:
==================================================================
BUG: KASAN: slab-use-after-free in ext4_split_extent_at+0xba8/0xcc0
Read of size 2 at addr ffff88810548ed08 by task kworker/u20:0/40
CPU: 0 PID: 40 Comm: kworker/u20:0 Not tainted 6.9.0-dirty #724
Call Trace:
<TASK>
kasan_report+0x93/0xc0
ext4_split_extent_at+0xba8/0xcc0
ext4_split_extent.isra.0+0x18f/0x500
ext4_split_convert_extents+0x275/0x750
ext4_ext_handle_unwritten_extents+0x73e/0x1580
ext4_ext_map_blocks+0xe20/0x2dc0
ext4_map_blocks+0x724/0x1700
ext4_do_writepages+0x12d6/0x2a70
[...]
Allocated by task 40:
__kmalloc_noprof+0x1ac/0x480
ext4_find_extent+0xf3b/0x1e70
ext4_ext_map_blocks+0x188/0x2dc0
ext4_map_blocks+0x724/0x1700
ext4_do_writepages+0x12d6/0x2a70
[...]
Freed by task 40:
kfree+0xf1/0x2b0
ext4_find_extent+0xa71/0x1e70
ext4_ext_insert_extent+0xa22/0x3260
ext4_split_extent_at+0x3ef/0xcc0
ext4_split_extent.isra.0+0x18f/0x500
ext4_split_convert_extents+0x275/0x750
ext4_ext_handle_unwritten_extents+0x73e/0x1580
ext4_ext_map_blocks+0xe20/0x2dc0
ext4_map_blocks+0x724/0x1700
ext4_do_writepages+0x12d6/0x2a70
[...]
==================================================================
The flow of issue triggering is as follows:
ext4_split_extent_at
path = *ppath
ext4_ext_insert_extent(ppath)
ext4_ext_create_new_leaf(ppath)
ext4_find_extent(orig_path)
path = *orig_path
read_extent_tree_block
// return -ENOMEM or -EIO
ext4_free_ext_path(path)
kfree(path)
*orig_path = NULL
a. If err is -ENOMEM:
ext4_ext_dirty(path + path->p_depth)
// path use-after-free !!!
b. If err is -EIO and we have EXT_DEBUG defined:
ext4_ext_show_leaf(path)
eh = path[depth].p_hdr
// path also use-after-free !!!
So when trying to zeroout or fix the extent length, call ext4_find_extent()
to update the path.
In addition we use *ppath directly as an ext4_ext_show_leaf() input to
avoid possible use-after-free when EXT_DEBUG is defined, and to avoid
unnecessary path updates.
Fixes: dfe5080939ea ("ext4: drop EXT4_EX_NOFREE_ON_ERR from rest of extents handling code")
Cc: stable@kernel.org
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 4d589d34b30e..ff4cfd8edeb7 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3251,6 +3251,25 @@ static int ext4_split_extent_at(handle_t *handle,
if (err != -ENOSPC && err != -EDQUOT && err != -ENOMEM)
goto out;
+ /*
+ * Update path is required because previous ext4_ext_insert_extent()
+ * may have freed or reallocated the path. Using EXT4_EX_NOFAIL
+ * guarantees that ext4_find_extent() will not return -ENOMEM,
+ * otherwise -ENOMEM will cause a retry in do_writepages(), and a
+ * WARN_ON may be triggered in ext4_da_update_reserve_space() due to
+ * an incorrect ee_len causing the i_reserved_data_blocks exception.
+ */
+ path = ext4_find_extent(inode, ee_block, ppath,
+ flags | EXT4_EX_NOFAIL);
+ if (IS_ERR(path)) {
+ EXT4_ERROR_INODE(inode, "Failed split extent on %u, err %ld",
+ split, PTR_ERR(path));
+ return PTR_ERR(path);
+ }
+ depth = ext_depth(inode);
+ ex = path[depth].p_ext;
+ *ppath = path;
+
if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
if (split_flag & EXT4_EXT_DATA_VALID1) {
@@ -3303,7 +3322,7 @@ static int ext4_split_extent_at(handle_t *handle,
ext4_ext_dirty(handle, inode, path + path->p_depth);
return err;
out:
- ext4_ext_show_leaf(inode, path);
+ ext4_ext_show_leaf(inode, *ppath);
return err;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 04/25] ext4: avoid use-after-free in ext4_ext_show_leaf()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (2 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 03/25] ext4: fix slab-use-after-free in ext4_split_extent_at() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 05/25] ext4: update orig_path in ext4_find_extent() libaokun
` (21 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
In ext4_find_extent(), path may be freed by error or be reallocated, so
using a previously saved *ppath may have been freed and thus may trigger
use-after-free, as follows:
ext4_split_extent
path = *ppath;
ext4_split_extent_at(ppath)
path = ext4_find_extent(ppath)
ext4_split_extent_at(ppath)
// ext4_find_extent fails to free path
// but zeroout succeeds
ext4_ext_show_leaf(inode, path)
eh = path[depth].p_hdr
// path use-after-free !!!
Similar to ext4_split_extent_at(), we use *ppath directly as an input to
ext4_ext_show_leaf(). Fix a spelling error by the way.
Same problem in ext4_ext_handle_unwritten_extents(). Since 'path' is only
used in ext4_ext_show_leaf(), remove 'path' and use *ppath directly.
This issue is triggered only when EXT_DEBUG is defined and therefore does
not affect functionality.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index ff4cfd8edeb7..0224cf0ef19e 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3327,7 +3327,7 @@ static int ext4_split_extent_at(handle_t *handle,
}
/*
- * ext4_split_extents() splits an extent and mark extent which is covered
+ * ext4_split_extent() splits an extent and mark extent which is covered
* by @map as split_flags indicates
*
* It may result in splitting the extent into multiple extents (up to three)
@@ -3403,7 +3403,7 @@ static int ext4_split_extent(handle_t *handle,
goto out;
}
- ext4_ext_show_leaf(inode, path);
+ ext4_ext_show_leaf(inode, *ppath);
out:
return err ? err : allocated;
}
@@ -3868,14 +3868,13 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
struct ext4_ext_path **ppath, int flags,
unsigned int allocated, ext4_fsblk_t newblock)
{
- struct ext4_ext_path __maybe_unused *path = *ppath;
int ret = 0;
int err = 0;
ext_debug(inode, "logical block %llu, max_blocks %u, flags 0x%x, allocated %u\n",
(unsigned long long)map->m_lblk, map->m_len, flags,
allocated);
- ext4_ext_show_leaf(inode, path);
+ ext4_ext_show_leaf(inode, *ppath);
/*
* When writing into unwritten space, we should not fail to
@@ -3972,7 +3971,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
if (allocated > map->m_len)
allocated = map->m_len;
map->m_len = allocated;
- ext4_ext_show_leaf(inode, path);
+ ext4_ext_show_leaf(inode, *ppath);
out2:
return err ? err : allocated;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 05/25] ext4: update orig_path in ext4_find_extent()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (3 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 04/25] ext4: avoid use-after-free in ext4_ext_show_leaf() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-27 18:04 ` Jan Kara
2024-08-22 2:35 ` [PATCH v2 06/25] ext4: aovid use-after-free in ext4_ext_insert_extent() libaokun
` (20 subsequent siblings)
25 siblings, 1 reply; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li, stable
From: Baokun Li <libaokun1@huawei.com>
In ext4_find_extent(), if the path is not big enough, we free it and set
*orig_path to NULL. But after reallocating and successfully initializing
the path, we don't update *orig_path, in which case the caller gets a
valid path but a NULL ppath, and this may cause a NULL pointer dereference
or a path memory leak. For example:
ext4_split_extent
path = *ppath = 2000
ext4_find_extent
if (depth > path[0].p_maxdepth)
kfree(path = 2000);
*orig_path = path = NULL;
path = kcalloc() = 3000
ext4_split_extent_at(*ppath = NULL)
path = *ppath;
ex = path[depth].p_ext;
// NULL pointer dereference!
==================================================================
BUG: kernel NULL pointer dereference, address: 0000000000000010
CPU: 6 UID: 0 PID: 576 Comm: fsstress Not tainted 6.11.0-rc2-dirty #847
RIP: 0010:ext4_split_extent_at+0x6d/0x560
Call Trace:
<TASK>
ext4_split_extent.isra.0+0xcb/0x1b0
ext4_ext_convert_to_initialized+0x168/0x6c0
ext4_ext_handle_unwritten_extents+0x325/0x4d0
ext4_ext_map_blocks+0x520/0xdb0
ext4_map_blocks+0x2b0/0x690
ext4_iomap_begin+0x20e/0x2c0
[...]
==================================================================
Therefore, *orig_path is updated when the extent lookup succeeds, so that
the caller can safely use path or *ppath.
Fixes: 10809df84a4d ("ext4: teach ext4_ext_find_extent() to realloc path if necessary")
Cc: stable@kernel.org
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
fs/ext4/extents.c | 3 ++-
fs/ext4/move_extent.c | 1 -
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 0224cf0ef19e..5879aef159d8 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -957,6 +957,8 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
ext4_ext_show_path(inode, path);
+ if (orig_path)
+ *orig_path = path;
return path;
err:
@@ -3268,7 +3270,6 @@ static int ext4_split_extent_at(handle_t *handle,
}
depth = ext_depth(inode);
ex = path[depth].p_ext;
- *ppath = path;
if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 204f53b23622..c95e3e526390 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -36,7 +36,6 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
*ppath = NULL;
return -ENODATA;
}
- *ppath = path;
return 0;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 06/25] ext4: aovid use-after-free in ext4_ext_insert_extent()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (4 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 05/25] ext4: update orig_path in ext4_find_extent() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-27 18:07 ` Jan Kara
2024-08-22 2:35 ` [PATCH v2 07/25] ext4: drop ppath from ext4_ext_replay_update_ex() to avoid double-free libaokun
` (19 subsequent siblings)
25 siblings, 1 reply; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li, stable
From: Baokun Li <libaokun1@huawei.com>
As Ojaswin mentioned in Link, in ext4_ext_insert_extent(), if the path is
reallocated in ext4_ext_create_new_leaf(), we'll use the stale path and
cause UAF. Below is a sample trace with dummy values:
ext4_ext_insert_extent
path = *ppath = 2000
ext4_ext_create_new_leaf(ppath)
ext4_find_extent(ppath)
path = *ppath = 2000
if (depth > path[0].p_maxdepth)
kfree(path = 2000);
*ppath = path = NULL;
path = kcalloc() = 3000
*ppath = 3000;
return path;
/* here path is still 2000, UAF! */
eh = path[depth].p_hdr
==================================================================
BUG: KASAN: slab-use-after-free in ext4_ext_insert_extent+0x26d4/0x3330
Read of size 8 at addr ffff8881027bf7d0 by task kworker/u36:1/179
CPU: 3 UID: 0 PID: 179 Comm: kworker/u6:1 Not tainted 6.11.0-rc2-dirty #866
Call Trace:
<TASK>
ext4_ext_insert_extent+0x26d4/0x3330
ext4_ext_map_blocks+0xe22/0x2d40
ext4_map_blocks+0x71e/0x1700
ext4_do_writepages+0x1290/0x2800
[...]
Allocated by task 179:
ext4_find_extent+0x81c/0x1f70
ext4_ext_map_blocks+0x146/0x2d40
ext4_map_blocks+0x71e/0x1700
ext4_do_writepages+0x1290/0x2800
ext4_writepages+0x26d/0x4e0
do_writepages+0x175/0x700
[...]
Freed by task 179:
kfree+0xcb/0x240
ext4_find_extent+0x7c0/0x1f70
ext4_ext_insert_extent+0xa26/0x3330
ext4_ext_map_blocks+0xe22/0x2d40
ext4_map_blocks+0x71e/0x1700
ext4_do_writepages+0x1290/0x2800
ext4_writepages+0x26d/0x4e0
do_writepages+0x175/0x700
[...]
==================================================================
So use *ppath to update the path to avoid the above problem.
Reported-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Closes: https://lore.kernel.org/r/ZqyL6rmtwl6N4MWR@li-bb2b2a4c-3307-11b2-a85c-8fa5c3a69313.ibm.com
Fixes: 10809df84a4d ("ext4: teach ext4_ext_find_extent() to realloc path if necessary")
Cc: stable@kernel.org
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
fs/ext4/extents.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 5879aef159d8..91c6586afcca 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2116,6 +2116,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
ppath, newext);
if (err)
goto cleanup;
+ path = *ppath;
depth = ext_depth(inode);
eh = path[depth].p_hdr;
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 07/25] ext4: drop ppath from ext4_ext_replay_update_ex() to avoid double-free
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (5 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 06/25] ext4: aovid use-after-free in ext4_ext_insert_extent() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 08/25] ext4: fix double brelse() the buffer of the extents path libaokun
` (18 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li, stable
From: Baokun Li <libaokun1@huawei.com>
When calling ext4_force_split_extent_at() in ext4_ext_replay_update_ex(),
the 'ppath' is updated but it is the 'path' that is freed, thus potentially
triggering a double-free in the following process:
ext4_ext_replay_update_ex
ppath = path
ext4_force_split_extent_at(&ppath)
ext4_split_extent_at
ext4_ext_insert_extent
ext4_ext_create_new_leaf
ext4_ext_grow_indepth
ext4_find_extent
if (depth > path[0].p_maxdepth)
kfree(path) ---> path First freed
*orig_path = path = NULL ---> null ppath
kfree(path) ---> path double-free !!!
So drop the unnecessary ppath and use path directly to avoid this problem.
And use ext4_find_extent() directly to update path, avoiding unnecessary
memory allocation and freeing. Also, propagate the error returned by
ext4_find_extent() instead of using strange error codes.
Fixes: 8016e29f4362 ("ext4: fast commit recovery path")
Cc: stable@kernel.org
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 91c6586afcca..cd2e71123a25 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -5921,7 +5921,7 @@ int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu)
int ext4_ext_replay_update_ex(struct inode *inode, ext4_lblk_t start,
int len, int unwritten, ext4_fsblk_t pblk)
{
- struct ext4_ext_path *path = NULL, *ppath;
+ struct ext4_ext_path *path;
struct ext4_extent *ex;
int ret;
@@ -5937,30 +5937,29 @@ int ext4_ext_replay_update_ex(struct inode *inode, ext4_lblk_t start,
if (le32_to_cpu(ex->ee_block) != start ||
ext4_ext_get_actual_len(ex) != len) {
/* We need to split this extent to match our extent first */
- ppath = path;
down_write(&EXT4_I(inode)->i_data_sem);
- ret = ext4_force_split_extent_at(NULL, inode, &ppath, start, 1);
+ ret = ext4_force_split_extent_at(NULL, inode, &path, start, 1);
up_write(&EXT4_I(inode)->i_data_sem);
if (ret)
goto out;
- kfree(path);
- path = ext4_find_extent(inode, start, NULL, 0);
+
+ path = ext4_find_extent(inode, start, &path, 0);
if (IS_ERR(path))
- return -1;
- ppath = path;
+ return PTR_ERR(path);
ex = path[path->p_depth].p_ext;
WARN_ON(le32_to_cpu(ex->ee_block) != start);
+
if (ext4_ext_get_actual_len(ex) != len) {
down_write(&EXT4_I(inode)->i_data_sem);
- ret = ext4_force_split_extent_at(NULL, inode, &ppath,
+ ret = ext4_force_split_extent_at(NULL, inode, &path,
start + len, 1);
up_write(&EXT4_I(inode)->i_data_sem);
if (ret)
goto out;
- kfree(path);
- path = ext4_find_extent(inode, start, NULL, 0);
+
+ path = ext4_find_extent(inode, start, &path, 0);
if (IS_ERR(path))
- return -EINVAL;
+ return PTR_ERR(path);
ex = path[path->p_depth].p_ext;
}
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 08/25] ext4: fix double brelse() the buffer of the extents path
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (6 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 07/25] ext4: drop ppath from ext4_ext_replay_update_ex() to avoid double-free libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 09/25] ext4: add new ext4_ext_path_brelse() helper libaokun
` (17 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li, stable
From: Baokun Li <libaokun1@huawei.com>
In ext4_ext_try_to_merge_up(), set path[1].p_bh to NULL after it has been
released, otherwise it may be released twice. An example of what triggers
this is as follows:
split2 map split1
|--------|-------|--------|
ext4_ext_map_blocks
ext4_ext_handle_unwritten_extents
ext4_split_convert_extents
// path->p_depth == 0
ext4_split_extent
// 1. do split1
ext4_split_extent_at
|ext4_ext_insert_extent
| ext4_ext_create_new_leaf
| ext4_ext_grow_indepth
| le16_add_cpu(&neh->eh_depth, 1)
| ext4_find_extent
| // return -ENOMEM
|// get error and try zeroout
|path = ext4_find_extent
| path->p_depth = 1
|ext4_ext_try_to_merge
| ext4_ext_try_to_merge_up
| path->p_depth = 0
| brelse(path[1].p_bh) ---> not set to NULL here
|// zeroout success
// 2. update path
ext4_find_extent
// 3. do split2
ext4_split_extent_at
ext4_ext_insert_extent
ext4_ext_create_new_leaf
ext4_ext_grow_indepth
le16_add_cpu(&neh->eh_depth, 1)
ext4_find_extent
path[0].p_bh = NULL;
path->p_depth = 1
read_extent_tree_block ---> return err
// path[1].p_bh is still the old value
ext4_free_ext_path
ext4_ext_drop_refs
// path->p_depth == 1
brelse(path[1].p_bh) ---> brelse a buffer twice
Finally got the following WARRNING when removing the buffer from lru:
============================================
VFS: brelse: Trying to free free buffer
WARNING: CPU: 2 PID: 72 at fs/buffer.c:1241 __brelse+0x58/0x90
CPU: 2 PID: 72 Comm: kworker/u19:1 Not tainted 6.9.0-dirty #716
RIP: 0010:__brelse+0x58/0x90
Call Trace:
<TASK>
__find_get_block+0x6e7/0x810
bdev_getblk+0x2b/0x480
__ext4_get_inode_loc+0x48a/0x1240
ext4_get_inode_loc+0xb2/0x150
ext4_reserve_inode_write+0xb7/0x230
__ext4_mark_inode_dirty+0x144/0x6a0
ext4_ext_insert_extent+0x9c8/0x3230
ext4_ext_map_blocks+0xf45/0x2dc0
ext4_map_blocks+0x724/0x1700
ext4_do_writepages+0x12d6/0x2a70
[...]
============================================
Fixes: ecb94f5fdf4b ("ext4: collapse a single extent tree block into the inode if possible")
Cc: stable@kernel.org
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index cd2e71123a25..c4a4573440c1 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1890,6 +1890,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle,
path[0].p_hdr->eh_max = cpu_to_le16(max_root);
brelse(path[1].p_bh);
+ path[1].p_bh = NULL;
ext4_free_blocks(handle, inode, NULL, blk, 1,
EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 09/25] ext4: add new ext4_ext_path_brelse() helper
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (7 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 08/25] ext4: fix double brelse() the buffer of the extents path libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 10/25] ext4: propagate errors from ext4_find_extent() in ext4_insert_range() libaokun
` (16 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
Add ext4_ext_path_brelse() helper function to reduce duplicate code
and ensure that path->p_bh is set to NULL after it is released.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index c4a4573440c1..5e760d1a0eff 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -106,6 +106,12 @@ static int ext4_ext_trunc_restart_fn(struct inode *inode, int *dropped)
return 0;
}
+static inline void ext4_ext_path_brelse(struct ext4_ext_path *path)
+{
+ brelse(path->p_bh);
+ path->p_bh = NULL;
+}
+
static void ext4_ext_drop_refs(struct ext4_ext_path *path)
{
int depth, i;
@@ -113,10 +119,8 @@ static void ext4_ext_drop_refs(struct ext4_ext_path *path)
if (!path)
return;
depth = path->p_depth;
- for (i = 0; i <= depth; i++, path++) {
- brelse(path->p_bh);
- path->p_bh = NULL;
- }
+ for (i = 0; i <= depth; i++, path++)
+ ext4_ext_path_brelse(path);
}
void ext4_free_ext_path(struct ext4_ext_path *path)
@@ -635,8 +639,7 @@ int ext4_ext_precache(struct inode *inode)
*/
if ((i == depth) ||
path[i].p_idx > EXT_LAST_INDEX(path[i].p_hdr)) {
- brelse(path[i].p_bh);
- path[i].p_bh = NULL;
+ ext4_ext_path_brelse(path + i);
i--;
continue;
}
@@ -1889,8 +1892,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle,
(path[1].p_ext - EXT_FIRST_EXTENT(path[1].p_hdr));
path[0].p_hdr->eh_max = cpu_to_le16(max_root);
- brelse(path[1].p_bh);
- path[1].p_bh = NULL;
+ ext4_ext_path_brelse(path + 1);
ext4_free_blocks(handle, inode, NULL, blk, 1,
EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
}
@@ -2959,8 +2961,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
err = ext4_ext_rm_leaf(handle, inode, path,
&partial, start, end);
/* root level has p_bh == NULL, brelse() eats this */
- brelse(path[i].p_bh);
- path[i].p_bh = NULL;
+ ext4_ext_path_brelse(path + i);
i--;
continue;
}
@@ -3022,8 +3023,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
err = ext4_ext_rm_idx(handle, inode, path, i);
}
/* root level has p_bh == NULL, brelse() eats this */
- brelse(path[i].p_bh);
- path[i].p_bh = NULL;
+ ext4_ext_path_brelse(path + i);
i--;
ext_debug(inode, "return to level %d\n", i);
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 10/25] ext4: propagate errors from ext4_find_extent() in ext4_insert_range()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (8 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 09/25] ext4: add new ext4_ext_path_brelse() helper libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 11/25] ext4: get rid of ppath in ext4_find_extent() libaokun
` (15 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li, stable
From: Baokun Li <libaokun1@huawei.com>
Even though ext4_find_extent() returns an error, ext4_insert_range() still
returns 0. This may confuse the user as to why fallocate returns success,
but the contents of the file are not as expected. So propagate the error
returned by ext4_find_extent() to avoid inconsistencies.
Fixes: 331573febb6a ("ext4: Add support FALLOC_FL_INSERT_RANGE for fallocate")
Cc: stable@kernel.org
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 5e760d1a0eff..1c1c7c39ceaa 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -5577,6 +5577,7 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
path = ext4_find_extent(inode, offset_lblk, NULL, 0);
if (IS_ERR(path)) {
up_write(&EXT4_I(inode)->i_data_sem);
+ ret = PTR_ERR(path);
goto out_stop;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 11/25] ext4: get rid of ppath in ext4_find_extent()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (9 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 10/25] ext4: propagate errors from ext4_find_extent() in ext4_insert_range() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 12/25] ext4: get rid of ppath in get_ext_path() libaokun
` (14 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
Getting rid of ppath in ext4_find_extent() requires its caller to update
ppath. These ppaths will also be dropped later. No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/ext4.h | 2 +-
fs/ext4/extents.c | 55 +++++++++++++++++++++++--------------------
fs/ext4/move_extent.c | 7 +++---
3 files changed, 34 insertions(+), 30 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index c3429b664b8d..ad3c7532fa72 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3714,7 +3714,7 @@ extern int ext4_ext_insert_extent(handle_t *, struct inode *,
struct ext4_ext_path **,
struct ext4_extent *, int);
extern struct ext4_ext_path *ext4_find_extent(struct inode *, ext4_lblk_t,
- struct ext4_ext_path **,
+ struct ext4_ext_path *,
int flags);
extern void ext4_free_ext_path(struct ext4_ext_path *);
extern int ext4_ext_check_inode(struct inode *inode);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 1c1c7c39ceaa..32d2f9c86ab2 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -884,11 +884,10 @@ void ext4_ext_tree_init(handle_t *handle, struct inode *inode)
struct ext4_ext_path *
ext4_find_extent(struct inode *inode, ext4_lblk_t block,
- struct ext4_ext_path **orig_path, int flags)
+ struct ext4_ext_path *path, int flags)
{
struct ext4_extent_header *eh;
struct buffer_head *bh;
- struct ext4_ext_path *path = orig_path ? *orig_path : NULL;
short int depth, i, ppos = 0;
int ret;
gfp_t gfp_flags = GFP_NOFS;
@@ -909,7 +908,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
ext4_ext_drop_refs(path);
if (depth > path[0].p_maxdepth) {
kfree(path);
- *orig_path = path = NULL;
+ path = NULL;
}
}
if (!path) {
@@ -960,14 +959,10 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
ext4_ext_show_path(inode, path);
- if (orig_path)
- *orig_path = path;
return path;
err:
ext4_free_ext_path(path);
- if (orig_path)
- *orig_path = NULL;
return ERR_PTR(ret);
}
@@ -1432,7 +1427,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
/* refill path */
path = ext4_find_extent(inode,
(ext4_lblk_t)le32_to_cpu(newext->ee_block),
- ppath, gb_flags);
+ path, gb_flags);
if (IS_ERR(path))
err = PTR_ERR(path);
} else {
@@ -1444,7 +1439,7 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
/* refill path */
path = ext4_find_extent(inode,
(ext4_lblk_t)le32_to_cpu(newext->ee_block),
- ppath, gb_flags);
+ path, gb_flags);
if (IS_ERR(path)) {
err = PTR_ERR(path);
goto out;
@@ -1460,8 +1455,8 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
goto repeat;
}
}
-
out:
+ *ppath = IS_ERR(path) ? NULL : path;
return err;
}
@@ -3263,15 +3258,17 @@ static int ext4_split_extent_at(handle_t *handle,
* WARN_ON may be triggered in ext4_da_update_reserve_space() due to
* an incorrect ee_len causing the i_reserved_data_blocks exception.
*/
- path = ext4_find_extent(inode, ee_block, ppath,
+ path = ext4_find_extent(inode, ee_block, *ppath,
flags | EXT4_EX_NOFAIL);
if (IS_ERR(path)) {
EXT4_ERROR_INODE(inode, "Failed split extent on %u, err %ld",
split, PTR_ERR(path));
+ *ppath = NULL;
return PTR_ERR(path);
}
depth = ext_depth(inode);
ex = path[depth].p_ext;
+ *ppath = path;
if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
@@ -3381,9 +3378,12 @@ static int ext4_split_extent(handle_t *handle,
* Update path is required because previous ext4_split_extent_at() may
* result in split of original leaf or extent zeroout.
*/
- path = ext4_find_extent(inode, map->m_lblk, ppath, flags);
- if (IS_ERR(path))
+ path = ext4_find_extent(inode, map->m_lblk, *ppath, flags);
+ if (IS_ERR(path)) {
+ *ppath = NULL;
return PTR_ERR(path);
+ }
+ *ppath = path;
depth = ext_depth(inode);
ex = path[depth].p_ext;
if (!ex) {
@@ -3769,9 +3769,12 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
EXT4_GET_BLOCKS_CONVERT);
if (err < 0)
return err;
- path = ext4_find_extent(inode, map->m_lblk, ppath, 0);
- if (IS_ERR(path))
+ path = ext4_find_extent(inode, map->m_lblk, *ppath, 0);
+ if (IS_ERR(path)) {
+ *ppath = NULL;
return PTR_ERR(path);
+ }
+ *ppath = path;
depth = ext_depth(inode);
ex = path[depth].p_ext;
}
@@ -3827,9 +3830,12 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
if (err < 0)
return err;
- path = ext4_find_extent(inode, map->m_lblk, ppath, 0);
- if (IS_ERR(path))
+ path = ext4_find_extent(inode, map->m_lblk, *ppath, 0);
+ if (IS_ERR(path)) {
+ *ppath = NULL;
return PTR_ERR(path);
+ }
+ *ppath = path;
depth = ext_depth(inode);
ex = path[depth].p_ext;
if (!ex) {
@@ -5226,7 +5232,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
* won't be shifted beyond EXT_MAX_BLOCKS.
*/
if (SHIFT == SHIFT_LEFT) {
- path = ext4_find_extent(inode, start - 1, &path,
+ path = ext4_find_extent(inode, start - 1, path,
EXT4_EX_NOCACHE);
if (IS_ERR(path))
return PTR_ERR(path);
@@ -5275,7 +5281,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
* becomes NULL to indicate the end of the loop.
*/
while (iterator && start <= stop) {
- path = ext4_find_extent(inode, *iterator, &path,
+ path = ext4_find_extent(inode, *iterator, path,
EXT4_EX_NOCACHE);
if (IS_ERR(path))
return PTR_ERR(path);
@@ -5857,11 +5863,8 @@ int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu)
/* search for the extent closest to the first block in the cluster */
path = ext4_find_extent(inode, EXT4_C2B(sbi, lclu), NULL, 0);
- if (IS_ERR(path)) {
- err = PTR_ERR(path);
- path = NULL;
- goto out;
- }
+ if (IS_ERR(path))
+ return PTR_ERR(path);
depth = ext_depth(inode);
@@ -5945,7 +5948,7 @@ int ext4_ext_replay_update_ex(struct inode *inode, ext4_lblk_t start,
if (ret)
goto out;
- path = ext4_find_extent(inode, start, &path, 0);
+ path = ext4_find_extent(inode, start, path, 0);
if (IS_ERR(path))
return PTR_ERR(path);
ex = path[path->p_depth].p_ext;
@@ -5959,7 +5962,7 @@ int ext4_ext_replay_update_ex(struct inode *inode, ext4_lblk_t start,
if (ret)
goto out;
- path = ext4_find_extent(inode, start, &path, 0);
+ path = ext4_find_extent(inode, start, path, 0);
if (IS_ERR(path))
return PTR_ERR(path);
ex = path[path->p_depth].p_ext;
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index c95e3e526390..b0ab19a913bf 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -26,16 +26,17 @@ static inline int
get_ext_path(struct inode *inode, ext4_lblk_t lblock,
struct ext4_ext_path **ppath)
{
- struct ext4_ext_path *path;
+ struct ext4_ext_path *path = *ppath;
- path = ext4_find_extent(inode, lblock, ppath, EXT4_EX_NOCACHE);
+ *ppath = NULL;
+ path = ext4_find_extent(inode, lblock, path, EXT4_EX_NOCACHE);
if (IS_ERR(path))
return PTR_ERR(path);
if (path[ext_depth(inode)].p_ext == NULL) {
ext4_free_ext_path(path);
- *ppath = NULL;
return -ENODATA;
}
+ *ppath = path;
return 0;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 12/25] ext4: get rid of ppath in get_ext_path()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (10 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 11/25] ext4: get rid of ppath in ext4_find_extent() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 13/25] ext4: get rid of ppath in ext4_ext_create_new_leaf() libaokun
` (13 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
After getting rid of ppath in get_ext_path(), its caller may pass an error
pointer to ext4_free_ext_path(), so it needs to teach ext4_free_ext_path()
and ext4_ext_drop_refs() to skip the error pointer. No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 5 +++--
fs/ext4/move_extent.c | 34 +++++++++++++++++-----------------
2 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 32d2f9c86ab2..adedf2d1e67e 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -116,7 +116,7 @@ static void ext4_ext_drop_refs(struct ext4_ext_path *path)
{
int depth, i;
- if (!path)
+ if (IS_ERR_OR_NULL(path))
return;
depth = path->p_depth;
for (i = 0; i <= depth; i++, path++)
@@ -125,6 +125,8 @@ static void ext4_ext_drop_refs(struct ext4_ext_path *path)
void ext4_free_ext_path(struct ext4_ext_path *path)
{
+ if (IS_ERR_OR_NULL(path))
+ return;
ext4_ext_drop_refs(path);
kfree(path);
}
@@ -4192,7 +4194,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
path = ext4_find_extent(inode, map->m_lblk, NULL, 0);
if (IS_ERR(path)) {
err = PTR_ERR(path);
- path = NULL;
goto out;
}
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index b0ab19a913bf..a7186d63725a 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -17,27 +17,23 @@
* get_ext_path() - Find an extent path for designated logical block number.
* @inode: inode to be searched
* @lblock: logical block number to find an extent path
- * @ppath: pointer to an extent path pointer (for output)
+ * @path: pointer to an extent path
*
- * ext4_find_extent wrapper. Return 0 on success, or a negative error value
- * on failure.
+ * ext4_find_extent wrapper. Return an extent path pointer on success,
+ * or an error pointer on failure.
*/
-static inline int
+static inline struct ext4_ext_path *
get_ext_path(struct inode *inode, ext4_lblk_t lblock,
- struct ext4_ext_path **ppath)
+ struct ext4_ext_path *path)
{
- struct ext4_ext_path *path = *ppath;
-
- *ppath = NULL;
path = ext4_find_extent(inode, lblock, path, EXT4_EX_NOCACHE);
if (IS_ERR(path))
- return PTR_ERR(path);
+ return path;
if (path[ext_depth(inode)].p_ext == NULL) {
ext4_free_ext_path(path);
- return -ENODATA;
+ return ERR_PTR(-ENODATA);
}
- *ppath = path;
- return 0;
+ return path;
}
/**
@@ -95,9 +91,11 @@ mext_check_coverage(struct inode *inode, ext4_lblk_t from, ext4_lblk_t count,
int ret = 0;
ext4_lblk_t last = from + count;
while (from < last) {
- *err = get_ext_path(inode, from, &path);
- if (*err)
- goto out;
+ path = get_ext_path(inode, from, path);
+ if (IS_ERR(path)) {
+ *err = PTR_ERR(path);
+ return ret;
+ }
ext = path[ext_depth(inode)].p_ext;
if (unwritten != ext4_ext_is_unwritten(ext))
goto out;
@@ -624,9 +622,11 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
int offset_in_page;
int unwritten, cur_len;
- ret = get_ext_path(orig_inode, o_start, &path);
- if (ret)
+ path = get_ext_path(orig_inode, o_start, path);
+ if (IS_ERR(path)) {
+ ret = PTR_ERR(path);
goto out;
+ }
ex = path[path->p_depth].p_ext;
cur_blk = le32_to_cpu(ex->ee_block);
cur_len = ext4_ext_get_actual_len(ex);
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 13/25] ext4: get rid of ppath in ext4_ext_create_new_leaf()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (11 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 12/25] ext4: get rid of ppath in get_ext_path() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 14/25] ext4: get rid of ppath in ext4_ext_insert_extent() libaokun
` (12 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in ext4_ext_create_new_leaf(), the following is
done here:
* Free the extents path when an error is encountered.
* Its caller needs to update ppath if it uses ppath.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 43 ++++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index adedf2d1e67e..a11a5144fd96 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1397,13 +1397,12 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
* finds empty index and adds new leaf.
* if no free index is found, then it requests in-depth growing.
*/
-static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
- unsigned int mb_flags,
- unsigned int gb_flags,
- struct ext4_ext_path **ppath,
- struct ext4_extent *newext)
+static struct ext4_ext_path *
+ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
+ unsigned int mb_flags, unsigned int gb_flags,
+ struct ext4_ext_path *path,
+ struct ext4_extent *newext)
{
- struct ext4_ext_path *path = *ppath;
struct ext4_ext_path *curp;
int depth, i, err = 0;
@@ -1424,28 +1423,25 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
* entry: create all needed subtree and add new leaf */
err = ext4_ext_split(handle, inode, mb_flags, path, newext, i);
if (err)
- goto out;
+ goto errout;
/* refill path */
path = ext4_find_extent(inode,
(ext4_lblk_t)le32_to_cpu(newext->ee_block),
path, gb_flags);
- if (IS_ERR(path))
- err = PTR_ERR(path);
+ return path;
} else {
/* tree is full, time to grow in depth */
err = ext4_ext_grow_indepth(handle, inode, mb_flags);
if (err)
- goto out;
+ goto errout;
/* refill path */
path = ext4_find_extent(inode,
(ext4_lblk_t)le32_to_cpu(newext->ee_block),
path, gb_flags);
- if (IS_ERR(path)) {
- err = PTR_ERR(path);
- goto out;
- }
+ if (IS_ERR(path))
+ return path;
/*
* only first (depth 0 -> 1) produces free space;
@@ -1457,9 +1453,11 @@ static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
goto repeat;
}
}
-out:
- *ppath = IS_ERR(path) ? NULL : path;
- return err;
+ return path;
+
+errout:
+ ext4_free_ext_path(path);
+ return ERR_PTR(err);
}
/*
@@ -2112,11 +2110,14 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
*/
if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
mb_flags |= EXT4_MB_USE_RESERVED;
- err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
- ppath, newext);
- if (err)
+ path = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
+ path, newext);
+ if (IS_ERR(path)) {
+ *ppath = NULL;
+ err = PTR_ERR(path);
goto cleanup;
- path = *ppath;
+ }
+ *ppath = path;
depth = ext_depth(inode);
eh = path[depth].p_hdr;
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 14/25] ext4: get rid of ppath in ext4_ext_insert_extent()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (12 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 13/25] ext4: get rid of ppath in ext4_ext_create_new_leaf() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 15/25] ext4: get rid of ppath in ext4_split_extent_at() libaokun
` (11 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in ext4_ext_insert_extent(), the following is done
here:
* Free the extents path when an error is encountered.
* Its caller needs to update ppath if it uses ppath.
* Free path when npath is used, free npath when it is not used.
* The got_allocated_blocks label in ext4_ext_map_blocks() does not
update err now, so err is updated to 0 if the err returned by
ext4_ext_search_right() is greater than 0 and is about to enter
got_allocated_blocks.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/ext4.h | 7 ++--
fs/ext4/extents.c | 88 ++++++++++++++++++++++++-------------------
fs/ext4/fast_commit.c | 8 ++--
fs/ext4/migrate.c | 5 ++-
4 files changed, 61 insertions(+), 47 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index ad3c7532fa72..c51584bc3f8c 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3710,9 +3710,10 @@ extern int ext4_map_blocks(handle_t *handle, struct inode *inode,
extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
int num,
struct ext4_ext_path *path);
-extern int ext4_ext_insert_extent(handle_t *, struct inode *,
- struct ext4_ext_path **,
- struct ext4_extent *, int);
+extern struct ext4_ext_path *ext4_ext_insert_extent(
+ handle_t *handle, struct inode *inode,
+ struct ext4_ext_path *path,
+ struct ext4_extent *newext, int gb_flags);
extern struct ext4_ext_path *ext4_find_extent(struct inode *, ext4_lblk_t,
struct ext4_ext_path *,
int flags);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index a11a5144fd96..2d435062c1d3 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1975,16 +1975,15 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
* inserts requested extent as new one into the tree,
* creating new leaf in the no-space case.
*/
-int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
- struct ext4_ext_path **ppath,
- struct ext4_extent *newext, int gb_flags)
+struct ext4_ext_path *
+ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+ struct ext4_ext_path *path,
+ struct ext4_extent *newext, int gb_flags)
{
- struct ext4_ext_path *path = *ppath;
struct ext4_extent_header *eh;
struct ext4_extent *ex, *fex;
struct ext4_extent *nearex; /* nearest extent */
- struct ext4_ext_path *npath = NULL;
- int depth, len, err;
+ int depth, len, err = 0;
ext4_lblk_t next;
int mb_flags = 0, unwritten;
@@ -1992,14 +1991,16 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
mb_flags |= EXT4_MB_DELALLOC_RESERVED;
if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
- return -EFSCORRUPTED;
+ err = -EFSCORRUPTED;
+ goto errout;
}
depth = ext_depth(inode);
ex = path[depth].p_ext;
eh = path[depth].p_hdr;
if (unlikely(path[depth].p_hdr == NULL)) {
EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
- return -EFSCORRUPTED;
+ err = -EFSCORRUPTED;
+ goto errout;
}
/* try to insert block into found extent and return */
@@ -2037,7 +2038,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
err = ext4_ext_get_access(handle, inode,
path + depth);
if (err)
- return err;
+ goto errout;
unwritten = ext4_ext_is_unwritten(ex);
ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)
+ ext4_ext_get_actual_len(newext));
@@ -2062,7 +2063,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
err = ext4_ext_get_access(handle, inode,
path + depth);
if (err)
- return err;
+ goto errout;
unwritten = ext4_ext_is_unwritten(ex);
ex->ee_block = newext->ee_block;
@@ -2087,21 +2088,26 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block))
next = ext4_ext_next_leaf_block(path);
if (next != EXT_MAX_BLOCKS) {
+ struct ext4_ext_path *npath;
+
ext_debug(inode, "next leaf block - %u\n", next);
- BUG_ON(npath != NULL);
npath = ext4_find_extent(inode, next, NULL, gb_flags);
- if (IS_ERR(npath))
- return PTR_ERR(npath);
+ if (IS_ERR(npath)) {
+ err = PTR_ERR(npath);
+ goto errout;
+ }
BUG_ON(npath->p_depth != path->p_depth);
eh = npath[depth].p_hdr;
if (le16_to_cpu(eh->eh_entries) < le16_to_cpu(eh->eh_max)) {
ext_debug(inode, "next leaf isn't full(%d)\n",
le16_to_cpu(eh->eh_entries));
+ ext4_free_ext_path(path);
path = npath;
goto has_space;
}
ext_debug(inode, "next leaf has no free space(%d,%d)\n",
le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max));
+ ext4_free_ext_path(npath);
}
/*
@@ -2112,12 +2118,8 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
mb_flags |= EXT4_MB_USE_RESERVED;
path = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
path, newext);
- if (IS_ERR(path)) {
- *ppath = NULL;
- err = PTR_ERR(path);
- goto cleanup;
- }
- *ppath = path;
+ if (IS_ERR(path))
+ return path;
depth = ext_depth(inode);
eh = path[depth].p_hdr;
@@ -2126,7 +2128,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
err = ext4_ext_get_access(handle, inode, path + depth);
if (err)
- goto cleanup;
+ goto errout;
if (!nearex) {
/* there is no extent in this leaf, create first one */
@@ -2184,17 +2186,20 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
ext4_ext_try_to_merge(handle, inode, path, nearex);
-
/* time to correct all indexes above */
err = ext4_ext_correct_indexes(handle, inode, path);
if (err)
- goto cleanup;
+ goto errout;
err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+ if (err)
+ goto errout;
-cleanup:
- ext4_free_ext_path(npath);
- return err;
+ return path;
+
+errout:
+ ext4_free_ext_path(path);
+ return ERR_PTR(err);
}
static int ext4_fill_es_cache_info(struct inode *inode,
@@ -3249,24 +3254,29 @@ static int ext4_split_extent_at(handle_t *handle,
if (split_flag & EXT4_EXT_MARK_UNWRIT2)
ext4_ext_mark_unwritten(ex2);
- err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags);
- if (err != -ENOSPC && err != -EDQUOT && err != -ENOMEM)
+ path = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
+ if (!IS_ERR(path)) {
+ *ppath = path;
goto out;
+ }
+ *ppath = NULL;
+ err = PTR_ERR(path);
+ if (err != -ENOSPC && err != -EDQUOT && err != -ENOMEM)
+ return err;
/*
- * Update path is required because previous ext4_ext_insert_extent()
- * may have freed or reallocated the path. Using EXT4_EX_NOFAIL
- * guarantees that ext4_find_extent() will not return -ENOMEM,
- * otherwise -ENOMEM will cause a retry in do_writepages(), and a
- * WARN_ON may be triggered in ext4_da_update_reserve_space() due to
- * an incorrect ee_len causing the i_reserved_data_blocks exception.
+ * Get a new path to try to zeroout or fix the extent length.
+ * Using EXT4_EX_NOFAIL guarantees that ext4_find_extent()
+ * will not return -ENOMEM, otherwise -ENOMEM will cause a
+ * retry in do_writepages(), and a WARN_ON may be triggered
+ * in ext4_da_update_reserve_space() due to an incorrect
+ * ee_len causing the i_reserved_data_blocks exception.
*/
- path = ext4_find_extent(inode, ee_block, *ppath,
+ path = ext4_find_extent(inode, ee_block, NULL,
flags | EXT4_EX_NOFAIL);
if (IS_ERR(path)) {
EXT4_ERROR_INODE(inode, "Failed split extent on %u, err %ld",
split, PTR_ERR(path));
- *ppath = NULL;
return PTR_ERR(path);
}
depth = ext_depth(inode);
@@ -3325,7 +3335,7 @@ static int ext4_split_extent_at(handle_t *handle,
ext4_ext_dirty(handle, inode, path + path->p_depth);
return err;
out:
- ext4_ext_show_leaf(inode, *ppath);
+ ext4_ext_show_leaf(inode, path);
return err;
}
@@ -4314,6 +4324,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
get_implied_cluster_alloc(inode->i_sb, map, &ex2, path)) {
ar.len = allocated = map->m_len;
newblock = map->m_pblk;
+ err = 0;
goto got_allocated_blocks;
}
@@ -4386,8 +4397,9 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
map->m_flags |= EXT4_MAP_UNWRITTEN;
}
- err = ext4_ext_insert_extent(handle, inode, &path, &newex, flags);
- if (err) {
+ path = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
+ if (IS_ERR(path)) {
+ err = PTR_ERR(path);
if (allocated_clusters) {
int fb_flags = 0;
diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index 3926a05eceee..52e42cb02f39 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -1783,12 +1783,12 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
if (ext4_ext_is_unwritten(ex))
ext4_ext_mark_unwritten(&newex);
down_write(&EXT4_I(inode)->i_data_sem);
- ret = ext4_ext_insert_extent(
- NULL, inode, &path, &newex, 0);
+ path = ext4_ext_insert_extent(NULL, inode,
+ path, &newex, 0);
up_write((&EXT4_I(inode)->i_data_sem));
- ext4_free_ext_path(path);
- if (ret)
+ if (IS_ERR(path))
goto out;
+ ext4_free_ext_path(path);
goto next;
}
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index d98ac2af8199..0f68b8a14560 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -37,7 +37,6 @@ static int finish_range(handle_t *handle, struct inode *inode,
path = ext4_find_extent(inode, lb->first_block, NULL, 0);
if (IS_ERR(path)) {
retval = PTR_ERR(path);
- path = NULL;
goto err_out;
}
@@ -53,7 +52,9 @@ static int finish_range(handle_t *handle, struct inode *inode,
retval = ext4_datasem_ensure_credits(handle, inode, needed, needed, 0);
if (retval < 0)
goto err_out;
- retval = ext4_ext_insert_extent(handle, inode, &path, &newext, 0);
+ path = ext4_ext_insert_extent(handle, inode, path, &newext, 0);
+ if (IS_ERR(path))
+ retval = PTR_ERR(path);
err_out:
up_write((&EXT4_I(inode)->i_data_sem));
ext4_free_ext_path(path);
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 15/25] ext4: get rid of ppath in ext4_split_extent_at()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (13 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 14/25] ext4: get rid of ppath in ext4_ext_insert_extent() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 16/25] ext4: get rid of ppath in ext4_force_split_extent_at() libaokun
` (10 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in ext4_split_extent_at(), the following is done
here:
* Free the extents path when an error is encountered.
* Its caller needs to update ppath if it uses ppath.
* Teach ext4_ext_show_leaf() to skip error pointer.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 85 ++++++++++++++++++++++++++---------------------
1 file changed, 47 insertions(+), 38 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 2d435062c1d3..cf4ce3304780 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -84,12 +84,11 @@ static void ext4_extent_block_csum_set(struct inode *inode,
et->et_checksum = ext4_extent_block_csum(inode, eh);
}
-static int ext4_split_extent_at(handle_t *handle,
- struct inode *inode,
- struct ext4_ext_path **ppath,
- ext4_lblk_t split,
- int split_flag,
- int flags);
+static struct ext4_ext_path *ext4_split_extent_at(handle_t *handle,
+ struct inode *inode,
+ struct ext4_ext_path *path,
+ ext4_lblk_t split,
+ int split_flag, int flags);
static int ext4_ext_trunc_restart_fn(struct inode *inode, int *dropped)
{
@@ -341,9 +340,15 @@ ext4_force_split_extent_at(handle_t *handle, struct inode *inode,
if (nofail)
flags |= EXT4_GET_BLOCKS_METADATA_NOFAIL | EXT4_EX_NOFAIL;
- return ext4_split_extent_at(handle, inode, ppath, lblk, unwritten ?
+ path = ext4_split_extent_at(handle, inode, path, lblk, unwritten ?
EXT4_EXT_MARK_UNWRIT1|EXT4_EXT_MARK_UNWRIT2 : 0,
flags);
+ if (IS_ERR(path)) {
+ *ppath = NULL;
+ return PTR_ERR(path);
+ }
+ *ppath = path;
+ return 0;
}
static int
@@ -694,7 +699,7 @@ static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path)
struct ext4_extent *ex;
int i;
- if (!path)
+ if (IS_ERR_OR_NULL(path))
return;
eh = path[depth].p_hdr;
@@ -3175,16 +3180,14 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
* a> the extent are splitted into two extent.
* b> split is not needed, and just mark the extent.
*
- * return 0 on success.
+ * Return an extent path pointer on success, or an error pointer on failure.
*/
-static int ext4_split_extent_at(handle_t *handle,
- struct inode *inode,
- struct ext4_ext_path **ppath,
- ext4_lblk_t split,
- int split_flag,
- int flags)
+static struct ext4_ext_path *ext4_split_extent_at(handle_t *handle,
+ struct inode *inode,
+ struct ext4_ext_path *path,
+ ext4_lblk_t split,
+ int split_flag, int flags)
{
- struct ext4_ext_path *path = *ppath;
ext4_fsblk_t newblock;
ext4_lblk_t ee_block;
struct ext4_extent *ex, newex, orig_ex, zero_ex;
@@ -3255,14 +3258,12 @@ static int ext4_split_extent_at(handle_t *handle,
ext4_ext_mark_unwritten(ex2);
path = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
- if (!IS_ERR(path)) {
- *ppath = path;
+ if (!IS_ERR(path))
goto out;
- }
- *ppath = NULL;
+
err = PTR_ERR(path);
if (err != -ENOSPC && err != -EDQUOT && err != -ENOMEM)
- return err;
+ return path;
/*
* Get a new path to try to zeroout or fix the extent length.
@@ -3272,16 +3273,14 @@ static int ext4_split_extent_at(handle_t *handle,
* in ext4_da_update_reserve_space() due to an incorrect
* ee_len causing the i_reserved_data_blocks exception.
*/
- path = ext4_find_extent(inode, ee_block, NULL,
- flags | EXT4_EX_NOFAIL);
+ path = ext4_find_extent(inode, ee_block, NULL, flags | EXT4_EX_NOFAIL);
if (IS_ERR(path)) {
EXT4_ERROR_INODE(inode, "Failed split extent on %u, err %ld",
split, PTR_ERR(path));
- return PTR_ERR(path);
+ return path;
}
depth = ext_depth(inode);
ex = path[depth].p_ext;
- *ppath = path;
if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
@@ -3333,10 +3332,13 @@ static int ext4_split_extent_at(handle_t *handle,
* and err is a non-zero error code.
*/
ext4_ext_dirty(handle, inode, path + path->p_depth);
- return err;
out:
+ if (err) {
+ ext4_free_ext_path(path);
+ path = ERR_PTR(err);
+ }
ext4_ext_show_leaf(inode, path);
- return err;
+ return path;
}
/*
@@ -3380,10 +3382,14 @@ static int ext4_split_extent(handle_t *handle,
EXT4_EXT_MARK_UNWRIT2;
if (split_flag & EXT4_EXT_DATA_VALID2)
split_flag1 |= EXT4_EXT_DATA_VALID1;
- err = ext4_split_extent_at(handle, inode, ppath,
+ path = ext4_split_extent_at(handle, inode, path,
map->m_lblk + map->m_len, split_flag1, flags1);
- if (err)
+ if (IS_ERR(path)) {
+ err = PTR_ERR(path);
+ *ppath = NULL;
goto out;
+ }
+ *ppath = path;
} else {
allocated = ee_len - (map->m_lblk - ee_block);
}
@@ -3391,7 +3397,7 @@ static int ext4_split_extent(handle_t *handle,
* Update path is required because previous ext4_split_extent_at() may
* result in split of original leaf or extent zeroout.
*/
- path = ext4_find_extent(inode, map->m_lblk, *ppath, flags);
+ path = ext4_find_extent(inode, map->m_lblk, path, flags);
if (IS_ERR(path)) {
*ppath = NULL;
return PTR_ERR(path);
@@ -3413,13 +3419,17 @@ static int ext4_split_extent(handle_t *handle,
split_flag1 |= split_flag & (EXT4_EXT_MAY_ZEROOUT |
EXT4_EXT_MARK_UNWRIT2);
}
- err = ext4_split_extent_at(handle, inode, ppath,
+ path = ext4_split_extent_at(handle, inode, path,
map->m_lblk, split_flag1, flags);
- if (err)
+ if (IS_ERR(path)) {
+ err = PTR_ERR(path);
+ *ppath = NULL;
goto out;
+ }
+ *ppath = path;
}
- ext4_ext_show_leaf(inode, *ppath);
+ ext4_ext_show_leaf(inode, path);
out:
return err ? err : allocated;
}
@@ -5616,22 +5626,21 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
if (ext4_ext_is_unwritten(extent))
split_flag = EXT4_EXT_MARK_UNWRIT1 |
EXT4_EXT_MARK_UNWRIT2;
- ret = ext4_split_extent_at(handle, inode, &path,
+ path = ext4_split_extent_at(handle, inode, path,
offset_lblk, split_flag,
EXT4_EX_NOCACHE |
EXT4_GET_BLOCKS_PRE_IO |
EXT4_GET_BLOCKS_METADATA_NOFAIL);
}
- ext4_free_ext_path(path);
- if (ret < 0) {
+ if (IS_ERR(path)) {
up_write(&EXT4_I(inode)->i_data_sem);
+ ret = PTR_ERR(path);
goto out_stop;
}
- } else {
- ext4_free_ext_path(path);
}
+ ext4_free_ext_path(path);
ext4_es_remove_extent(inode, offset_lblk, EXT_MAX_BLOCKS - offset_lblk);
/*
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 16/25] ext4: get rid of ppath in ext4_force_split_extent_at()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (14 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 15/25] ext4: get rid of ppath in ext4_split_extent_at() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 17/25] ext4: get rid of ppath in ext4_split_extent() libaokun
` (9 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in ext4_force_split_extent_at(), the following is
done here:
* Free the extents path when an error is encountered.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 69 ++++++++++++++++++++++++++---------------------
1 file changed, 38 insertions(+), 31 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index cf4ce3304780..c64f87b53efb 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -328,27 +328,20 @@ static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
return size;
}
-static inline int
+static inline struct ext4_ext_path *
ext4_force_split_extent_at(handle_t *handle, struct inode *inode,
- struct ext4_ext_path **ppath, ext4_lblk_t lblk,
+ struct ext4_ext_path *path, ext4_lblk_t lblk,
int nofail)
{
- struct ext4_ext_path *path = *ppath;
int unwritten = ext4_ext_is_unwritten(path[path->p_depth].p_ext);
int flags = EXT4_EX_NOCACHE | EXT4_GET_BLOCKS_PRE_IO;
if (nofail)
flags |= EXT4_GET_BLOCKS_METADATA_NOFAIL | EXT4_EX_NOFAIL;
- path = ext4_split_extent_at(handle, inode, path, lblk, unwritten ?
+ return ext4_split_extent_at(handle, inode, path, lblk, unwritten ?
EXT4_EXT_MARK_UNWRIT1|EXT4_EXT_MARK_UNWRIT2 : 0,
flags);
- if (IS_ERR(path)) {
- *ppath = NULL;
- return PTR_ERR(path);
- }
- *ppath = path;
- return 0;
}
static int
@@ -2907,11 +2900,12 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
* fail removing space due to ENOSPC so try to use
* reserved block if that happens.
*/
- err = ext4_force_split_extent_at(handle, inode, &path,
- end + 1, 1);
- if (err < 0)
+ path = ext4_force_split_extent_at(handle, inode, path,
+ end + 1, 1);
+ if (IS_ERR(path)) {
+ err = PTR_ERR(path);
goto out;
-
+ }
} else if (sbi->s_cluster_ratio > 1 && end >= ex_end &&
partial.state == initial) {
/*
@@ -5764,17 +5758,21 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
/* Prepare left boundary */
if (e1_blk < lblk1) {
split = 1;
- *erp = ext4_force_split_extent_at(handle, inode1,
- &path1, lblk1, 0);
- if (unlikely(*erp))
+ path1 = ext4_force_split_extent_at(handle, inode1,
+ path1, lblk1, 0);
+ if (IS_ERR(path1)) {
+ *erp = PTR_ERR(path1);
goto finish;
+ }
}
if (e2_blk < lblk2) {
split = 1;
- *erp = ext4_force_split_extent_at(handle, inode2,
- &path2, lblk2, 0);
- if (unlikely(*erp))
+ path2 = ext4_force_split_extent_at(handle, inode2,
+ path2, lblk2, 0);
+ if (IS_ERR(path2)) {
+ *erp = PTR_ERR(path2);
goto finish;
+ }
}
/* ext4_split_extent_at() may result in leaf extent split,
* path must to be revalidated. */
@@ -5790,17 +5788,21 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
if (len != e1_len) {
split = 1;
- *erp = ext4_force_split_extent_at(handle, inode1,
- &path1, lblk1 + len, 0);
- if (unlikely(*erp))
+ path1 = ext4_force_split_extent_at(handle, inode1,
+ path1, lblk1 + len, 0);
+ if (IS_ERR(path1)) {
+ *erp = PTR_ERR(path1);
goto finish;
+ }
}
if (len != e2_len) {
split = 1;
- *erp = ext4_force_split_extent_at(handle, inode2,
- &path2, lblk2 + len, 0);
- if (*erp)
+ path2 = ext4_force_split_extent_at(handle, inode2,
+ path2, lblk2 + len, 0);
+ if (IS_ERR(path2)) {
+ *erp = PTR_ERR(path2);
goto finish;
+ }
}
/* ext4_split_extent_at() may result in leaf extent split,
* path must to be revalidated. */
@@ -5966,24 +5968,29 @@ int ext4_ext_replay_update_ex(struct inode *inode, ext4_lblk_t start,
ext4_ext_get_actual_len(ex) != len) {
/* We need to split this extent to match our extent first */
down_write(&EXT4_I(inode)->i_data_sem);
- ret = ext4_force_split_extent_at(NULL, inode, &path, start, 1);
+ path = ext4_force_split_extent_at(NULL, inode, path, start, 1);
up_write(&EXT4_I(inode)->i_data_sem);
- if (ret)
+ if (IS_ERR(path)) {
+ ret = PTR_ERR(path);
goto out;
+ }
path = ext4_find_extent(inode, start, path, 0);
if (IS_ERR(path))
return PTR_ERR(path);
+
ex = path[path->p_depth].p_ext;
WARN_ON(le32_to_cpu(ex->ee_block) != start);
if (ext4_ext_get_actual_len(ex) != len) {
down_write(&EXT4_I(inode)->i_data_sem);
- ret = ext4_force_split_extent_at(NULL, inode, &path,
- start + len, 1);
+ path = ext4_force_split_extent_at(NULL, inode, path,
+ start + len, 1);
up_write(&EXT4_I(inode)->i_data_sem);
- if (ret)
+ if (IS_ERR(path)) {
+ ret = PTR_ERR(path);
goto out;
+ }
path = ext4_find_extent(inode, start, path, 0);
if (IS_ERR(path))
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 17/25] ext4: get rid of ppath in ext4_split_extent()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (15 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 16/25] ext4: get rid of ppath in ext4_force_split_extent_at() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 18/25] ext4: get rid of ppath in ext4_split_convert_extents() libaokun
` (8 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in ext4_split_extent(), the following is done here:
* The 'allocated' is changed from passing a value to passing an address.
* Its caller needs to update ppath if it uses ppath.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 97 ++++++++++++++++++++++++-----------------------
1 file changed, 50 insertions(+), 47 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index c64f87b53efb..9bbb8def1958 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3346,21 +3346,18 @@ static struct ext4_ext_path *ext4_split_extent_at(handle_t *handle,
* c> Splits in three extents: Somone is splitting in middle of the extent
*
*/
-static int ext4_split_extent(handle_t *handle,
- struct inode *inode,
- struct ext4_ext_path **ppath,
- struct ext4_map_blocks *map,
- int split_flag,
- int flags)
+static struct ext4_ext_path *ext4_split_extent(handle_t *handle,
+ struct inode *inode,
+ struct ext4_ext_path *path,
+ struct ext4_map_blocks *map,
+ int split_flag, int flags,
+ unsigned int *allocated)
{
- struct ext4_ext_path *path = *ppath;
ext4_lblk_t ee_block;
struct ext4_extent *ex;
unsigned int ee_len, depth;
- int err = 0;
int unwritten;
int split_flag1, flags1;
- int allocated = map->m_len;
depth = ext_depth(inode);
ex = path[depth].p_ext;
@@ -3378,33 +3375,25 @@ static int ext4_split_extent(handle_t *handle,
split_flag1 |= EXT4_EXT_DATA_VALID1;
path = ext4_split_extent_at(handle, inode, path,
map->m_lblk + map->m_len, split_flag1, flags1);
- if (IS_ERR(path)) {
- err = PTR_ERR(path);
- *ppath = NULL;
- goto out;
+ if (IS_ERR(path))
+ return path;
+ /*
+ * Update path is required because previous ext4_split_extent_at
+ * may result in split of original leaf or extent zeroout.
+ */
+ path = ext4_find_extent(inode, map->m_lblk, path, flags);
+ if (IS_ERR(path))
+ return path;
+ depth = ext_depth(inode);
+ ex = path[depth].p_ext;
+ if (!ex) {
+ EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+ (unsigned long) map->m_lblk);
+ ext4_free_ext_path(path);
+ return ERR_PTR(-EFSCORRUPTED);
}
- *ppath = path;
- } else {
- allocated = ee_len - (map->m_lblk - ee_block);
- }
- /*
- * Update path is required because previous ext4_split_extent_at() may
- * result in split of original leaf or extent zeroout.
- */
- path = ext4_find_extent(inode, map->m_lblk, path, flags);
- if (IS_ERR(path)) {
- *ppath = NULL;
- return PTR_ERR(path);
- }
- *ppath = path;
- depth = ext_depth(inode);
- ex = path[depth].p_ext;
- if (!ex) {
- EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
- (unsigned long) map->m_lblk);
- return -EFSCORRUPTED;
+ unwritten = ext4_ext_is_unwritten(ex);
}
- unwritten = ext4_ext_is_unwritten(ex);
if (map->m_lblk >= ee_block) {
split_flag1 = split_flag & EXT4_EXT_DATA_VALID2;
@@ -3415,17 +3404,18 @@ static int ext4_split_extent(handle_t *handle,
}
path = ext4_split_extent_at(handle, inode, path,
map->m_lblk, split_flag1, flags);
- if (IS_ERR(path)) {
- err = PTR_ERR(path);
- *ppath = NULL;
- goto out;
- }
- *ppath = path;
+ if (IS_ERR(path))
+ return path;
}
+ if (allocated) {
+ if (map->m_lblk + map->m_len > ee_block + ee_len)
+ *allocated = ee_len - (map->m_lblk - ee_block);
+ else
+ *allocated = map->m_len;
+ }
ext4_ext_show_leaf(inode, path);
-out:
- return err ? err : allocated;
+ return path;
}
/*
@@ -3670,10 +3660,15 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
}
fallback:
- err = ext4_split_extent(handle, inode, ppath, &split_map, split_flag,
- flags);
- if (err > 0)
- err = 0;
+ path = ext4_split_extent(handle, inode, path, &split_map, split_flag,
+ flags, NULL);
+ if (IS_ERR(path)) {
+ err = PTR_ERR(path);
+ *ppath = NULL;
+ goto out;
+ }
+ err = 0;
+ *ppath = path;
out:
/* If we have gotten a failure, don't zero out status tree */
if (!err) {
@@ -3719,6 +3714,7 @@ static int ext4_split_convert_extents(handle_t *handle,
struct ext4_extent *ex;
unsigned int ee_len;
int split_flag = 0, depth;
+ unsigned int allocated = 0;
ext_debug(inode, "logical block %llu, max_blocks %u\n",
(unsigned long long)map->m_lblk, map->m_len);
@@ -3746,7 +3742,14 @@ static int ext4_split_convert_extents(handle_t *handle,
split_flag |= (EXT4_EXT_MARK_UNWRIT2 | EXT4_EXT_DATA_VALID2);
}
flags |= EXT4_GET_BLOCKS_PRE_IO;
- return ext4_split_extent(handle, inode, ppath, map, split_flag, flags);
+ path = ext4_split_extent(handle, inode, path, map, split_flag, flags,
+ &allocated);
+ if (IS_ERR(path)) {
+ *ppath = NULL;
+ return PTR_ERR(path);
+ }
+ *ppath = path;
+ return allocated;
}
static int ext4_convert_unwritten_extents_endio(handle_t *handle,
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 18/25] ext4: get rid of ppath in ext4_split_convert_extents()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (16 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 17/25] ext4: get rid of ppath in ext4_split_extent() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 19/25] ext4: get rid of ppath in ext4_convert_unwritten_extents_endio() libaokun
` (7 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in ext4_split_convert_extents(), the following is
done here:
* Its caller needs to update ppath if it uses ppath.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 65 ++++++++++++++++++++++++-----------------------
1 file changed, 33 insertions(+), 32 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 9bbb8def1958..4698f765b8e7 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3700,21 +3700,21 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
* being filled will be convert to initialized by the end_io callback function
* via ext4_convert_unwritten_extents().
*
- * Returns the size of unwritten extent to be written on success.
+ * The size of unwritten extent to be written is passed to the caller via the
+ * allocated pointer. Return an extent path pointer on success, or an error
+ * pointer on failure.
*/
-static int ext4_split_convert_extents(handle_t *handle,
+static struct ext4_ext_path *ext4_split_convert_extents(handle_t *handle,
struct inode *inode,
struct ext4_map_blocks *map,
- struct ext4_ext_path **ppath,
- int flags)
+ struct ext4_ext_path *path,
+ int flags, unsigned int *allocated)
{
- struct ext4_ext_path *path = *ppath;
ext4_lblk_t eof_block;
ext4_lblk_t ee_block;
struct ext4_extent *ex;
unsigned int ee_len;
int split_flag = 0, depth;
- unsigned int allocated = 0;
ext_debug(inode, "logical block %llu, max_blocks %u\n",
(unsigned long long)map->m_lblk, map->m_len);
@@ -3742,14 +3742,8 @@ static int ext4_split_convert_extents(handle_t *handle,
split_flag |= (EXT4_EXT_MARK_UNWRIT2 | EXT4_EXT_DATA_VALID2);
}
flags |= EXT4_GET_BLOCKS_PRE_IO;
- path = ext4_split_extent(handle, inode, path, map, split_flag, flags,
- &allocated);
- if (IS_ERR(path)) {
- *ppath = NULL;
- return PTR_ERR(path);
- }
- *ppath = path;
- return allocated;
+ return ext4_split_extent(handle, inode, path, map, split_flag, flags,
+ allocated);
}
static int ext4_convert_unwritten_extents_endio(handle_t *handle,
@@ -3785,11 +3779,14 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
inode->i_ino, (unsigned long long)ee_block, ee_len,
(unsigned long long)map->m_lblk, map->m_len);
#endif
- err = ext4_split_convert_extents(handle, inode, map, ppath,
- EXT4_GET_BLOCKS_CONVERT);
- if (err < 0)
- return err;
- path = ext4_find_extent(inode, map->m_lblk, *ppath, 0);
+ path = ext4_split_convert_extents(handle, inode, map, path,
+ EXT4_GET_BLOCKS_CONVERT, NULL);
+ if (IS_ERR(path)) {
+ *ppath = NULL;
+ return PTR_ERR(path);
+ }
+
+ path = ext4_find_extent(inode, map->m_lblk, path, 0);
if (IS_ERR(path)) {
*ppath = NULL;
return PTR_ERR(path);
@@ -3846,11 +3843,14 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
(unsigned long long)ee_block, ee_len);
if (ee_block != map->m_lblk || ee_len > map->m_len) {
- err = ext4_split_convert_extents(handle, inode, map, ppath,
- EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
- if (err < 0)
- return err;
- path = ext4_find_extent(inode, map->m_lblk, *ppath, 0);
+ path = ext4_split_convert_extents(handle, inode, map, path,
+ EXT4_GET_BLOCKS_CONVERT_UNWRITTEN, NULL);
+ if (IS_ERR(path)) {
+ *ppath = NULL;
+ return PTR_ERR(path);
+ }
+
+ path = ext4_find_extent(inode, map->m_lblk, path, 0);
if (IS_ERR(path)) {
*ppath = NULL;
return PTR_ERR(path);
@@ -3916,19 +3916,20 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
/* get_block() before submitting IO, split the extent */
if (flags & EXT4_GET_BLOCKS_PRE_IO) {
- ret = ext4_split_convert_extents(handle, inode, map, ppath,
- flags | EXT4_GET_BLOCKS_CONVERT);
- if (ret < 0) {
- err = ret;
+ *ppath = ext4_split_convert_extents(handle, inode, map, *ppath,
+ flags | EXT4_GET_BLOCKS_CONVERT, &allocated);
+ if (IS_ERR(*ppath)) {
+ err = PTR_ERR(*ppath);
+ *ppath = NULL;
goto out2;
}
/*
- * shouldn't get a 0 return when splitting an extent unless
+ * shouldn't get a 0 allocated when splitting an extent unless
* m_len is 0 (bug) or extent has been corrupted
*/
- if (unlikely(ret == 0)) {
+ if (unlikely(allocated == 0)) {
EXT4_ERROR_INODE(inode,
- "unexpected ret == 0, m_len = %u",
+ "unexpected allocated == 0, m_len = %u",
map->m_len);
err = -EFSCORRUPTED;
goto out2;
@@ -3989,9 +3990,9 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
err = -EFSCORRUPTED;
goto out2;
}
+ allocated = ret;
out:
- allocated = ret;
map->m_flags |= EXT4_MAP_NEW;
map_out:
map->m_flags |= EXT4_MAP_MAPPED;
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 19/25] ext4: get rid of ppath in ext4_convert_unwritten_extents_endio()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (17 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 18/25] ext4: get rid of ppath in ext4_split_convert_extents() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 20/25] ext4: get rid of ppath in ext4_ext_convert_to_initialized() libaokun
` (6 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in ext4_convert_unwritten_extents_endio(), the
following is done here:
* Free the extents path when an error is encountered.
* Its caller needs to update ppath if it uses ppath.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 43 +++++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 20 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 4698f765b8e7..f0c9c53452d2 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3746,12 +3746,11 @@ static struct ext4_ext_path *ext4_split_convert_extents(handle_t *handle,
allocated);
}
-static int ext4_convert_unwritten_extents_endio(handle_t *handle,
- struct inode *inode,
- struct ext4_map_blocks *map,
- struct ext4_ext_path **ppath)
+static struct ext4_ext_path *
+ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
+ struct ext4_map_blocks *map,
+ struct ext4_ext_path *path)
{
- struct ext4_ext_path *path = *ppath;
struct ext4_extent *ex;
ext4_lblk_t ee_block;
unsigned int ee_len;
@@ -3781,24 +3780,19 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
#endif
path = ext4_split_convert_extents(handle, inode, map, path,
EXT4_GET_BLOCKS_CONVERT, NULL);
- if (IS_ERR(path)) {
- *ppath = NULL;
- return PTR_ERR(path);
- }
+ if (IS_ERR(path))
+ return path;
path = ext4_find_extent(inode, map->m_lblk, path, 0);
- if (IS_ERR(path)) {
- *ppath = NULL;
- return PTR_ERR(path);
- }
- *ppath = path;
+ if (IS_ERR(path))
+ return path;
depth = ext_depth(inode);
ex = path[depth].p_ext;
}
err = ext4_ext_get_access(handle, inode, path + depth);
if (err)
- goto out;
+ goto errout;
/* first mark the extent as initialized */
ext4_ext_mark_initialized(ex);
@@ -3809,9 +3803,15 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
/* Mark modified extent as dirty */
err = ext4_ext_dirty(handle, inode, path + path->p_depth);
-out:
+ if (err)
+ goto errout;
+
ext4_ext_show_leaf(inode, path);
- return err;
+ return path;
+
+errout:
+ ext4_free_ext_path(path);
+ return ERR_PTR(err);
}
static int
@@ -3939,10 +3939,13 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
}
/* IO end_io complete, convert the filled extent to written */
if (flags & EXT4_GET_BLOCKS_CONVERT) {
- err = ext4_convert_unwritten_extents_endio(handle, inode, map,
- ppath);
- if (err < 0)
+ *ppath = ext4_convert_unwritten_extents_endio(handle, inode,
+ map, *ppath);
+ if (IS_ERR(*ppath)) {
+ err = PTR_ERR(*ppath);
+ *ppath = NULL;
goto out2;
+ }
ext4_update_inode_fsync_trans(handle, inode, 1);
goto map_out;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 20/25] ext4: get rid of ppath in ext4_ext_convert_to_initialized()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (18 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 19/25] ext4: get rid of ppath in ext4_convert_unwritten_extents_endio() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 21/25] ext4: get rid of ppath in ext4_ext_handle_unwritten_extents() libaokun
` (5 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in ext4_ext_convert_to_initialized(), the following
is done here:
* Free the extents path when an error is encountered.
* Its caller needs to update ppath if it uses ppath.
* The 'allocated' is changed from passing a value to passing an address.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 73 +++++++++++++++++++++++------------------------
1 file changed, 35 insertions(+), 38 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index f0c9c53452d2..efc078c2124e 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3438,13 +3438,11 @@ static struct ext4_ext_path *ext4_split_extent(handle_t *handle,
* that are allocated and initialized.
* It is guaranteed to be >= map->m_len.
*/
-static int ext4_ext_convert_to_initialized(handle_t *handle,
- struct inode *inode,
- struct ext4_map_blocks *map,
- struct ext4_ext_path **ppath,
- int flags)
+static struct ext4_ext_path *
+ext4_ext_convert_to_initialized(handle_t *handle, struct inode *inode,
+ struct ext4_map_blocks *map, struct ext4_ext_path *path,
+ int flags, unsigned int *allocated)
{
- struct ext4_ext_path *path = *ppath;
struct ext4_sb_info *sbi;
struct ext4_extent_header *eh;
struct ext4_map_blocks split_map;
@@ -3454,7 +3452,6 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
unsigned int ee_len, depth, map_len = map->m_len;
int err = 0;
int split_flag = EXT4_EXT_DATA_VALID2;
- int allocated = 0;
unsigned int max_zeroout = 0;
ext_debug(inode, "logical block %llu, max_blocks %u\n",
@@ -3495,6 +3492,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
* - L2: we only attempt to merge with an extent stored in the
* same extent tree node.
*/
+ *allocated = 0;
if ((map->m_lblk == ee_block) &&
/* See if we can merge left */
(map_len < ee_len) && /*L1*/
@@ -3524,7 +3522,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
(prev_len < (EXT_INIT_MAX_LEN - map_len))) { /*C4*/
err = ext4_ext_get_access(handle, inode, path + depth);
if (err)
- goto out;
+ goto errout;
trace_ext4_ext_convert_to_initialized_fastpath(inode,
map, ex, abut_ex);
@@ -3539,7 +3537,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
abut_ex->ee_len = cpu_to_le16(prev_len + map_len);
/* Result: number of initialized blocks past m_lblk */
- allocated = map_len;
+ *allocated = map_len;
}
} else if (((map->m_lblk + map_len) == (ee_block + ee_len)) &&
(map_len < ee_len) && /*L1*/
@@ -3570,7 +3568,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
(next_len < (EXT_INIT_MAX_LEN - map_len))) { /*C4*/
err = ext4_ext_get_access(handle, inode, path + depth);
if (err)
- goto out;
+ goto errout;
trace_ext4_ext_convert_to_initialized_fastpath(inode,
map, ex, abut_ex);
@@ -3585,18 +3583,20 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
abut_ex->ee_len = cpu_to_le16(next_len + map_len);
/* Result: number of initialized blocks past m_lblk */
- allocated = map_len;
+ *allocated = map_len;
}
}
- if (allocated) {
+ if (*allocated) {
/* Mark the block containing both extents as dirty */
err = ext4_ext_dirty(handle, inode, path + depth);
/* Update path to point to the right extent */
path[depth].p_ext = abut_ex;
+ if (err)
+ goto errout;
goto out;
} else
- allocated = ee_len - (map->m_lblk - ee_block);
+ *allocated = ee_len - (map->m_lblk - ee_block);
WARN_ON(map->m_lblk < ee_block);
/*
@@ -3623,21 +3623,21 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
split_map.m_lblk = map->m_lblk;
split_map.m_len = map->m_len;
- if (max_zeroout && (allocated > split_map.m_len)) {
- if (allocated <= max_zeroout) {
+ if (max_zeroout && (*allocated > split_map.m_len)) {
+ if (*allocated <= max_zeroout) {
/* case 3 or 5 */
zero_ex1.ee_block =
cpu_to_le32(split_map.m_lblk +
split_map.m_len);
zero_ex1.ee_len =
- cpu_to_le16(allocated - split_map.m_len);
+ cpu_to_le16(*allocated - split_map.m_len);
ext4_ext_store_pblock(&zero_ex1,
ext4_ext_pblock(ex) + split_map.m_lblk +
split_map.m_len - ee_block);
err = ext4_ext_zeroout(inode, &zero_ex1);
if (err)
goto fallback;
- split_map.m_len = allocated;
+ split_map.m_len = *allocated;
}
if (split_map.m_lblk - ee_block + split_map.m_len <
max_zeroout) {
@@ -3655,27 +3655,24 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
split_map.m_len += split_map.m_lblk - ee_block;
split_map.m_lblk = ee_block;
- allocated = map->m_len;
+ *allocated = map->m_len;
}
}
fallback:
path = ext4_split_extent(handle, inode, path, &split_map, split_flag,
flags, NULL);
- if (IS_ERR(path)) {
- err = PTR_ERR(path);
- *ppath = NULL;
- goto out;
- }
- err = 0;
- *ppath = path;
+ if (IS_ERR(path))
+ return path;
out:
/* If we have gotten a failure, don't zero out status tree */
- if (!err) {
- ext4_zeroout_es(inode, &zero_ex1);
- ext4_zeroout_es(inode, &zero_ex2);
- }
- return err ? err : allocated;
+ ext4_zeroout_es(inode, &zero_ex1);
+ ext4_zeroout_es(inode, &zero_ex2);
+ return path;
+
+errout:
+ ext4_free_ext_path(path);
+ return ERR_PTR(err);
}
/*
@@ -3897,7 +3894,6 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
struct ext4_ext_path **ppath, int flags,
unsigned int allocated, ext4_fsblk_t newblock)
{
- int ret = 0;
int err = 0;
ext_debug(inode, "logical block %llu, max_blocks %u, flags 0x%x, allocated %u\n",
@@ -3977,23 +3973,24 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
* For buffered writes, at writepage time, etc. Convert a
* discovered unwritten extent to written.
*/
- ret = ext4_ext_convert_to_initialized(handle, inode, map, ppath, flags);
- if (ret < 0) {
- err = ret;
+ *ppath = ext4_ext_convert_to_initialized(handle, inode, map, *ppath,
+ flags, &allocated);
+ if (IS_ERR(*ppath)) {
+ err = PTR_ERR(*ppath);
+ *ppath = NULL;
goto out2;
}
ext4_update_inode_fsync_trans(handle, inode, 1);
/*
- * shouldn't get a 0 return when converting an unwritten extent
+ * shouldn't get a 0 allocated when converting an unwritten extent
* unless m_len is 0 (bug) or extent has been corrupted
*/
- if (unlikely(ret == 0)) {
- EXT4_ERROR_INODE(inode, "unexpected ret == 0, m_len = %u",
+ if (unlikely(allocated == 0)) {
+ EXT4_ERROR_INODE(inode, "unexpected allocated == 0, m_len = %u",
map->m_len);
err = -EFSCORRUPTED;
goto out2;
}
- allocated = ret;
out:
map->m_flags |= EXT4_MAP_NEW;
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 21/25] ext4: get rid of ppath in ext4_ext_handle_unwritten_extents()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (19 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 20/25] ext4: get rid of ppath in ext4_ext_convert_to_initialized() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 22/25] ext4: get rid of ppath in convert_initialized_extent() libaokun
` (4 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in ext4_ext_handle_unwritten_extents(), the
following is done here:
* Free the extents path when an error is encountered.
* The 'allocated' is changed from passing a value to passing an address.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 82 +++++++++++++++++++++--------------------------
1 file changed, 37 insertions(+), 45 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index efc078c2124e..dd2dd880dd8d 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3888,18 +3888,18 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
return 0;
}
-static int
+static struct ext4_ext_path *
ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
struct ext4_map_blocks *map,
- struct ext4_ext_path **ppath, int flags,
- unsigned int allocated, ext4_fsblk_t newblock)
+ struct ext4_ext_path *path, int flags,
+ unsigned int *allocated, ext4_fsblk_t newblock)
{
int err = 0;
ext_debug(inode, "logical block %llu, max_blocks %u, flags 0x%x, allocated %u\n",
(unsigned long long)map->m_lblk, map->m_len, flags,
- allocated);
- ext4_ext_show_leaf(inode, *ppath);
+ *allocated);
+ ext4_ext_show_leaf(inode, path);
/*
* When writing into unwritten space, we should not fail to
@@ -3908,40 +3908,34 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
flags |= EXT4_GET_BLOCKS_METADATA_NOFAIL;
trace_ext4_ext_handle_unwritten_extents(inode, map, flags,
- allocated, newblock);
+ *allocated, newblock);
/* get_block() before submitting IO, split the extent */
if (flags & EXT4_GET_BLOCKS_PRE_IO) {
- *ppath = ext4_split_convert_extents(handle, inode, map, *ppath,
- flags | EXT4_GET_BLOCKS_CONVERT, &allocated);
- if (IS_ERR(*ppath)) {
- err = PTR_ERR(*ppath);
- *ppath = NULL;
- goto out2;
- }
+ path = ext4_split_convert_extents(handle, inode, map, path,
+ flags | EXT4_GET_BLOCKS_CONVERT, allocated);
+ if (IS_ERR(path))
+ return path;
/*
* shouldn't get a 0 allocated when splitting an extent unless
* m_len is 0 (bug) or extent has been corrupted
*/
- if (unlikely(allocated == 0)) {
+ if (unlikely(*allocated == 0)) {
EXT4_ERROR_INODE(inode,
"unexpected allocated == 0, m_len = %u",
map->m_len);
err = -EFSCORRUPTED;
- goto out2;
+ goto errout;
}
map->m_flags |= EXT4_MAP_UNWRITTEN;
goto out;
}
/* IO end_io complete, convert the filled extent to written */
if (flags & EXT4_GET_BLOCKS_CONVERT) {
- *ppath = ext4_convert_unwritten_extents_endio(handle, inode,
- map, *ppath);
- if (IS_ERR(*ppath)) {
- err = PTR_ERR(*ppath);
- *ppath = NULL;
- goto out2;
- }
+ path = ext4_convert_unwritten_extents_endio(handle, inode,
+ map, path);
+ if (IS_ERR(path))
+ return path;
ext4_update_inode_fsync_trans(handle, inode, 1);
goto map_out;
}
@@ -3973,23 +3967,20 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
* For buffered writes, at writepage time, etc. Convert a
* discovered unwritten extent to written.
*/
- *ppath = ext4_ext_convert_to_initialized(handle, inode, map, *ppath,
- flags, &allocated);
- if (IS_ERR(*ppath)) {
- err = PTR_ERR(*ppath);
- *ppath = NULL;
- goto out2;
- }
+ path = ext4_ext_convert_to_initialized(handle, inode, map, path,
+ flags, allocated);
+ if (IS_ERR(path))
+ return path;
ext4_update_inode_fsync_trans(handle, inode, 1);
/*
* shouldn't get a 0 allocated when converting an unwritten extent
* unless m_len is 0 (bug) or extent has been corrupted
*/
- if (unlikely(allocated == 0)) {
+ if (unlikely(*allocated == 0)) {
EXT4_ERROR_INODE(inode, "unexpected allocated == 0, m_len = %u",
map->m_len);
err = -EFSCORRUPTED;
- goto out2;
+ goto errout;
}
out:
@@ -3998,12 +3989,15 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
map->m_flags |= EXT4_MAP_MAPPED;
out1:
map->m_pblk = newblock;
- if (allocated > map->m_len)
- allocated = map->m_len;
- map->m_len = allocated;
- ext4_ext_show_leaf(inode, *ppath);
-out2:
- return err ? err : allocated;
+ if (*allocated > map->m_len)
+ *allocated = map->m_len;
+ map->m_len = *allocated;
+ ext4_ext_show_leaf(inode, path);
+ return path;
+
+errout:
+ ext4_free_ext_path(path);
+ return ERR_PTR(err);
}
/*
@@ -4200,7 +4194,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
struct ext4_extent newex, *ex, ex2;
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
ext4_fsblk_t newblock = 0, pblk;
- int err = 0, depth, ret;
+ int err = 0, depth;
unsigned int allocated = 0, offset = 0;
unsigned int allocated_clusters = 0;
struct ext4_allocation_request ar;
@@ -4274,13 +4268,11 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
goto out;
}
- ret = ext4_ext_handle_unwritten_extents(
- handle, inode, map, &path, flags,
- allocated, newblock);
- if (ret < 0)
- err = ret;
- else
- allocated = ret;
+ path = ext4_ext_handle_unwritten_extents(
+ handle, inode, map, path, flags,
+ &allocated, newblock);
+ if (IS_ERR(path))
+ err = PTR_ERR(path);
goto out;
}
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 22/25] ext4: get rid of ppath in convert_initialized_extent()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (20 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 21/25] ext4: get rid of ppath in ext4_ext_handle_unwritten_extents() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 23/25] ext4: refactor ext4_swap_extents() to reuse extents path libaokun
` (3 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The use of path and ppath is now very confusing, so to make the code more
readable, pass path between functions uniformly, and get rid of ppath.
To get rid of the ppath in convert_initialized_extent(), the following is
done here:
* Free the extents path when an error is encountered.
No functional changes.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index dd2dd880dd8d..bc7b1dc13084 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3811,13 +3811,12 @@ ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
return ERR_PTR(err);
}
-static int
+static struct ext4_ext_path *
convert_initialized_extent(handle_t *handle, struct inode *inode,
struct ext4_map_blocks *map,
- struct ext4_ext_path **ppath,
+ struct ext4_ext_path *path,
unsigned int *allocated)
{
- struct ext4_ext_path *path = *ppath;
struct ext4_extent *ex;
ext4_lblk_t ee_block;
unsigned int ee_len;
@@ -3842,29 +3841,25 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
if (ee_block != map->m_lblk || ee_len > map->m_len) {
path = ext4_split_convert_extents(handle, inode, map, path,
EXT4_GET_BLOCKS_CONVERT_UNWRITTEN, NULL);
- if (IS_ERR(path)) {
- *ppath = NULL;
- return PTR_ERR(path);
- }
+ if (IS_ERR(path))
+ return path;
path = ext4_find_extent(inode, map->m_lblk, path, 0);
- if (IS_ERR(path)) {
- *ppath = NULL;
- return PTR_ERR(path);
- }
- *ppath = path;
+ if (IS_ERR(path))
+ return path;
depth = ext_depth(inode);
ex = path[depth].p_ext;
if (!ex) {
EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
(unsigned long) map->m_lblk);
- return -EFSCORRUPTED;
+ err = -EFSCORRUPTED;
+ goto errout;
}
}
err = ext4_ext_get_access(handle, inode, path + depth);
if (err)
- return err;
+ goto errout;
/* first mark the extent as unwritten */
ext4_ext_mark_unwritten(ex);
@@ -3876,7 +3871,7 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
/* Mark modified extent as dirty */
err = ext4_ext_dirty(handle, inode, path + path->p_depth);
if (err)
- return err;
+ goto errout;
ext4_ext_show_leaf(inode, path);
ext4_update_inode_fsync_trans(handle, inode, 1);
@@ -3885,7 +3880,11 @@ convert_initialized_extent(handle_t *handle, struct inode *inode,
if (*allocated > map->m_len)
*allocated = map->m_len;
map->m_len = *allocated;
- return 0;
+ return path;
+
+errout:
+ ext4_free_ext_path(path);
+ return ERR_PTR(err);
}
static struct ext4_ext_path *
@@ -4255,8 +4254,10 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
*/
if ((!ext4_ext_is_unwritten(ex)) &&
(flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) {
- err = convert_initialized_extent(handle,
- inode, map, &path, &allocated);
+ path = convert_initialized_extent(handle,
+ inode, map, path, &allocated);
+ if (IS_ERR(path))
+ err = PTR_ERR(path);
goto out;
} else if (!ext4_ext_is_unwritten(ex)) {
map->m_flags |= EXT4_MAP_MAPPED;
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 23/25] ext4: refactor ext4_swap_extents() to reuse extents path
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (21 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 22/25] ext4: get rid of ppath in convert_initialized_extent() libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 24/25] ext4: make some fast commit functions " libaokun
` (2 subsequent siblings)
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The ext4_find_extent() can update the extent path so it doesn't have to
allocate and free path repeatedly, thus reducing the consumption of memory
allocation and freeing in ext4_swap_extents().
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 48 ++++++++++++++++++++++-------------------------
1 file changed, 22 insertions(+), 26 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index bc7b1dc13084..37b36b1abb16 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -5699,25 +5699,21 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
int e1_len, e2_len, len;
int split = 0;
- path1 = ext4_find_extent(inode1, lblk1, NULL, EXT4_EX_NOCACHE);
+ path1 = ext4_find_extent(inode1, lblk1, path1, EXT4_EX_NOCACHE);
if (IS_ERR(path1)) {
*erp = PTR_ERR(path1);
- path1 = NULL;
- finish:
- count = 0;
- goto repeat;
+ goto errout;
}
- path2 = ext4_find_extent(inode2, lblk2, NULL, EXT4_EX_NOCACHE);
+ path2 = ext4_find_extent(inode2, lblk2, path2, EXT4_EX_NOCACHE);
if (IS_ERR(path2)) {
*erp = PTR_ERR(path2);
- path2 = NULL;
- goto finish;
+ goto errout;
}
ex1 = path1[path1->p_depth].p_ext;
ex2 = path2[path2->p_depth].p_ext;
/* Do we have something to swap ? */
if (unlikely(!ex2 || !ex1))
- goto finish;
+ goto errout;
e1_blk = le32_to_cpu(ex1->ee_block);
e2_blk = le32_to_cpu(ex2->ee_block);
@@ -5739,7 +5735,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
next2 = e2_blk;
/* Do we have something to swap */
if (next1 == EXT_MAX_BLOCKS || next2 == EXT_MAX_BLOCKS)
- goto finish;
+ goto errout;
/* Move to the rightest boundary */
len = next1 - lblk1;
if (len < next2 - lblk2)
@@ -5749,7 +5745,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
lblk1 += len;
lblk2 += len;
count -= len;
- goto repeat;
+ continue;
}
/* Prepare left boundary */
@@ -5759,7 +5755,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
path1, lblk1, 0);
if (IS_ERR(path1)) {
*erp = PTR_ERR(path1);
- goto finish;
+ goto errout;
}
}
if (e2_blk < lblk2) {
@@ -5768,13 +5764,13 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
path2, lblk2, 0);
if (IS_ERR(path2)) {
*erp = PTR_ERR(path2);
- goto finish;
+ goto errout;
}
}
/* ext4_split_extent_at() may result in leaf extent split,
* path must to be revalidated. */
if (split)
- goto repeat;
+ continue;
/* Prepare right boundary */
len = count;
@@ -5789,7 +5785,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
path1, lblk1 + len, 0);
if (IS_ERR(path1)) {
*erp = PTR_ERR(path1);
- goto finish;
+ goto errout;
}
}
if (len != e2_len) {
@@ -5798,21 +5794,21 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
path2, lblk2 + len, 0);
if (IS_ERR(path2)) {
*erp = PTR_ERR(path2);
- goto finish;
+ goto errout;
}
}
/* ext4_split_extent_at() may result in leaf extent split,
* path must to be revalidated. */
if (split)
- goto repeat;
+ continue;
BUG_ON(e2_len != e1_len);
*erp = ext4_ext_get_access(handle, inode1, path1 + path1->p_depth);
if (unlikely(*erp))
- goto finish;
+ goto errout;
*erp = ext4_ext_get_access(handle, inode2, path2 + path2->p_depth);
if (unlikely(*erp))
- goto finish;
+ goto errout;
/* Both extents are fully inside boundaries. Swap it now */
tmp_ex = *ex1;
@@ -5830,7 +5826,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
*erp = ext4_ext_dirty(handle, inode2, path2 +
path2->p_depth);
if (unlikely(*erp))
- goto finish;
+ goto errout;
*erp = ext4_ext_dirty(handle, inode1, path1 +
path1->p_depth);
/*
@@ -5840,17 +5836,17 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
* aborted anyway.
*/
if (unlikely(*erp))
- goto finish;
+ goto errout;
+
lblk1 += len;
lblk2 += len;
replaced_count += len;
count -= len;
-
- repeat:
- ext4_free_ext_path(path1);
- ext4_free_ext_path(path2);
- path1 = path2 = NULL;
}
+
+errout:
+ ext4_free_ext_path(path1);
+ ext4_free_ext_path(path2);
return replaced_count;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 24/25] ext4: make some fast commit functions reuse extents path
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (22 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 23/25] ext4: refactor ext4_swap_extents() to reuse extents path libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-22 2:35 ` [PATCH v2 25/25] ext4: save unnecessary indentation in ext4_ext_create_new_leaf() libaokun
2024-09-05 14:53 ` [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path Theodore Ts'o
25 siblings, 0 replies; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
The ext4_find_extent() can update the extent path so that it does not have
to allocate and free the path repeatedly, thus reducing the consumption of
memory allocation and freeing in the following functions:
ext4_ext_clear_bb
ext4_ext_replay_set_iblocks
ext4_fc_replay_add_range
ext4_fc_set_bitmaps_and_counters
No functional changes. Note that ext4_find_extent() does not support error
pointers, so in this case set path to NULL first.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents.c | 51 +++++++++++++++++++------------------------
fs/ext4/fast_commit.c | 11 ++++++----
2 files changed, 29 insertions(+), 33 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 37b36b1abb16..ca1f946514dd 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -6069,12 +6069,9 @@ int ext4_ext_replay_set_iblocks(struct inode *inode)
if (IS_ERR(path))
return PTR_ERR(path);
ex = path[path->p_depth].p_ext;
- if (!ex) {
- ext4_free_ext_path(path);
+ if (!ex)
goto out;
- }
end = le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex);
- ext4_free_ext_path(path);
/* Count the number of data blocks */
cur = 0;
@@ -6100,32 +6097,28 @@ int ext4_ext_replay_set_iblocks(struct inode *inode)
ret = skip_hole(inode, &cur);
if (ret < 0)
goto out;
- path = ext4_find_extent(inode, cur, NULL, 0);
+ path = ext4_find_extent(inode, cur, path, 0);
if (IS_ERR(path))
goto out;
numblks += path->p_depth;
- ext4_free_ext_path(path);
while (cur < end) {
- path = ext4_find_extent(inode, cur, NULL, 0);
+ path = ext4_find_extent(inode, cur, path, 0);
if (IS_ERR(path))
break;
ex = path[path->p_depth].p_ext;
- if (!ex) {
- ext4_free_ext_path(path);
- return 0;
- }
+ if (!ex)
+ goto cleanup;
+
cur = max(cur + 1, le32_to_cpu(ex->ee_block) +
ext4_ext_get_actual_len(ex));
ret = skip_hole(inode, &cur);
- if (ret < 0) {
- ext4_free_ext_path(path);
+ if (ret < 0)
break;
- }
- path2 = ext4_find_extent(inode, cur, NULL, 0);
- if (IS_ERR(path2)) {
- ext4_free_ext_path(path);
+
+ path2 = ext4_find_extent(inode, cur, path2, 0);
+ if (IS_ERR(path2))
break;
- }
+
for (i = 0; i <= max(path->p_depth, path2->p_depth); i++) {
cmp1 = cmp2 = 0;
if (i <= path->p_depth)
@@ -6137,13 +6130,14 @@ int ext4_ext_replay_set_iblocks(struct inode *inode)
if (cmp1 != cmp2 && cmp2 != 0)
numblks++;
}
- ext4_free_ext_path(path);
- ext4_free_ext_path(path2);
}
out:
inode->i_blocks = numblks << (inode->i_sb->s_blocksize_bits - 9);
ext4_mark_inode_dirty(NULL, inode);
+cleanup:
+ ext4_free_ext_path(path);
+ ext4_free_ext_path(path2);
return 0;
}
@@ -6164,12 +6158,9 @@ int ext4_ext_clear_bb(struct inode *inode)
if (IS_ERR(path))
return PTR_ERR(path);
ex = path[path->p_depth].p_ext;
- if (!ex) {
- ext4_free_ext_path(path);
- return 0;
- }
+ if (!ex)
+ goto out;
end = le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex);
- ext4_free_ext_path(path);
cur = 0;
while (cur < end) {
@@ -6179,16 +6170,16 @@ int ext4_ext_clear_bb(struct inode *inode)
if (ret < 0)
break;
if (ret > 0) {
- path = ext4_find_extent(inode, map.m_lblk, NULL, 0);
- if (!IS_ERR_OR_NULL(path)) {
+ path = ext4_find_extent(inode, map.m_lblk, path, 0);
+ if (!IS_ERR(path)) {
for (j = 0; j < path->p_depth; j++) {
-
ext4_mb_mark_bb(inode->i_sb,
path[j].p_block, 1, false);
ext4_fc_record_regions(inode->i_sb, inode->i_ino,
0, path[j].p_block, 1, 1);
}
- ext4_free_ext_path(path);
+ } else {
+ path = NULL;
}
ext4_mb_mark_bb(inode->i_sb, map.m_pblk, map.m_len, false);
ext4_fc_record_regions(inode->i_sb, inode->i_ino,
@@ -6197,5 +6188,7 @@ int ext4_ext_clear_bb(struct inode *inode)
cur = cur + map.m_len;
}
+out:
+ ext4_free_ext_path(path);
return 0;
}
diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index 52e42cb02f39..7ab3290b49e3 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -1772,7 +1772,7 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
if (ret == 0) {
/* Range is not mapped */
- path = ext4_find_extent(inode, cur, NULL, 0);
+ path = ext4_find_extent(inode, cur, path, 0);
if (IS_ERR(path))
goto out;
memset(&newex, 0, sizeof(newex));
@@ -1788,7 +1788,6 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
up_write((&EXT4_I(inode)->i_data_sem));
if (IS_ERR(path))
goto out;
- ext4_free_ext_path(path);
goto next;
}
@@ -1836,6 +1835,7 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
ext4_ext_replay_shrink_inode(inode, i_size_read(inode) >>
sb->s_blocksize_bits);
out:
+ ext4_free_ext_path(path);
iput(inode);
return 0;
}
@@ -1936,12 +1936,13 @@ static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb)
break;
if (ret > 0) {
- path = ext4_find_extent(inode, map.m_lblk, NULL, 0);
+ path = ext4_find_extent(inode, map.m_lblk, path, 0);
if (!IS_ERR(path)) {
for (j = 0; j < path->p_depth; j++)
ext4_mb_mark_bb(inode->i_sb,
path[j].p_block, 1, true);
- ext4_free_ext_path(path);
+ } else {
+ path = NULL;
}
cur += ret;
ext4_mb_mark_bb(inode->i_sb, map.m_pblk,
@@ -1952,6 +1953,8 @@ static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb)
}
iput(inode);
}
+
+ ext4_free_ext_path(path);
}
/*
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v2 25/25] ext4: save unnecessary indentation in ext4_ext_create_new_leaf()
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (23 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 24/25] ext4: make some fast commit functions " libaokun
@ 2024-08-22 2:35 ` libaokun
2024-08-27 17:16 ` Jan Kara
2024-09-05 14:53 ` [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path Theodore Ts'o
25 siblings, 1 reply; 30+ messages in thread
From: libaokun @ 2024-08-22 2:35 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, ritesh.list, ojaswin, linux-kernel,
yi.zhang, yangerkun, libaokun, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
Save an indentation level in ext4_ext_create_new_leaf() by removing
unnecessary 'else'. Besides, the variable 'ee_block' is declared to
avoid line breaks. No functional changes.
Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
fs/ext4/extents.c | 44 +++++++++++++++++++++-----------------------
1 file changed, 21 insertions(+), 23 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index ca1f946514dd..45ddc0692673 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1403,6 +1403,7 @@ ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
{
struct ext4_ext_path *curp;
int depth, i, err = 0;
+ ext4_lblk_t ee_block = le32_to_cpu(newext->ee_block);
repeat:
i = depth = ext_depth(inode);
@@ -1424,33 +1425,30 @@ ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
goto errout;
/* refill path */
- path = ext4_find_extent(inode,
- (ext4_lblk_t)le32_to_cpu(newext->ee_block),
- path, gb_flags);
+ path = ext4_find_extent(inode, ee_block, path, gb_flags);
return path;
- } else {
- /* tree is full, time to grow in depth */
- err = ext4_ext_grow_indepth(handle, inode, mb_flags);
- if (err)
- goto errout;
+ }
- /* refill path */
- path = ext4_find_extent(inode,
- (ext4_lblk_t)le32_to_cpu(newext->ee_block),
- path, gb_flags);
- if (IS_ERR(path))
- return path;
+ /* tree is full, time to grow in depth */
+ err = ext4_ext_grow_indepth(handle, inode, mb_flags);
+ if (err)
+ goto errout;
- /*
- * only first (depth 0 -> 1) produces free space;
- * in all other cases we have to split the grown tree
- */
- depth = ext_depth(inode);
- if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
- /* now we need to split */
- goto repeat;
- }
+ /* refill path */
+ path = ext4_find_extent(inode, ee_block, path, gb_flags);
+ if (IS_ERR(path))
+ return path;
+
+ /*
+ * only first (depth 0 -> 1) produces free space;
+ * in all other cases we have to split the grown tree
+ */
+ depth = ext_depth(inode);
+ if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
+ /* now we need to split */
+ goto repeat;
}
+
return path;
errout:
--
2.39.2
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH v2 25/25] ext4: save unnecessary indentation in ext4_ext_create_new_leaf()
2024-08-22 2:35 ` [PATCH v2 25/25] ext4: save unnecessary indentation in ext4_ext_create_new_leaf() libaokun
@ 2024-08-27 17:16 ` Jan Kara
0 siblings, 0 replies; 30+ messages in thread
From: Jan Kara @ 2024-08-27 17:16 UTC (permalink / raw)
To: libaokun
Cc: linux-ext4, tytso, adilger.kernel, jack, ritesh.list, ojaswin,
linux-kernel, yi.zhang, yangerkun, Baokun Li
On Thu 22-08-24 10:35:45, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> Save an indentation level in ext4_ext_create_new_leaf() by removing
> unnecessary 'else'. Besides, the variable 'ee_block' is declared to
> avoid line breaks. No functional changes.
>
> Suggested-by: Jan Kara <jack@suse.cz>
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/ext4/extents.c | 44 +++++++++++++++++++++-----------------------
> 1 file changed, 21 insertions(+), 23 deletions(-)
>
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index ca1f946514dd..45ddc0692673 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -1403,6 +1403,7 @@ ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
> {
> struct ext4_ext_path *curp;
> int depth, i, err = 0;
> + ext4_lblk_t ee_block = le32_to_cpu(newext->ee_block);
>
> repeat:
> i = depth = ext_depth(inode);
> @@ -1424,33 +1425,30 @@ ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
> goto errout;
>
> /* refill path */
> - path = ext4_find_extent(inode,
> - (ext4_lblk_t)le32_to_cpu(newext->ee_block),
> - path, gb_flags);
> + path = ext4_find_extent(inode, ee_block, path, gb_flags);
> return path;
> - } else {
> - /* tree is full, time to grow in depth */
> - err = ext4_ext_grow_indepth(handle, inode, mb_flags);
> - if (err)
> - goto errout;
> + }
>
> - /* refill path */
> - path = ext4_find_extent(inode,
> - (ext4_lblk_t)le32_to_cpu(newext->ee_block),
> - path, gb_flags);
> - if (IS_ERR(path))
> - return path;
> + /* tree is full, time to grow in depth */
> + err = ext4_ext_grow_indepth(handle, inode, mb_flags);
> + if (err)
> + goto errout;
>
> - /*
> - * only first (depth 0 -> 1) produces free space;
> - * in all other cases we have to split the grown tree
> - */
> - depth = ext_depth(inode);
> - if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
> - /* now we need to split */
> - goto repeat;
> - }
> + /* refill path */
> + path = ext4_find_extent(inode, ee_block, path, gb_flags);
> + if (IS_ERR(path))
> + return path;
> +
> + /*
> + * only first (depth 0 -> 1) produces free space;
> + * in all other cases we have to split the grown tree
> + */
> + depth = ext_depth(inode);
> + if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
> + /* now we need to split */
> + goto repeat;
> }
> +
> return path;
>
> errout:
> --
> 2.39.2
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v2 05/25] ext4: update orig_path in ext4_find_extent()
2024-08-22 2:35 ` [PATCH v2 05/25] ext4: update orig_path in ext4_find_extent() libaokun
@ 2024-08-27 18:04 ` Jan Kara
0 siblings, 0 replies; 30+ messages in thread
From: Jan Kara @ 2024-08-27 18:04 UTC (permalink / raw)
To: libaokun
Cc: linux-ext4, tytso, adilger.kernel, jack, ritesh.list, ojaswin,
linux-kernel, yi.zhang, yangerkun, Baokun Li, stable
On Thu 22-08-24 10:35:25, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> In ext4_find_extent(), if the path is not big enough, we free it and set
> *orig_path to NULL. But after reallocating and successfully initializing
> the path, we don't update *orig_path, in which case the caller gets a
> valid path but a NULL ppath, and this may cause a NULL pointer dereference
> or a path memory leak. For example:
>
> ext4_split_extent
> path = *ppath = 2000
> ext4_find_extent
> if (depth > path[0].p_maxdepth)
> kfree(path = 2000);
> *orig_path = path = NULL;
> path = kcalloc() = 3000
> ext4_split_extent_at(*ppath = NULL)
> path = *ppath;
> ex = path[depth].p_ext;
> // NULL pointer dereference!
>
> ==================================================================
> BUG: kernel NULL pointer dereference, address: 0000000000000010
> CPU: 6 UID: 0 PID: 576 Comm: fsstress Not tainted 6.11.0-rc2-dirty #847
> RIP: 0010:ext4_split_extent_at+0x6d/0x560
> Call Trace:
> <TASK>
> ext4_split_extent.isra.0+0xcb/0x1b0
> ext4_ext_convert_to_initialized+0x168/0x6c0
> ext4_ext_handle_unwritten_extents+0x325/0x4d0
> ext4_ext_map_blocks+0x520/0xdb0
> ext4_map_blocks+0x2b0/0x690
> ext4_iomap_begin+0x20e/0x2c0
> [...]
> ==================================================================
>
> Therefore, *orig_path is updated when the extent lookup succeeds, so that
> the caller can safely use path or *ppath.
>
> Fixes: 10809df84a4d ("ext4: teach ext4_ext_find_extent() to realloc path if necessary")
> Cc: stable@kernel.org
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/ext4/extents.c | 3 ++-
> fs/ext4/move_extent.c | 1 -
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index 0224cf0ef19e..5879aef159d8 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -957,6 +957,8 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
>
> ext4_ext_show_path(inode, path);
>
> + if (orig_path)
> + *orig_path = path;
> return path;
>
> err:
> @@ -3268,7 +3270,6 @@ static int ext4_split_extent_at(handle_t *handle,
> }
> depth = ext_depth(inode);
> ex = path[depth].p_ext;
> - *ppath = path;
>
> if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
> if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
> diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
> index 204f53b23622..c95e3e526390 100644
> --- a/fs/ext4/move_extent.c
> +++ b/fs/ext4/move_extent.c
> @@ -36,7 +36,6 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
> *ppath = NULL;
> return -ENODATA;
> }
> - *ppath = path;
> return 0;
> }
>
> --
> 2.39.2
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v2 06/25] ext4: aovid use-after-free in ext4_ext_insert_extent()
2024-08-22 2:35 ` [PATCH v2 06/25] ext4: aovid use-after-free in ext4_ext_insert_extent() libaokun
@ 2024-08-27 18:07 ` Jan Kara
0 siblings, 0 replies; 30+ messages in thread
From: Jan Kara @ 2024-08-27 18:07 UTC (permalink / raw)
To: libaokun
Cc: linux-ext4, tytso, adilger.kernel, jack, ritesh.list, ojaswin,
linux-kernel, yi.zhang, yangerkun, Baokun Li, stable
On Thu 22-08-24 10:35:26, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> As Ojaswin mentioned in Link, in ext4_ext_insert_extent(), if the path is
> reallocated in ext4_ext_create_new_leaf(), we'll use the stale path and
> cause UAF. Below is a sample trace with dummy values:
>
> ext4_ext_insert_extent
> path = *ppath = 2000
> ext4_ext_create_new_leaf(ppath)
> ext4_find_extent(ppath)
> path = *ppath = 2000
> if (depth > path[0].p_maxdepth)
> kfree(path = 2000);
> *ppath = path = NULL;
> path = kcalloc() = 3000
> *ppath = 3000;
> return path;
> /* here path is still 2000, UAF! */
> eh = path[depth].p_hdr
>
> ==================================================================
> BUG: KASAN: slab-use-after-free in ext4_ext_insert_extent+0x26d4/0x3330
> Read of size 8 at addr ffff8881027bf7d0 by task kworker/u36:1/179
> CPU: 3 UID: 0 PID: 179 Comm: kworker/u6:1 Not tainted 6.11.0-rc2-dirty #866
> Call Trace:
> <TASK>
> ext4_ext_insert_extent+0x26d4/0x3330
> ext4_ext_map_blocks+0xe22/0x2d40
> ext4_map_blocks+0x71e/0x1700
> ext4_do_writepages+0x1290/0x2800
> [...]
>
> Allocated by task 179:
> ext4_find_extent+0x81c/0x1f70
> ext4_ext_map_blocks+0x146/0x2d40
> ext4_map_blocks+0x71e/0x1700
> ext4_do_writepages+0x1290/0x2800
> ext4_writepages+0x26d/0x4e0
> do_writepages+0x175/0x700
> [...]
>
> Freed by task 179:
> kfree+0xcb/0x240
> ext4_find_extent+0x7c0/0x1f70
> ext4_ext_insert_extent+0xa26/0x3330
> ext4_ext_map_blocks+0xe22/0x2d40
> ext4_map_blocks+0x71e/0x1700
> ext4_do_writepages+0x1290/0x2800
> ext4_writepages+0x26d/0x4e0
> do_writepages+0x175/0x700
> [...]
> ==================================================================
>
> So use *ppath to update the path to avoid the above problem.
>
> Reported-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
> Closes: https://lore.kernel.org/r/ZqyL6rmtwl6N4MWR@li-bb2b2a4c-3307-11b2-a85c-8fa5c3a69313.ibm.com
> Fixes: 10809df84a4d ("ext4: teach ext4_ext_find_extent() to realloc path if necessary")
> Cc: stable@kernel.org
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/ext4/extents.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index 5879aef159d8..91c6586afcca 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -2116,6 +2116,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
> ppath, newext);
> if (err)
> goto cleanup;
> + path = *ppath;
> depth = ext_depth(inode);
> eh = path[depth].p_hdr;
>
> --
> 2.39.2
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
` (24 preceding siblings ...)
2024-08-22 2:35 ` [PATCH v2 25/25] ext4: save unnecessary indentation in ext4_ext_create_new_leaf() libaokun
@ 2024-09-05 14:53 ` Theodore Ts'o
25 siblings, 0 replies; 30+ messages in thread
From: Theodore Ts'o @ 2024-09-05 14:53 UTC (permalink / raw)
To: linux-ext4, libaokun
Cc: Theodore Ts'o, adilger.kernel, jack, ritesh.list, ojaswin,
linux-kernel, yi.zhang, yangerkun, Baokun Li
On Thu, 22 Aug 2024 10:35:20 +0800, libaokun@huaweicloud.com wrote:
> This patch series is a hardening of ext4 extents path related code.
>
> This is the second version of this patch series. Thank you, Jan Kara and
> Ojaswin Mujoo, for the feedback in the previous version. The new version
> has no functional changes compared to the previous one, so I've kept the
> previous Reviewed-by, please let me know if you have any objections.
>
> [...]
Applied, thanks!
[01/25] ext4: refactor ext4_ext_rm_idx() to index 'path'
commit: edfa71dbe841075109e3e1da7d3925b45328ed25
[02/25] ext4: prevent partial update of the extents path
commit: 3e8a584c82cc999b99ea17c31fc2da101201545f
[03/25] ext4: fix slab-use-after-free in ext4_split_extent_at()
commit: c26ab35702f8cd0cdc78f96aa5856bfb77be798f
[04/25] ext4: avoid use-after-free in ext4_ext_show_leaf()
commit: 4e2524ba2ca5f54bdbb9e5153bea00421ef653f5
[05/25] ext4: update orig_path in ext4_find_extent()
commit: 5b4b2dcace35f618fe361a87bae6f0d13af31bc1
[06/25] ext4: aovid use-after-free in ext4_ext_insert_extent()
commit: a164f3a432aae62ca23d03e6d926b122ee5b860d
[07/25] ext4: drop ppath from ext4_ext_replay_update_ex() to avoid double-free
commit: 5c0f4cc84d3a601c99bc5e6e6eb1cbda542cce95
[08/25] ext4: fix double brelse() the buffer of the extents path
commit: dcaa6c31134c0f515600111c38ed7750003e1b9c
[09/25] ext4: add new ext4_ext_path_brelse() helper
commit: 6c2b3246cd0b951338c54b10f8ca13c59a41c86a
[10/25] ext4: propagate errors from ext4_find_extent() in ext4_insert_range()
commit: 369c944ed1d7c3fb7b35f24e4735761153afe7b3
[11/25] ext4: get rid of ppath in ext4_find_extent()
commit: 0be4c0c2f17bd10ae16c852f02d51a6a7b318aca
[12/25] ext4: get rid of ppath in get_ext_path()
commit: 6b854d552711aa33f59eda334e6d94a00d8825bb
[13/25] ext4: get rid of ppath in ext4_ext_create_new_leaf()
commit: a000bc8678cc2bb10a5b80b4e991e77c7b4612fd
[14/25] ext4: get rid of ppath in ext4_ext_insert_extent()
commit: f7d1331f16a869c76a5102caebb58e840e1d509c
[15/25] ext4: get rid of ppath in ext4_split_extent_at()
commit: 1de82b1b60d4613753254bf3cbf622a4c02c945c
[16/25] ext4: get rid of ppath in ext4_force_split_extent_at()
commit: f07be1c367369636d7d338d7994473d6eae283c5
[17/25] ext4: get rid of ppath in ext4_split_extent()
commit: f74cde045617cc275c848c9692feac249ff7a3e7
[18/25] ext4: get rid of ppath in ext4_split_convert_extents()
commit: 225057b1af381567ffa4eb813f4a28a5c38a25cf
[19/25] ext4: get rid of ppath in ext4_convert_unwritten_extents_endio()
commit: 8d5ad7b08f9234bc92b9567cfe52e521df5f6626
[20/25] ext4: get rid of ppath in ext4_ext_convert_to_initialized()
commit: 33c14b8bd8a9ef8b3dfde136b0ca779e68c2f576
[21/25] ext4: get rid of ppath in ext4_ext_handle_unwritten_extents()
commit: 2ec2e1043473b3d4a3afbe6ad7c5a5b7a6fdf480
[22/25] ext4: get rid of ppath in convert_initialized_extent()
commit: 4191eefef978d734fa8249bede3f9b02a85aa3c0
[23/25] ext4: refactor ext4_swap_extents() to reuse extents path
commit: a2c613b8c4860d5e70010e7391fff727c5d96bab
[24/25] ext4: make some fast commit functions reuse extents path
commit: 2352e3e461926b59f01c1e39fbb0494891cff997
[25/25] ext4: save unnecessary indentation in ext4_ext_create_new_leaf()
commit: 5f48d4d9d8556ffa934537f0c000f9c3e108da66
Best regards,
--
Theodore Ts'o <tytso@mit.edu>
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2024-09-05 14:54 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-22 2:35 [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path libaokun
2024-08-22 2:35 ` [PATCH v2 01/25] ext4: refactor ext4_ext_rm_idx() to index 'path' libaokun
2024-08-22 2:35 ` [PATCH v2 02/25] ext4: prevent partial update of the extents path libaokun
2024-08-22 2:35 ` [PATCH v2 03/25] ext4: fix slab-use-after-free in ext4_split_extent_at() libaokun
2024-08-22 2:35 ` [PATCH v2 04/25] ext4: avoid use-after-free in ext4_ext_show_leaf() libaokun
2024-08-22 2:35 ` [PATCH v2 05/25] ext4: update orig_path in ext4_find_extent() libaokun
2024-08-27 18:04 ` Jan Kara
2024-08-22 2:35 ` [PATCH v2 06/25] ext4: aovid use-after-free in ext4_ext_insert_extent() libaokun
2024-08-27 18:07 ` Jan Kara
2024-08-22 2:35 ` [PATCH v2 07/25] ext4: drop ppath from ext4_ext_replay_update_ex() to avoid double-free libaokun
2024-08-22 2:35 ` [PATCH v2 08/25] ext4: fix double brelse() the buffer of the extents path libaokun
2024-08-22 2:35 ` [PATCH v2 09/25] ext4: add new ext4_ext_path_brelse() helper libaokun
2024-08-22 2:35 ` [PATCH v2 10/25] ext4: propagate errors from ext4_find_extent() in ext4_insert_range() libaokun
2024-08-22 2:35 ` [PATCH v2 11/25] ext4: get rid of ppath in ext4_find_extent() libaokun
2024-08-22 2:35 ` [PATCH v2 12/25] ext4: get rid of ppath in get_ext_path() libaokun
2024-08-22 2:35 ` [PATCH v2 13/25] ext4: get rid of ppath in ext4_ext_create_new_leaf() libaokun
2024-08-22 2:35 ` [PATCH v2 14/25] ext4: get rid of ppath in ext4_ext_insert_extent() libaokun
2024-08-22 2:35 ` [PATCH v2 15/25] ext4: get rid of ppath in ext4_split_extent_at() libaokun
2024-08-22 2:35 ` [PATCH v2 16/25] ext4: get rid of ppath in ext4_force_split_extent_at() libaokun
2024-08-22 2:35 ` [PATCH v2 17/25] ext4: get rid of ppath in ext4_split_extent() libaokun
2024-08-22 2:35 ` [PATCH v2 18/25] ext4: get rid of ppath in ext4_split_convert_extents() libaokun
2024-08-22 2:35 ` [PATCH v2 19/25] ext4: get rid of ppath in ext4_convert_unwritten_extents_endio() libaokun
2024-08-22 2:35 ` [PATCH v2 20/25] ext4: get rid of ppath in ext4_ext_convert_to_initialized() libaokun
2024-08-22 2:35 ` [PATCH v2 21/25] ext4: get rid of ppath in ext4_ext_handle_unwritten_extents() libaokun
2024-08-22 2:35 ` [PATCH v2 22/25] ext4: get rid of ppath in convert_initialized_extent() libaokun
2024-08-22 2:35 ` [PATCH v2 23/25] ext4: refactor ext4_swap_extents() to reuse extents path libaokun
2024-08-22 2:35 ` [PATCH v2 24/25] ext4: make some fast commit functions " libaokun
2024-08-22 2:35 ` [PATCH v2 25/25] ext4: save unnecessary indentation in ext4_ext_create_new_leaf() libaokun
2024-08-27 17:16 ` Jan Kara
2024-09-05 14:53 ` [PATCH v2 00/25] ext4: some bugfixes and cleanups for ext4 extents path 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