Skip to content

Commit 8cc3e39

Browse files
chaseyupundiramit
authored andcommitted
f2fs: fix fdatasync
commit 281518c694a5228d6c46fac83529fb3e2c331281 upstream. For below two cases, we can't guarantee data consistence: a) 1. xfs_io "pwrite 0 4195328" "fsync" 2. xfs_io "pwrite 4195328 1024" "fdatasync" 3. godown 4. umount & mount --> isize we updated before fdatasync won't be recovered b) 1. xfs_io "pwrite -S 0xcc 0 4202496" "fsync" 2. xfs_io "fpunch 4194304 4096" "fdatasync" 3. godown 4. umount & mount --> dnode we punched before fdatasync won't be recovered The reason is that normally fdatasync won't be aware of modification of metadata in file, e.g. isize changing, dnode updating, so in ->fsync we will skip flushing node pages for above cases, result in making fdatasynced file being lost during recovery. Currently we have introduced DIRTY_META global list in sbi for tracking dirty inode selectively, so in fdatasync we can choose to flush nodes depend on dirty state of current inode in the list. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent c2cec7e commit 8cc3e39

2 files changed

Lines changed: 11 additions & 2 deletions

File tree

fs/f2fs/f2fs.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1763,8 +1763,17 @@ static inline void f2fs_i_size_write(struct inode *inode, loff_t i_size)
17631763
set_inode_flag(inode, FI_AUTO_RECOVER);
17641764
}
17651765

1766-
static inline bool f2fs_skip_inode_update(struct inode *inode)
1766+
static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
17671767
{
1768+
if (dsync) {
1769+
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
1770+
bool ret;
1771+
1772+
spin_lock(&sbi->inode_lock[DIRTY_META]);
1773+
ret = list_empty(&F2FS_I(inode)->gdirty_list);
1774+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
1775+
return ret;
1776+
}
17681777
if (!is_inode_flag_set(inode, FI_AUTO_RECOVER))
17691778
return false;
17701779
return F2FS_I(inode)->last_disk_size == i_size_read(inode);

fs/f2fs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
209209
}
210210

211211
/* if the inode is dirty, let's recover all the time */
212-
if (!datasync && !f2fs_skip_inode_update(inode)) {
212+
if (!f2fs_skip_inode_update(inode, datasync)) {
213213
f2fs_write_inode(inode, NULL);
214214
goto go_write;
215215
}

0 commit comments

Comments
 (0)