aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2018-06-04 11:20:36 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2018-06-04 17:33:20 -0400
commitc29fd0c0e26dacb7a33ad166587059818a94b4e0 (patch)
tree6a25f17833047796fccde3cd7c4e17d35199e640
parentaae764ece6076b0852b95943c40748569c7b8585 (diff)
f2fs: let sync node IO interrupt async one
Although mixed sync/async IOs can have continuous LBA, as they have different IO priority, block IO scheduler will add them into different queues and commit them separately, result in splited IOs which causes wrose performance. This patch gives high priority to synchronous IO of nodes, means that once synchronous flow starts, it can interrupt asynchronous writeback flow of system flusher, so more big IOs can be expected. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fs/f2fs/checkpoint.c2
-rw-r--r--fs/f2fs/data.c9
-rw-r--r--fs/f2fs/f2fs.h2
-rw-r--r--fs/f2fs/file.c2
-rw-r--r--fs/f2fs/gc.c7
-rw-r--r--fs/f2fs/node.c21
-rw-r--r--fs/f2fs/super.c3
7 files changed, 37 insertions, 9 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 40b39db317ea..9624a8f7254b 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -1089,7 +1089,9 @@ retry_flush_nodes:
1089 1089
1090 if (get_pages(sbi, F2FS_DIRTY_NODES)) { 1090 if (get_pages(sbi, F2FS_DIRTY_NODES)) {
1091 up_write(&sbi->node_write); 1091 up_write(&sbi->node_write);
1092 atomic_inc(&sbi->wb_sync_req[NODE]);
1092 err = f2fs_sync_node_pages(sbi, &wbc, false, FS_CP_NODE_IO); 1093 err = f2fs_sync_node_pages(sbi, &wbc, false, FS_CP_NODE_IO);
1094 atomic_dec(&sbi->wb_sync_req[NODE]);
1093 if (err) { 1095 if (err) {
1094 up_write(&sbi->node_change); 1096 up_write(&sbi->node_change);
1095 f2fs_unlock_all(sbi); 1097 f2fs_unlock_all(sbi);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index a2e30c403ef2..8f931d699287 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1933,6 +1933,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
1933 int ret = 0; 1933 int ret = 0;
1934 int done = 0; 1934 int done = 0;
1935 struct pagevec pvec; 1935 struct pagevec pvec;
1936 struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
1936 int nr_pages; 1937 int nr_pages;
1937 pgoff_t uninitialized_var(writeback_index); 1938 pgoff_t uninitialized_var(writeback_index);
1938 pgoff_t index; 1939 pgoff_t index;
@@ -1987,7 +1988,7 @@ retry:
1987 bool submitted = false; 1988 bool submitted = false;
1988 1989
1989 /* give a priority to WB_SYNC threads */ 1990 /* give a priority to WB_SYNC threads */
1990 if (atomic_read(&F2FS_M_SB(mapping)->wb_sync_req) && 1991 if (atomic_read(&sbi->wb_sync_req[DATA]) &&
1991 wbc->sync_mode == WB_SYNC_NONE) { 1992 wbc->sync_mode == WB_SYNC_NONE) {
1992 done = 1; 1993 done = 1;
1993 break; 1994 break;
@@ -2107,8 +2108,8 @@ static int __f2fs_write_data_pages(struct address_space *mapping,
2107 2108
2108 /* to avoid spliting IOs due to mixed WB_SYNC_ALL and WB_SYNC_NONE */ 2109 /* to avoid spliting IOs due to mixed WB_SYNC_ALL and WB_SYNC_NONE */
2109 if (wbc->sync_mode == WB_SYNC_ALL) 2110 if (wbc->sync_mode == WB_SYNC_ALL)
2110 atomic_inc(&sbi->wb_sync_req); 2111 atomic_inc(&sbi->wb_sync_req[DATA]);
2111 else if (atomic_read(&sbi->wb_sync_req)) 2112 else if (atomic_read(&sbi->wb_sync_req[DATA]))
2112 goto skip_write; 2113 goto skip_write;
2113 2114
2114 blk_start_plug(&plug); 2115 blk_start_plug(&plug);
@@ -2116,7 +2117,7 @@ static int __f2fs_write_data_pages(struct address_space *mapping,
2116 blk_finish_plug(&plug); 2117 blk_finish_plug(&plug);
2117 2118
2118 if (wbc->sync_mode == WB_SYNC_ALL) 2119 if (wbc->sync_mode == WB_SYNC_ALL)
2119 atomic_dec(&sbi->wb_sync_req); 2120 atomic_dec(&sbi->wb_sync_req[DATA]);
2120 /* 2121 /*
2121 * if some pages were truncated, we cannot guarantee its mapping->host 2122 * if some pages were truncated, we cannot guarantee its mapping->host
2122 * to detect pending bios. 2123 * to detect pending bios.
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index f167d01443fe..4c09e770a0a3 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1201,7 +1201,7 @@ struct f2fs_sb_info {
1201 struct percpu_counter alloc_valid_block_count; 1201 struct percpu_counter alloc_valid_block_count;
1202 1202
1203 /* writeback control */ 1203 /* writeback control */
1204 atomic_t wb_sync_req; /* count # of WB_SYNC threads */ 1204 atomic_t wb_sync_req[META]; /* count # of WB_SYNC threads */
1205 1205
1206 /* valid inode count */ 1206 /* valid inode count */
1207 struct percpu_counter total_valid_inode_count; 1207 struct percpu_counter total_valid_inode_count;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 74c326442565..16fd50abbf40 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -274,7 +274,9 @@ go_write:
274 goto out; 274 goto out;
275 } 275 }
276sync_nodes: 276sync_nodes:
277 atomic_inc(&sbi->wb_sync_req[NODE]);
277 ret = f2fs_fsync_node_pages(sbi, inode, &wbc, atomic); 278 ret = f2fs_fsync_node_pages(sbi, inode, &wbc, atomic);
279 atomic_dec(&sbi->wb_sync_req[NODE]);
278 if (ret) 280 if (ret)
279 goto out; 281 goto out;
280 282
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 2a97ce7bc91d..9093be6e7a7d 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -473,12 +473,16 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
473 block_t start_addr; 473 block_t start_addr;
474 int off; 474 int off;
475 int phase = 0; 475 int phase = 0;
476 bool fggc = (gc_type == FG_GC);
476 477
477 start_addr = START_BLOCK(sbi, segno); 478 start_addr = START_BLOCK(sbi, segno);
478 479
479next_step: 480next_step:
480 entry = sum; 481 entry = sum;
481 482
483 if (fggc && phase == 2)
484 atomic_inc(&sbi->wb_sync_req[NODE]);
485
482 for (off = 0; off < sbi->blocks_per_seg; off++, entry++) { 486 for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
483 nid_t nid = le32_to_cpu(entry->nid); 487 nid_t nid = le32_to_cpu(entry->nid);
484 struct page *node_page; 488 struct page *node_page;
@@ -525,6 +529,9 @@ next_step:
525 529
526 if (++phase < 3) 530 if (++phase < 3)
527 goto next_step; 531 goto next_step;
532
533 if (fggc)
534 atomic_dec(&sbi->wb_sync_req[NODE]);
528} 535}
529 536
530/* 537/*
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 64ad5466887f..47d0e64a95a8 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1596,21 +1596,28 @@ int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
1596 int step = 0; 1596 int step = 0;
1597 int nwritten = 0; 1597 int nwritten = 0;
1598 int ret = 0; 1598 int ret = 0;
1599 int nr_pages; 1599 int nr_pages, done = 0;
1600 1600
1601 pagevec_init(&pvec); 1601 pagevec_init(&pvec);
1602 1602
1603next_step: 1603next_step:
1604 index = 0; 1604 index = 0;
1605 1605
1606 while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, 1606 while (!done && (nr_pages = pagevec_lookup_tag(&pvec,
1607 PAGECACHE_TAG_DIRTY))) { 1607 NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY))) {
1608 int i; 1608 int i;
1609 1609
1610 for (i = 0; i < nr_pages; i++) { 1610 for (i = 0; i < nr_pages; i++) {
1611 struct page *page = pvec.pages[i]; 1611 struct page *page = pvec.pages[i];
1612 bool submitted = false; 1612 bool submitted = false;
1613 1613
1614 /* give a priority to WB_SYNC threads */
1615 if (atomic_read(&sbi->wb_sync_req[NODE]) &&
1616 wbc->sync_mode == WB_SYNC_NONE) {
1617 done = 1;
1618 break;
1619 }
1620
1614 /* 1621 /*
1615 * flushing sequence with step: 1622 * flushing sequence with step:
1616 * 0. indirect nodes 1623 * 0. indirect nodes
@@ -1738,6 +1745,11 @@ static int f2fs_write_node_pages(struct address_space *mapping,
1738 if (get_pages(sbi, F2FS_DIRTY_NODES) < nr_pages_to_skip(sbi, NODE)) 1745 if (get_pages(sbi, F2FS_DIRTY_NODES) < nr_pages_to_skip(sbi, NODE))
1739 goto skip_write; 1746 goto skip_write;
1740 1747
1748 if (wbc->sync_mode == WB_SYNC_ALL)
1749 atomic_inc(&sbi->wb_sync_req[NODE]);
1750 else if (atomic_read(&sbi->wb_sync_req[NODE]))
1751 goto skip_write;
1752
1741 trace_f2fs_writepages(mapping->host, wbc, NODE); 1753 trace_f2fs_writepages(mapping->host, wbc, NODE);
1742 1754
1743 diff = nr_pages_to_write(sbi, NODE, wbc); 1755 diff = nr_pages_to_write(sbi, NODE, wbc);
@@ -1745,6 +1757,9 @@ static int f2fs_write_node_pages(struct address_space *mapping,
1745 f2fs_sync_node_pages(sbi, wbc, true, FS_NODE_IO); 1757 f2fs_sync_node_pages(sbi, wbc, true, FS_NODE_IO);
1746 blk_finish_plug(&plug); 1758 blk_finish_plug(&plug);
1747 wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff); 1759 wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff);
1760
1761 if (wbc->sync_mode == WB_SYNC_ALL)
1762 atomic_dec(&sbi->wb_sync_req[NODE]);
1748 return 0; 1763 return 0;
1749 1764
1750skip_write: 1765skip_write:
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 25863cec143a..73d7d7e51a61 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2362,7 +2362,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
2362 for (i = 0; i < NR_COUNT_TYPE; i++) 2362 for (i = 0; i < NR_COUNT_TYPE; i++)
2363 atomic_set(&sbi->nr_pages[i], 0); 2363 atomic_set(&sbi->nr_pages[i], 0);
2364 2364
2365 atomic_set(&sbi->wb_sync_req, 0); 2365 for (i = 0; i < META; i++)
2366 atomic_set(&sbi->wb_sync_req[i], 0);
2366 2367
2367 INIT_LIST_HEAD(&sbi->s_list); 2368 INIT_LIST_HEAD(&sbi->s_list);
2368 mutex_init(&sbi->umount_mutex); 2369 mutex_init(&sbi->umount_mutex);