diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-09-11 05:51:35 +0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-09-11 05:51:35 +0800 |
commit | 1b0a9069dec4168b431755ca89c6999d7c46a7de (patch) | |
tree | e39c5d34098071504a97740efa614fe404fcff4c /fs/ext3/inode.c | |
parent | 6562271ae4ffb25a193995133c3d6d3b0b4f6730 (diff) | |
parent | 9c2fc0de1a6e638fe58c354a463f544f42a90a09 (diff) | |
download | lwn-1b0a9069dec4168b431755ca89c6999d7c46a7de.tar.gz lwn-1b0a9069dec4168b431755ca89c6999d7c46a7de.zip |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull UDF and ext3 fixes from Jan Kara:
"One UDF data corruption fix and one ext3 fix where we didn't write
everything to disk on fsync in one corner case."
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
udf: Fix data corruption for files in ICB
ext3: Fix fdatasync() for files with only i_size changes
Diffstat (limited to 'fs/ext3/inode.c')
-rw-r--r-- | fs/ext3/inode.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index a07597307fd1..ff574b4e345e 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -3072,6 +3072,8 @@ static int ext3_do_update_inode(handle_t *handle, struct ext3_inode_info *ei = EXT3_I(inode); struct buffer_head *bh = iloc->bh; int err = 0, rc, block; + int need_datasync = 0; + __le32 disksize; uid_t i_uid; gid_t i_gid; @@ -3113,7 +3115,11 @@ again: raw_inode->i_gid_high = 0; } raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); - raw_inode->i_size = cpu_to_le32(ei->i_disksize); + disksize = cpu_to_le32(ei->i_disksize); + if (disksize != raw_inode->i_size) { + need_datasync = 1; + raw_inode->i_size = disksize; + } raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec); raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec); raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); @@ -3129,8 +3135,11 @@ again: if (!S_ISREG(inode->i_mode)) { raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl); } else { - raw_inode->i_size_high = - cpu_to_le32(ei->i_disksize >> 32); + disksize = cpu_to_le32(ei->i_disksize >> 32); + if (disksize != raw_inode->i_size_high) { + raw_inode->i_size_high = disksize; + need_datasync = 1; + } if (ei->i_disksize > 0x7fffffffULL) { struct super_block *sb = inode->i_sb; if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, @@ -3183,6 +3192,8 @@ again: ext3_clear_inode_state(inode, EXT3_STATE_NEW); atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid); + if (need_datasync) + atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid); out_brelse: brelse (bh); ext3_std_error(inode->i_sb, err); |