forked from Minki/linux
ext4: recover csum seed of tmp_inode after migrating to extents
When migrating to extents, the checksum seed of temporary inode
need to be replaced by inode's, otherwise the inode checksums
will be incorrect when swapping the inodes data.
However, the temporary inode can not match it's checksum to
itself since it has lost it's own checksum seed.
mkfs.ext4 -F /dev/sdc
mount /dev/sdc /mnt/sdc
xfs_io -fc "pwrite 4k 4k" -c "fsync" /mnt/sdc/testfile
chattr -e /mnt/sdc/testfile
chattr +e /mnt/sdc/testfile
umount /dev/sdc
fsck -fn /dev/sdc
========
...
Pass 1: Checking inodes, blocks, and sizes
Inode 13 passes checks, but checksum does not match inode. Fix? no
...
========
The fix is simple, save the checksum seed of temporary inode, and
recover it after migrating to extents.
Fixes: e81c9302a6
("ext4: set csum seed in tmp inode while migrating to extents")
Signed-off-by: Li Lingfeng <lilingfeng3@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20220617062515.2113438-1-lilingfeng3@huawei.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
51ae846cff
commit
07ea7a617d
@ -417,7 +417,7 @@ int ext4_ext_migrate(struct inode *inode)
|
|||||||
struct inode *tmp_inode = NULL;
|
struct inode *tmp_inode = NULL;
|
||||||
struct migrate_struct lb;
|
struct migrate_struct lb;
|
||||||
unsigned long max_entries;
|
unsigned long max_entries;
|
||||||
__u32 goal;
|
__u32 goal, tmp_csum_seed;
|
||||||
uid_t owner[2];
|
uid_t owner[2];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -465,6 +465,7 @@ int ext4_ext_migrate(struct inode *inode)
|
|||||||
* the migration.
|
* the migration.
|
||||||
*/
|
*/
|
||||||
ei = EXT4_I(inode);
|
ei = EXT4_I(inode);
|
||||||
|
tmp_csum_seed = EXT4_I(tmp_inode)->i_csum_seed;
|
||||||
EXT4_I(tmp_inode)->i_csum_seed = ei->i_csum_seed;
|
EXT4_I(tmp_inode)->i_csum_seed = ei->i_csum_seed;
|
||||||
i_size_write(tmp_inode, i_size_read(inode));
|
i_size_write(tmp_inode, i_size_read(inode));
|
||||||
/*
|
/*
|
||||||
@ -575,6 +576,7 @@ err_out:
|
|||||||
* the inode is not visible to user space.
|
* the inode is not visible to user space.
|
||||||
*/
|
*/
|
||||||
tmp_inode->i_blocks = 0;
|
tmp_inode->i_blocks = 0;
|
||||||
|
EXT4_I(tmp_inode)->i_csum_seed = tmp_csum_seed;
|
||||||
|
|
||||||
/* Reset the extent details */
|
/* Reset the extent details */
|
||||||
ext4_ext_tree_init(handle, tmp_inode);
|
ext4_ext_tree_init(handle, tmp_inode);
|
||||||
|
Loading…
Reference in New Issue
Block a user