f2fs: avoid wait if IO end up when do_checkpoint for better performance
authorGu Zheng <guz.fnst@cn.fujitsu.com>
Mon, 14 Oct 2013 10:45:56 +0000 (18:45 +0800)
committerJaegeuk Kim <jaegeuk.kim@samsung.com>
Fri, 18 Oct 2013 00:44:14 +0000 (09:44 +0900)
Previously, do_checkpoint() will call congestion_wait() for waiting the pages
(previous submitted node/meta/data pages) to be written back.
Because congestion_wait() will set a regular period (e.g. HZ / 50 ) for waiting, and
no additional wake up mechanism was introduced if IO ends up before regular period costed.
Yuan Zhong found there is a situation that after the pages have been written back,
but the checkpoint thread still wait for congestion_wait to exit.

So here we store checkpoint task into f2fs_sb when doing checkpoint, it'll wait for IO completes
if there's IO going on, and in the end IO path, wake up checkpoint task when IO ends up.

Thanks to Yuan Zhong's pre work about this problem.

Reported-by: Yuan Zhong <yuan.mark.zhong@samsung.com>
Signed-off-by: Gu Zheng <guz.fnst@cn.fujitsu.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
fs/f2fs/checkpoint.c
fs/f2fs/f2fs.h
fs/f2fs/segment.c

index d80882763ffd94c5a77f9561096d36c0486970a7..2a5999d865b25f9f7d1b7a8631601c3185170f40 100644 (file)
@@ -757,8 +757,15 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        f2fs_put_page(cp_page, 1);
 
        /* wait for previous submitted node/meta pages writeback */
-       while (get_pages(sbi, F2FS_WRITEBACK))
-               congestion_wait(BLK_RW_ASYNC, HZ / 50);
+       sbi->cp_task = current;
+       while (get_pages(sbi, F2FS_WRITEBACK)) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               if (!get_pages(sbi, F2FS_WRITEBACK))
+                       break;
+               io_schedule();
+       }
+       __set_current_state(TASK_RUNNING);
+       sbi->cp_task = NULL;
 
        filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX);
        filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX);
index 308967b7167414caa46b29a108c9d0f65061e19a..171c52fc95bb8d6ef076fe2d3687bc511f721cde 100644 (file)
@@ -362,6 +362,7 @@ struct f2fs_sb_info {
        struct mutex writepages;                /* mutex for writepages() */
        int por_doing;                          /* recovery is doing or not */
        int on_build_free_nids;                 /* build_free_nids is doing */
+       struct task_struct *cp_task;            /* checkpoint task */
 
        /* for orphan inode management */
        struct list_head orphan_inode_list;     /* orphan inode list */
index bd79bbeceb1d73be929bc3dba2319f76f18d885c..3b203597c744faa6f2d34db1bd1806cb9cce699b 100644 (file)
@@ -597,6 +597,10 @@ static void f2fs_end_io_write(struct bio *bio, int err)
 
        if (p->is_sync)
                complete(p->wait);
+
+       if (!get_pages(p->sbi, F2FS_WRITEBACK) && p->sbi->cp_task)
+               wake_up_process(p->sbi->cp_task);
+
        kfree(p);
        bio_put(bio);
 }
This page took 0.02864 seconds and 5 git commands to generate.