[PATCH -next v2 1/7] ext4: use reserved metadata blocks when splitting extent on endio

Zhang Yi posted 7 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH -next v2 1/7] ext4: use reserved metadata blocks when splitting extent on endio
Posted by Zhang Yi 1 month, 2 weeks ago
From: Zhang Yi <yi.zhang@huawei.com>

When performing buffered writes, we may need to split and convert an
unwritten extent into a written one during the end I/O process. However,
we do not reserve space specifically for these metadata changes, we only
reserve 2% of space or 4096 blocks. To address this, we use
EXT4_GET_BLOCKS_PRE_IO to potentially split extents in advance and
EXT4_GET_BLOCKS_METADATA_NOFAIL to utilize reserved space if necessary.

These two approaches can reduce the likelihood of running out of space
and losing data. However, these methods are merely best efforts, we
could still run out of space, and there is not much difference between
converting an extent during the writeback process and the end I/O
process, it won't increase the rick of losing data if we postpone the
conversion.

Therefore, also use EXT4_GET_BLOCKS_METADATA_NOFAIL in
ext4_convert_unwritten_extents_endio() to prepare for the buffered I/O
iomap conversion, which may perform extent conversion during the end I/O
process.

Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
---
 fs/ext4/extents.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 27eb2c1df012..e53959120b04 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3794,6 +3794,8 @@ ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
 	 * illegal.
 	 */
 	if (ee_block != map->m_lblk || ee_len > map->m_len) {
+		int flags = EXT4_GET_BLOCKS_CONVERT |
+			    EXT4_GET_BLOCKS_METADATA_NOFAIL;
 #ifdef CONFIG_EXT4_DEBUG
 		ext4_warning(inode->i_sb, "Inode (%ld) finished: extent logical block %llu,"
 			     " len %u; IO logical block %llu, len %u",
@@ -3801,7 +3803,7 @@ ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
 			     (unsigned long long)map->m_lblk, map->m_len);
 #endif
 		path = ext4_split_convert_extents(handle, inode, map, path,
-						EXT4_GET_BLOCKS_CONVERT, NULL);
+						  flags, NULL);
 		if (IS_ERR(path))
 			return path;
 
-- 
2.52.0
Re: [PATCH -next v2 1/7] ext4: use reserved metadata blocks when splitting extent on endio
Posted by Ojaswin Mujoo 1 month, 1 week ago
On Tue, Dec 23, 2025 at 09:17:56AM +0800, Zhang Yi wrote:
> From: Zhang Yi <yi.zhang@huawei.com>
> 
> When performing buffered writes, we may need to split and convert an
> unwritten extent into a written one during the end I/O process. However,
> we do not reserve space specifically for these metadata changes, we only
> reserve 2% of space or 4096 blocks. To address this, we use
> EXT4_GET_BLOCKS_PRE_IO to potentially split extents in advance and
> EXT4_GET_BLOCKS_METADATA_NOFAIL to utilize reserved space if necessary.
> 
> These two approaches can reduce the likelihood of running out of space
> and losing data. However, these methods are merely best efforts, we
> could still run out of space, and there is not much difference between
> converting an extent during the writeback process and the end I/O
> process, it won't increase the rick of losing data if we postpone the
                                ^^^^ risk

Other than the minor typo above, feel free to add:
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>

> conversion.
> 
> Therefore, also use EXT4_GET_BLOCKS_METADATA_NOFAIL in
> ext4_convert_unwritten_extents_endio() to prepare for the buffered I/O
> iomap conversion, which may perform extent conversion during the end I/O
> process.
> 
> Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
> Reviewed-by: Jan Kara <jack@suse.cz>

> ---
>  fs/ext4/extents.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index 27eb2c1df012..e53959120b04 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -3794,6 +3794,8 @@ ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
>  	 * illegal.
>  	 */
>  	if (ee_block != map->m_lblk || ee_len > map->m_len) {
> +		int flags = EXT4_GET_BLOCKS_CONVERT |
> +			    EXT4_GET_BLOCKS_METADATA_NOFAIL;
>  #ifdef CONFIG_EXT4_DEBUG
>  		ext4_warning(inode->i_sb, "Inode (%ld) finished: extent logical block %llu,"
>  			     " len %u; IO logical block %llu, len %u",
> @@ -3801,7 +3803,7 @@ ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
>  			     (unsigned long long)map->m_lblk, map->m_len);
>  #endif
>  		path = ext4_split_convert_extents(handle, inode, map, path,
> -						EXT4_GET_BLOCKS_CONVERT, NULL);
> +						  flags, NULL);
>  		if (IS_ERR(path))
>  			return path;
>  
> -- 
> 2.52.0
>
Re: [PATCH -next v2 1/7] ext4: use reserved metadata blocks when splitting extent on endio
Posted by Zhang Yi 1 month ago
On 1/3/2026 9:42 PM, Ojaswin Mujoo wrote:
> On Tue, Dec 23, 2025 at 09:17:56AM +0800, Zhang Yi wrote:
>> From: Zhang Yi <yi.zhang@huawei.com>
>>
>> When performing buffered writes, we may need to split and convert an
>> unwritten extent into a written one during the end I/O process. However,
>> we do not reserve space specifically for these metadata changes, we only
>> reserve 2% of space or 4096 blocks. To address this, we use
>> EXT4_GET_BLOCKS_PRE_IO to potentially split extents in advance and
>> EXT4_GET_BLOCKS_METADATA_NOFAIL to utilize reserved space if necessary.
>>
>> These two approaches can reduce the likelihood of running out of space
>> and losing data. However, these methods are merely best efforts, we
>> could still run out of space, and there is not much difference between
>> converting an extent during the writeback process and the end I/O
>> process, it won't increase the rick of losing data if we postpone the
>                                 ^^^^ risk
> 
> Other than the minor typo above, feel free to add:
> Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>

