f2fs: avoid out-of-order execution of atomic writes
authorJaegeuk Kim <jaegeuk@kernel.org>
Fri, 3 Feb 2017 02:18:06 +0000 (18:18 -0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Thu, 23 Feb 2017 18:10:35 +0000 (10:10 -0800)
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>
fs/f2fs/file.c
fs/f2fs/node.c
include/trace/events/f2fs.h

index 9c0f469cde133ed9297947c6086a78d098491801..a3808c49e326537d3ee07f489a8dea904aeed9d1 100644 (file)
@@ -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);
index 0cb6e86bcf28a33c152e55cba35aa331ab1d21c4..6a86f398aeac675fe38cd56bca107e3040183b57 100644 (file)
@@ -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);
index 04c527410ecceb68a208841a055f16dbd8d02db7..82236792b50cb6f356224f21cdb4ed56d71cb077 100644 (file)
@@ -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" })