aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2017-02-02 18:18:06 -0800
committerMister Oyster <oysterized@gmail.com>2017-04-13 12:34:50 +0200
commit6b70a1234d7b3e0db8ab557c0b193786357c2ab9 (patch)
tree4f13f9a48e8bc0737a619d84a7b6721f1d3a8572
parent3ad19e69e992427b5aae92a85e59edb286d221cd (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. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Conflicts: include/trace/events/f2fs.h
-rw-r--r--fs/f2fs/file.c3
-rw-r--r--fs/f2fs/node.c10
2 files changed, 9 insertions, 4 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index b09ba511a..ea22c1732 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 82d29eb77..e44a28719 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1335,7 +1335,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);
@@ -1379,6 +1379,9 @@ static int __write_node_page(struct page *page,
return 0;
}
+ if (atomic && !test_opt(sbi, NOBARRIER))
+ fio.op_flags |= WRITE_FLUSH_FUA;
+
set_page_writeback(page);
fio.old_blkaddr = ni.blk_addr;
write_node_page(nid, &fio);
@@ -1404,7 +1407,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,
@@ -1486,7 +1489,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);