aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorGu Zheng <guz.fnst@cn.fujitsu.com>2013-10-14 06:45:56 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-10-17 20:44:14 -0400
commite234088758fca3a669ebb1a02d8bf7bf60f0e4ff (patch)
tree32f6816d20e5baf06ee7df7b40e7de8c50918167 /fs
parent9076a75f8e0f23ab64e2f34eb6be144e81f00a3e (diff)
f2fs: avoid wait if IO end up when do_checkpoint for better performance
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/f2fs/checkpoint.c11
-rw-r--r--fs/f2fs/f2fs.h1
-rw-r--r--fs/f2fs/segment.c4
3 files changed, 14 insertions, 2 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index d80882763ffd..2a5999d865b2 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -757,8 +757,15 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
757 f2fs_put_page(cp_page, 1); 757 f2fs_put_page(cp_page, 1);
758 758
759 /* wait for previous submitted node/meta pages writeback */ 759 /* wait for previous submitted node/meta pages writeback */
760 while (get_pages(sbi, F2FS_WRITEBACK)) 760 sbi->cp_task = current;
761 congestion_wait(BLK_RW_ASYNC, HZ / 50); 761 while (get_pages(sbi, F2FS_WRITEBACK)) {
762 set_current_state(TASK_UNINTERRUPTIBLE);
763 if (!get_pages(sbi, F2FS_WRITEBACK))
764 break;
765 io_schedule();
766 }
767 __set_current_state(TASK_RUNNING);
768 sbi->cp_task = NULL;
762 769
763 filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX); 770 filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX);
764 filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX); 771 filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 308967b71674..171c52fc95bb 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -362,6 +362,7 @@ struct f2fs_sb_info {
362 struct mutex writepages; /* mutex for writepages() */ 362 struct mutex writepages; /* mutex for writepages() */
363 int por_doing; /* recovery is doing or not */ 363 int por_doing; /* recovery is doing or not */
364 int on_build_free_nids; /* build_free_nids is doing */ 364 int on_build_free_nids; /* build_free_nids is doing */
365 struct task_struct *cp_task; /* checkpoint task */
365 366
366 /* for orphan inode management */ 367 /* for orphan inode management */
367 struct list_head orphan_inode_list; /* orphan inode list */ 368 struct list_head orphan_inode_list; /* orphan inode list */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index bd79bbeceb1d..3b203597c744 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -597,6 +597,10 @@ static void f2fs_end_io_write(struct bio *bio, int err)
597 597
598 if (p->is_sync) 598 if (p->is_sync)
599 complete(p->wait); 599 complete(p->wait);
600
601 if (!get_pages(p->sbi, F2FS_WRITEBACK) && p->sbi->cp_task)
602 wake_up_process(p->sbi->cp_task);
603
600 kfree(p); 604 kfree(p);
601 bio_put(bio); 605 bio_put(bio);
602} 606}