Thank you for reviewing this series, I will revise it in v3.

Cheers,
Yi.

> 
>> conversion.
>>
>> Therefore, also use EXT4_GET_BLOCKS_METADATA_NOFAIL in
>> ext4_convert_unwritten_extents_endio() to prepare for the buffered I/O
>> iomap conversion, which may perform extent conversion during the end I/O
>> process.
>>
>> Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
>> Reviewed-by: Jan Kara <jack@suse.cz>
> 
>> ---
>>  fs/ext4/extents.c | 4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
>> index 27eb2c1df012..e53959120b04 100644
>> --- a/fs/ext4/extents.c
>> +++ b/fs/ext4/extents.c
>> @@ -3794,6 +3794,8 @@ ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
>>  	 * illegal.
>>  	 */
>>  	if (ee_block != map->m_lblk || ee_len > map->m_len) {
>> +		int flags = EXT4_GET_BLOCKS_CONVERT |
>> +			    EXT4_GET_BLOCKS_METADATA_NOFAIL;
>>  #ifdef CONFIG_EXT4_DEBUG
>>  		ext4_warning(inode->i_sb, "Inode (%ld) finished: extent logical block %llu,"
>>  			     " len %u; IO logical block %llu, len %u",
>> @@ -3801,7 +3803,7 @@ ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
>>  			     (unsigned long long)map->m_lblk, map->m_len);
>>  #endif
>>  		path = ext4_split_convert_extents(handle, inode, map, path,
>> -						EXT4_GET_BLOCKS_CONVERT, NULL);
>> +						  flags, NULL);
>>  		if (IS_ERR(path))
>>  			return path;
>>  
>> -- 
>> 2.52.0
>>
Re: [PATCH -next v2 1/7] ext4: use reserved metadata blocks when splitting extent on endio
Posted by Baokun Li 1 month, 1 week ago
On 2025-12-23 09:17, Zhang Yi wrote:
> From: Zhang Yi <yi.zhang@huawei.com>
>
> When performing buffered writes, we may need to split and convert an
> unwritten extent into a written one during the end I/O process. However,
> we do not reserve space specifically for these metadata changes, we only
> reserve 2% of space or 4096 blocks. To address this, we use
> EXT4_GET_BLOCKS_PRE_IO to potentially split extents in advance and
> EXT4_GET_BLOCKS_METADATA_NOFAIL to utilize reserved space if necessary.
>
> These two approaches can reduce the likelihood of running out of space
> and losing data. However, these methods are merely best efforts, we
> could still run out of space, and there is not much difference between
> converting an extent during the writeback process and the end I/O
> process, it won't increase the rick of losing data if we postpone the
> conversion.
>
> Therefore, also use EXT4_GET_BLOCKS_METADATA_NOFAIL in
> ext4_convert_unwritten_extents_endio() to prepare for the buffered I/O
> iomap conversion, which may perform extent conversion during the end I/O
> process.
>
> Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
> Reviewed-by: Jan Kara <jack@suse.cz>

Fair point, that is consistent with how
ext4_ext_handle_unwritten_extents() handles it.

Reviewed-by: Baokun Li <libaokun1@huawei.com>

> ---
>  fs/ext4/extents.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index 27eb2c1df012..e53959120b04 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -3794,6 +3794,8 @@ ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
>  	 * illegal.
>  	 */
>  	if (ee_block != map->m_lblk || ee_len > map->m_len) {
> +		int flags = EXT4_GET_BLOCKS_CONVERT |
> +			    EXT4_GET_BLOCKS_METADATA_NOFAIL;
>  #ifdef CONFIG_EXT4_DEBUG
>  		ext4_warning(inode->i_sb, "Inode (%ld) finished: extent logical block %llu,"
>  			     " len %u; IO logical block %llu, len %u",
> @@ -3801,7 +3803,7 @@ ext4_convert_unwritten_extents_endio(handle_t *handle, struct inode *inode,
>  			     (unsigned long long)map->m_lblk, map->m_len);
>  #endif
>  		path = ext4_split_convert_extents(handle, inode, map, path,
> -						EXT4_GET_BLOCKS_CONVERT, NULL);
> +						  flags, NULL);
>  		if (IS_ERR(path))
>  			return path;
>