f2fs: update i_size after DIO completion
This is related to
ee70daaba8
("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>
This commit is contained in:
parent
d83d0f5ba8
commit
0a4daae5ff
@ -881,7 +881,6 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
|
|||||||
struct f2fs_summary sum;
|
struct f2fs_summary sum;
|
||||||
struct node_info ni;
|
struct node_info ni;
|
||||||
block_t old_blkaddr;
|
block_t old_blkaddr;
|
||||||
pgoff_t fofs;
|
|
||||||
blkcnt_t count = 1;
|
blkcnt_t count = 1;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -910,12 +909,10 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
|
|||||||
old_blkaddr, old_blkaddr);
|
old_blkaddr, old_blkaddr);
|
||||||
f2fs_set_data_blkaddr(dn);
|
f2fs_set_data_blkaddr(dn);
|
||||||
|
|
||||||
/* update i_size */
|
/*
|
||||||
fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) +
|
* i_size will be updated by direct_IO. Otherwise, we'll get stale
|
||||||
dn->ofs_in_node;
|
* data from unwritten block via dio_read.
|
||||||
if (i_size_read(dn->inode) < ((loff_t)(fofs + 1) << PAGE_SHIFT))
|
*/
|
||||||
f2fs_i_size_write(dn->inode,
|
|
||||||
((loff_t)(fofs + 1) << PAGE_SHIFT));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1081,6 +1078,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
|
|||||||
last_ofs_in_node = dn.ofs_in_node;
|
last_ofs_in_node = dn.ofs_in_node;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
WARN_ON(flag != F2FS_GET_BLOCK_PRE_DIO &&
|
||||||
|
flag != F2FS_GET_BLOCK_DIO);
|
||||||
err = __allocate_data_block(&dn,
|
err = __allocate_data_block(&dn,
|
||||||
map->m_seg_type);
|
map->m_seg_type);
|
||||||
if (!err)
|
if (!err)
|
||||||
@ -1260,7 +1259,7 @@ static int get_data_block_dio(struct inode *inode, sector_t iblock,
|
|||||||
struct buffer_head *bh_result, int create)
|
struct buffer_head *bh_result, int create)
|
||||||
{
|
{
|
||||||
return __get_data_block(inode, iblock, bh_result, 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(
|
f2fs_rw_hint_to_seg_type(
|
||||||
inode->i_write_hint));
|
inode->i_write_hint));
|
||||||
}
|
}
|
||||||
|
@ -599,6 +599,7 @@ enum {
|
|||||||
F2FS_GET_BLOCK_DEFAULT,
|
F2FS_GET_BLOCK_DEFAULT,
|
||||||
F2FS_GET_BLOCK_FIEMAP,
|
F2FS_GET_BLOCK_FIEMAP,
|
||||||
F2FS_GET_BLOCK_BMAP,
|
F2FS_GET_BLOCK_BMAP,
|
||||||
|
F2FS_GET_BLOCK_DIO,
|
||||||
F2FS_GET_BLOCK_PRE_DIO,
|
F2FS_GET_BLOCK_PRE_DIO,
|
||||||
F2FS_GET_BLOCK_PRE_AIO,
|
F2FS_GET_BLOCK_PRE_AIO,
|
||||||
F2FS_GET_BLOCK_PRECACHE,
|
F2FS_GET_BLOCK_PRECACHE,
|
||||||
|
Loading…
Reference in New Issue
Block a user