Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b71fc079 authored by Jan Kara's avatar Jan Kara Committed by Theodore Ts'o
Browse files

ext4: fix fdatasync() for files with only i_size changes



Code tracking when transaction needs to be committed on fdatasync(2) forgets
to handle a situation when only inode's i_size is changed. Thus in such
situations fdatasync(2) doesn't force transaction with new i_size to disk
and that can result in wrong i_size after a crash.

Fix the issue by updating inode's i_datasync_tid whenever its size is
updated.

CC: <stable@vger.kernel.org> # >= 2.6.32
Reported-by: default avatarKristian Nielsen <knielsen@knielsen-hq.org>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 6a08f447
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -4054,6 +4054,7 @@ static int ext4_do_update_inode(handle_t *handle,
	struct ext4_inode_info *ei = EXT4_I(inode);
	struct buffer_head *bh = iloc->bh;
	int err = 0, rc, block;
	int need_datasync = 0;
	uid_t i_uid;
	gid_t i_gid;

@@ -4104,7 +4105,10 @@ static int ext4_do_update_inode(handle_t *handle,
		raw_inode->i_file_acl_high =
			cpu_to_le16(ei->i_file_acl >> 32);
	raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl);
	if (ei->i_disksize != ext4_isize(raw_inode)) {
		ext4_isize_set(raw_inode, ei->i_disksize);
		need_datasync = 1;
	}
	if (ei->i_disksize > 0x7fffffffULL) {
		struct super_block *sb = inode->i_sb;
		if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
@@ -4157,7 +4161,7 @@ static int ext4_do_update_inode(handle_t *handle,
		err = rc;
	ext4_clear_inode_state(inode, EXT4_STATE_NEW);

	ext4_update_inode_fsync_trans(handle, inode, 0);
	ext4_update_inode_fsync_trans(handle, inode, need_datasync);
out_brelse:
	brelse(bh);
	ext4_std_error(inode->i_sb, err);