| From 1322181170bb01bce3c228b82ae3d5c6b793164f Mon Sep 17 00:00:00 2001 |
| From: Luo Meng <luomeng12@huawei.com> |
| Date: Tue, 20 Oct 2020 09:36:31 +0800 |
| Subject: ext4: fix invalid inode checksum |
| |
| From: Luo Meng <luomeng12@huawei.com> |
| |
| commit 1322181170bb01bce3c228b82ae3d5c6b793164f upstream. |
| |
| During the stability test, there are some errors: |
| ext4_lookup:1590: inode #6967: comm fsstress: iget: checksum invalid. |
| |
| If the inode->i_iblocks too big and doesn't set huge file flag, checksum |
| will not be recalculated when update the inode information to it's buffer. |
| If other inode marks the buffer dirty, then the inconsistent inode will |
| be flushed to disk. |
| |
| Fix this problem by checking i_blocks in advance. |
| |
| Cc: stable@kernel.org |
| Signed-off-by: Luo Meng <luomeng12@huawei.com> |
| Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> |
| Link: https://lore.kernel.org/r/20201020013631.3796673-1-luomeng12@huawei.com |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/ext4/inode.c | 11 ++++++----- |
| 1 file changed, 6 insertions(+), 5 deletions(-) |
| |
| --- a/fs/ext4/inode.c |
| +++ b/fs/ext4/inode.c |
| @@ -4982,6 +4982,12 @@ static int ext4_do_update_inode(handle_t |
| if (ext4_test_inode_state(inode, EXT4_STATE_NEW)) |
| memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size); |
| |
| + err = ext4_inode_blocks_set(handle, raw_inode, ei); |
| + if (err) { |
| + spin_unlock(&ei->i_raw_lock); |
| + goto out_brelse; |
| + } |
| + |
| raw_inode->i_mode = cpu_to_le16(inode->i_mode); |
| i_uid = i_uid_read(inode); |
| i_gid = i_gid_read(inode); |
| @@ -5015,11 +5021,6 @@ static int ext4_do_update_inode(handle_t |
| EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode); |
| EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode); |
| |
| - err = ext4_inode_blocks_set(handle, raw_inode, ei); |
| - if (err) { |
| - spin_unlock(&ei->i_raw_lock); |
| - goto out_brelse; |
| - } |
| raw_inode->i_dtime = cpu_to_le32(ei->i_dtime); |
| raw_inode->i_flags = cpu_to_le32(ei->i_flags & 0xFFFFFFFF); |
| if (likely(!test_opt2(inode->i_sb, HURD_COMPAT))) |