Skip to content

Commit 0f2f87d

Browse files
zhangyi089tytso
authored andcommitted
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 <[email protected]> Reviewed-by: Theodore Ts'o <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 9c6e071 commit 0f2f87d

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

fs/ext4/extents.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,25 @@ int ext4_datasem_ensure_credits(handle_t *handle, struct inode *inode,
136136
static int ext4_ext_get_access(handle_t *handle, struct inode *inode,
137137
struct ext4_ext_path *path)
138138
{
139+
int err = 0;
140+
139141
if (path->p_bh) {
140142
/* path points to block */
141143
BUFFER_TRACE(path->p_bh, "get_write_access");
142-
return ext4_journal_get_write_access(handle, inode->i_sb,
143-
path->p_bh, EXT4_JTR_NONE);
144+
err = ext4_journal_get_write_access(handle, inode->i_sb,
145+
path->p_bh, EXT4_JTR_NONE);
146+
/*
147+
* The extent buffer's verified bit will be set again in
148+
* __ext4_ext_dirty(). We could leave an inconsistent
149+
* buffer if the extents updating procudure break off du
150+
* to some error happens, force to check it again.
151+
*/
152+
if (!err)
153+
clear_buffer_verified(path->p_bh);
144154
}
145155
/* path points to leaf/index in inode body */
146156
/* we use in-core data, no need to protect them */
147-
return 0;
157+
return err;
148158
}
149159

150160
/*
@@ -165,6 +175,9 @@ static int __ext4_ext_dirty(const char *where, unsigned int line,
165175
/* path points to block */
166176
err = __ext4_handle_dirty_metadata(where, line, handle,
167177
inode, path->p_bh);
178+
/* Extents updating done, re-set verified flag */
179+
if (!err)
180+
set_buffer_verified(path->p_bh);
168181
} else {
169182
/* path points to leaf/index in inode body */
170183
err = ext4_mark_inode_dirty(handle, inode);

0 commit comments

Comments
 (0)