mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 06:50:58 +07:00
f2fs: avoid out-of-order execution of atomic writes
We need to flush data writes before flushing last node block writes by using FUA with PREFLUSH. We don't need to guarantee precedent node writes since if those are not written, we can't reach to the last node block when scanning node block chain during roll-forward recovery. Afterwards f2fs_wait_on_page_writeback guarantees all the IO submission to disk, which builds a valid node block chain. Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
faa24895ac
commit
e7c75ab099
@ -278,7 +278,8 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
|
|||||||
flush_out:
|
flush_out:
|
||||||
remove_ino_entry(sbi, ino, UPDATE_INO);
|
remove_ino_entry(sbi, ino, UPDATE_INO);
|
||||||
clear_inode_flag(inode, FI_UPDATE_WRITE);
|
clear_inode_flag(inode, FI_UPDATE_WRITE);
|
||||||
ret = f2fs_issue_flush(sbi);
|
if (!atomic)
|
||||||
|
ret = f2fs_issue_flush(sbi);
|
||||||
f2fs_update_time(sbi, REQ_TIME);
|
f2fs_update_time(sbi, REQ_TIME);
|
||||||
out:
|
out:
|
||||||
trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret);
|
trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret);
|
||||||
|
@ -1318,7 +1318,7 @@ static struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino)
|
|||||||
return last_page;
|
return last_page;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __write_node_page(struct page *page,
|
static int __write_node_page(struct page *page, bool atomic,
|
||||||
struct writeback_control *wbc)
|
struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
struct f2fs_sb_info *sbi = F2FS_P_SB(page);
|
struct f2fs_sb_info *sbi = F2FS_P_SB(page);
|
||||||
@ -1362,6 +1362,9 @@ static int __write_node_page(struct page *page,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (atomic && !test_opt(sbi, NOBARRIER))
|
||||||
|
fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
|
||||||
|
|
||||||
set_page_writeback(page);
|
set_page_writeback(page);
|
||||||
fio.old_blkaddr = ni.blk_addr;
|
fio.old_blkaddr = ni.blk_addr;
|
||||||
write_node_page(nid, &fio);
|
write_node_page(nid, &fio);
|
||||||
@ -1387,7 +1390,7 @@ static int __write_node_page(struct page *page,
|
|||||||
static int f2fs_write_node_page(struct page *page,
|
static int f2fs_write_node_page(struct page *page,
|
||||||
struct writeback_control *wbc)
|
struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
return __write_node_page(page, wbc);
|
return __write_node_page(page, false, wbc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
|
int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
|
||||||
@ -1469,7 +1472,8 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
|
|||||||
if (!clear_page_dirty_for_io(page))
|
if (!clear_page_dirty_for_io(page))
|
||||||
goto continue_unlock;
|
goto continue_unlock;
|
||||||
|
|
||||||
ret = __write_node_page(page, wbc);
|
ret = __write_node_page(page, atomic &&
|
||||||
|
page == last_page, wbc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
f2fs_put_page(last_page, 0);
|
f2fs_put_page(last_page, 0);
|
||||||
|
@ -81,6 +81,7 @@ TRACE_DEFINE_ENUM(CP_DISCARD);
|
|||||||
{ REQ_SYNC | REQ_PRIO, "(SP)" }, \
|
{ REQ_SYNC | REQ_PRIO, "(SP)" }, \
|
||||||
{ REQ_META, "(M)" }, \
|
{ REQ_META, "(M)" }, \
|
||||||
{ REQ_META | REQ_PRIO, "(MP)" }, \
|
{ REQ_META | REQ_PRIO, "(MP)" }, \
|
||||||
|
{ REQ_SYNC | REQ_PREFLUSH , "(SF)" }, \
|
||||||
{ REQ_SYNC | REQ_META | REQ_PRIO, "(SMP)" }, \
|
{ REQ_SYNC | REQ_META | REQ_PRIO, "(SMP)" }, \
|
||||||
{ REQ_PREFLUSH | REQ_META | REQ_PRIO, "(FMP)" }, \
|
{ REQ_PREFLUSH | REQ_META | REQ_PRIO, "(FMP)" }, \
|
||||||
{ 0, " \b" })
|
{ 0, " \b" })
|
||||||
|
Loading…
Reference in New Issue
Block a user