[Devel] [PATCH RHEL7 COMMIT] ms/ext4: prevent partial update of the extent blocks

Konstantin Khorenko khorenko at virtuozzo.com
Mon Jun 20 21:04:06 MSK 2022


The commit is pushed to "branch-rh7-3.10.0-1160.62.1.vz7.187.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.62.1.vz7.187.5
------>
commit 47e53e93deb673b4b3e756e90b4b5a54448cccd0
Author: Zhang Yi <yi.zhang at huawei.com>
Date:   Tue Jun 14 17:53:32 2022 +0300

    ms/ext4: prevent partial update of the extent blocks
    
    In the most error path of current extents updating operations are not
    roll back partial updates properly when some bad things happens(.e.g in
    ext4_ext_insert_extent()). So we may get an inconsistent extents tree
    if journal has been aborted due to IO error, which may probability lead
    to BUGON later when we accessing these extent entries in errors=continue
    mode. This patch drop extent buffer's verify flag before updatng the
    contents in ext4_ext_get_access(), and reset it after updating in
    __ext4_ext_dirty(). After this patch we could force to check the extent
    buffer if extents tree updating was break off, make sure the extents are
    consistent.
    
    Signed-off-by: Zhang Yi <yi.zhang at huawei.com>
    Reviewed-by: Theodore Ts'o <tytso at mit.edu>
    Link: https://lore.kernel.org/r/20210908120850.4012324-4-yi.zhang@huawei.com
    Signed-off-by: Theodore Ts'o <tytso at mit.edu>
    
    (cherry-picked from ms commit 0f2f87d51aebcf71a709b52f661d681594c7dffa)
    https://jira.sw.ru/browse/PSBM-139452
    Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 fs/ext4/extents.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 0b6ed085f3d9..52835f176015 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -140,14 +140,24 @@ static int ext4_ext_truncate_extend_restart(handle_t *handle,
 static int ext4_ext_get_access(handle_t *handle, struct inode *inode,
 				struct ext4_ext_path *path)
 {
+	int err = 0;
+
 	if (path->p_bh) {
 		/* path points to block */
 		BUFFER_TRACE(path->p_bh, "get_write_access");
-		return ext4_journal_get_write_access(handle, path->p_bh);
+		err = ext4_journal_get_write_access(handle, path->p_bh);
+		/*
+		 * The extent buffer's verified bit will be set again in
+		 * __ext4_ext_dirty(). We could leave an inconsistent
+		 * buffer if the extents updating procudure break off du
+		 * to some error happens, force to check it again.
+		 */
+		if (!err)
+			clear_buffer_verified(path->p_bh);
 	}
 	/* path points to leaf/index in inode body */
 	/* we use in-core data, no need to protect them */
-	return 0;
+	return err;
 }
 
 /*
@@ -167,6 +177,9 @@ int __ext4_ext_dirty(const char *where, unsigned int line, handle_t *handle,
 		/* path points to block */
 		err = __ext4_handle_dirty_metadata(where, line, handle,
 						   inode, path->p_bh);
+		/* Extents updating done, re-set verified flag */
+		if (!err)
+			set_buffer_verified(path->p_bh);
 	} else {
 		/* path points to leaf/index in inode body */
 		err = ext4_mark_inode_dirty(handle, inode);


More information about the Devel mailing list