| From a3dfa1925ca8b6accf748aff585ae5979130175f Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 19 Sep 2018 15:28:40 -0700 |
| Subject: f2fs: update i_size after DIO completion |
| |
| From: Jaegeuk Kim <jaegeuk@kernel.org> |
| |
| [ Upstream commit 0a4daae5ffea39f5015334e4d18a6a80b447cae4 ] |
| |
| This is related to |
| ee70daaba82d ("xfs: update i_size after unwritten conversion in dio completion") |
| |
| If we update i_size during dio_write, dio_read can read out stale data, which |
| breaks xfstests/465. |
| |
| Reviewed-by: Chao Yu <yuchao0@huawei.com> |
| Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/f2fs/data.c | 15 +++++++-------- |
| fs/f2fs/f2fs.h | 1 + |
| 2 files changed, 8 insertions(+), 8 deletions(-) |
| |
| diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c |
| index b4a634da1372b..3a2fd66769660 100644 |
| --- a/fs/f2fs/data.c |
| +++ b/fs/f2fs/data.c |
| @@ -889,7 +889,6 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type) |
| struct f2fs_summary sum; |
| struct node_info ni; |
| block_t old_blkaddr; |
| - pgoff_t fofs; |
| blkcnt_t count = 1; |
| int err; |
| |
| @@ -918,12 +917,10 @@ alloc: |
| old_blkaddr, old_blkaddr); |
| f2fs_set_data_blkaddr(dn); |
| |
| - /* update i_size */ |
| - fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) + |
| - dn->ofs_in_node; |
| - if (i_size_read(dn->inode) < ((loff_t)(fofs + 1) << PAGE_SHIFT)) |
| - f2fs_i_size_write(dn->inode, |
| - ((loff_t)(fofs + 1) << PAGE_SHIFT)); |
| + /* |
| + * i_size will be updated by direct_IO. Otherwise, we'll get stale |
| + * data from unwritten block via dio_read. |
| + */ |
| return 0; |
| } |
| |
| @@ -1089,6 +1086,8 @@ next_block: |
| last_ofs_in_node = dn.ofs_in_node; |
| } |
| } else { |
| + WARN_ON(flag != F2FS_GET_BLOCK_PRE_DIO && |
| + flag != F2FS_GET_BLOCK_DIO); |
| err = __allocate_data_block(&dn, |
| map->m_seg_type); |
| if (!err) |
| @@ -1268,7 +1267,7 @@ static int get_data_block_dio(struct inode *inode, sector_t iblock, |
| struct buffer_head *bh_result, int create) |
| { |
| return __get_data_block(inode, iblock, bh_result, create, |
| - F2FS_GET_BLOCK_DEFAULT, NULL, |
| + F2FS_GET_BLOCK_DIO, NULL, |
| f2fs_rw_hint_to_seg_type( |
| inode->i_write_hint)); |
| } |
| diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h |
| index 6d361c8c61306..2dc49a5419070 100644 |
| --- a/fs/f2fs/f2fs.h |
| +++ b/fs/f2fs/f2fs.h |
| @@ -600,6 +600,7 @@ enum { |
| F2FS_GET_BLOCK_DEFAULT, |
| F2FS_GET_BLOCK_FIEMAP, |
| F2FS_GET_BLOCK_BMAP, |
| + F2FS_GET_BLOCK_DIO, |
| F2FS_GET_BLOCK_PRE_DIO, |
| F2FS_GET_BLOCK_PRE_AIO, |
| F2FS_GET_BLOCK_PRECACHE, |
| -- |
| 2.20.1 |
| |