aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaegeuk Kim2017-02-02 18:18:06 -0800
committerJaegeuk Kim2017-02-23 10:10:35 -0800
commite7c75ab099c8c8d4616c2ac10517e86a88b368d1 (patch)
treee19af673d391917611a269fe286418eba871b72d
parentfaa24895acfd49cb61055b762e39ee6a5452a389 (diff)
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>
-rw-r--r--fs/f2fs/file.c3
-rw-r--r--fs/f2fs/node.c10
-rw-r--r--include/trace/events/f2fs.h1
3 files changed, 10 insertions, 4 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 9c0f469cde13..a3808c49e326 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -278,7 +278,8 @@ sync_nodes:
flush_out:
remove_ino_entry(sbi, ino, UPDATE_INO);
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);
out:
trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 0cb6e86bcf28..6a86f398aeac 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1318,7 +1318,7 @@ continue_unlock:
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 f2fs_sb_info *sbi = F2FS_P_SB(page);
@@ -1362,6 +1362,9 @@ static int __write_node_page(struct page *page,
return 0;
}
+ if (atomic && !test_opt(sbi, NOBARRIER))
+ fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
+
set_page_writeback(page);
fio.old_blkaddr = ni.blk_addr;
write_node_page(nid, &fio);
@@ -1387,7 +1390,7 @@ redirty_out:
static int f2fs_write_node_page(struct page *page,
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,
@@ -1469,7 +1472,8 @@ continue_unlock:
if (!clear_page_dirty_for_io(page))
goto continue_unlock;
- ret = __write_node_page(page, wbc);
+ ret = __write_node_page(page, atomic &&
+ page == last_page, wbc);
if (ret) {
unlock_page(page);
f2fs_put_page(last_page, 0);
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index 04c527410ecc..82236792b50c 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -81,6 +81,7 @@ TRACE_DEFINE_ENUM(CP_DISCARD);
{ REQ_SYNC | REQ_PRIO, "(SP)" }, \
{ REQ_META, "(M)" }, \
{ REQ_META | REQ_PRIO, "(MP)" }, \
+ { REQ_SYNC | REQ_PREFLUSH , "(SF)" }, \
{ REQ_SYNC | REQ_META | REQ_PRIO, "(SMP)" }, \
{ REQ_PREFLUSH | REQ_META | REQ_PRIO, "(FMP)" }, \
{ 0, " \b" })