]> Git Repo - linux.git/commitdiff
f2fs: let sync node IO interrupt async one
authorChao Yu <[email protected]>
Mon, 4 Jun 2018 15:20:36 +0000 (23:20 +0800)
committerJaegeuk Kim <[email protected]>
Mon, 4 Jun 2018 21:33:20 +0000 (14:33 -0700)
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 <[email protected]>
Signed-off-by: Jaegeuk Kim <[email protected]>
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/node.c
fs/f2fs/super.c

index 40b39db317ea5c192c9cb0375bb3a101bd81f99f..9624a8f7254b002bc23c674471f427ab28a2d9df 100644 (file)
@@ -1089,7 +1089,9 @@ retry_flush_nodes:
 
        if (get_pages(sbi, F2FS_DIRTY_NODES)) {
                up_write(&sbi->node_write);
+               atomic_inc(&sbi->wb_sync_req[NODE]);
                err = f2fs_sync_node_pages(sbi, &wbc, false, FS_CP_NODE_IO);
+               atomic_dec(&sbi->wb_sync_req[NODE]);
                if (err) {
                        up_write(&sbi->node_change);
                        f2fs_unlock_all(sbi);
index a2e30c403ef2b1789f7ae939b7189378f1ed383d..8f931d699287af894e0101f7aedd4f4f2ef75d72 100644 (file)
@@ -1933,6 +1933,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
        int ret = 0;
        int done = 0;
        struct pagevec pvec;
+       struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
        int nr_pages;
        pgoff_t uninitialized_var(writeback_index);
        pgoff_t index;
@@ -1987,7 +1988,7 @@ retry:
                        bool submitted = false;
 
                        /* give a priority to WB_SYNC threads */
-                       if (atomic_read(&F2FS_M_SB(mapping)->wb_sync_req) &&
+                       if (atomic_read(&sbi->wb_sync_req[DATA]) &&
                                        wbc->sync_mode == WB_SYNC_NONE) {
                                done = 1;
                                break;
@@ -2107,8 +2108,8 @@ static int __f2fs_write_data_pages(struct address_space *mapping,
 
        /* to avoid spliting IOs due to mixed WB_SYNC_ALL and WB_SYNC_NONE */
        if (wbc->sync_mode == WB_SYNC_ALL)
-               atomic_inc(&sbi->wb_sync_req);
-       else if (atomic_read(&sbi->wb_sync_req))
+               atomic_inc(&sbi->wb_sync_req[DATA]);
+       else if (atomic_read(&sbi->wb_sync_req[DATA]))
                goto skip_write;
 
        blk_start_plug(&plug);
@@ -2116,7 +2117,7 @@ static int __f2fs_write_data_pages(struct address_space *mapping,
        blk_finish_plug(&plug);
 
        if (wbc->sync_mode == WB_SYNC_ALL)
-               atomic_dec(&sbi->wb_sync_req);
+               atomic_dec(&sbi->wb_sync_req[DATA]);
        /*
         * if some pages were truncated, we cannot guarantee its mapping->host
         * to detect pending bios.
index f167d01443fe0dada2ea378033fb46161797188e..4c09e770a0a3bf6d8ef8f8e79d0582e5df05306d 100644 (file)
@@ -1201,7 +1201,7 @@ struct f2fs_sb_info {
        struct percpu_counter alloc_valid_block_count;
 
        /* writeback control */
-       atomic_t wb_sync_req;                   /* count # of WB_SYNC threads */
+       atomic_t wb_sync_req[META];     /* count # of WB_SYNC threads */
 
        /* valid inode count */
        struct percpu_counter total_valid_inode_count;
index 74c3264425652426d3cc74b97443893d59bc1d62..16fd50abbf40648a39e860a28f5190284c98c3f3 100644 (file)
@@ -274,7 +274,9 @@ go_write:
                goto out;
        }
 sync_nodes:
+       atomic_inc(&sbi->wb_sync_req[NODE]);
        ret = f2fs_fsync_node_pages(sbi, inode, &wbc, atomic);
+       atomic_dec(&sbi->wb_sync_req[NODE]);
        if (ret)
                goto out;
 
index 2a97ce7bc91d6a881f64ed47ef2274f3a0183a43..9093be6e7a7db80ca8c1f07f391875541ec99e13 100644 (file)
@@ -473,12 +473,16 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
        block_t start_addr;
        int off;
        int phase = 0;
+       bool fggc = (gc_type == FG_GC);
 
        start_addr = START_BLOCK(sbi, segno);
 
 next_step:
        entry = sum;
 
+       if (fggc && phase == 2)
+               atomic_inc(&sbi->wb_sync_req[NODE]);
+
        for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
                nid_t nid = le32_to_cpu(entry->nid);
                struct page *node_page;
@@ -525,6 +529,9 @@ next_step:
 
        if (++phase < 3)
                goto next_step;
+
+       if (fggc)
+               atomic_dec(&sbi->wb_sync_req[NODE]);
 }
 
 /*
index 64ad5466887ff5f415eba85bbc0e7647ff0210bc..47d0e64a95a8f8be2dc054d58f2f2084304d5f79 100644 (file)
@@ -1596,21 +1596,28 @@ int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
        int step = 0;
        int nwritten = 0;
        int ret = 0;
-       int nr_pages;
+       int nr_pages, done = 0;
 
        pagevec_init(&pvec);
 
 next_step:
        index = 0;
 
-       while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
-                               PAGECACHE_TAG_DIRTY))) {
+       while (!done && (nr_pages = pagevec_lookup_tag(&pvec,
+                       NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY))) {
                int i;
 
                for (i = 0; i < nr_pages; i++) {
                        struct page *page = pvec.pages[i];
                        bool submitted = false;
 
+                       /* give a priority to WB_SYNC threads */
+                       if (atomic_read(&sbi->wb_sync_req[NODE]) &&
+                                       wbc->sync_mode == WB_SYNC_NONE) {
+                               done = 1;
+                               break;
+                       }
+
                        /*
                         * flushing sequence with step:
                         * 0. indirect nodes
@@ -1738,6 +1745,11 @@ static int f2fs_write_node_pages(struct address_space *mapping,
        if (get_pages(sbi, F2FS_DIRTY_NODES) < nr_pages_to_skip(sbi, NODE))
                goto skip_write;
 
+       if (wbc->sync_mode == WB_SYNC_ALL)
+               atomic_inc(&sbi->wb_sync_req[NODE]);
+       else if (atomic_read(&sbi->wb_sync_req[NODE]))
+               goto skip_write;
+
        trace_f2fs_writepages(mapping->host, wbc, NODE);
 
        diff = nr_pages_to_write(sbi, NODE, wbc);
@@ -1745,6 +1757,9 @@ static int f2fs_write_node_pages(struct address_space *mapping,
        f2fs_sync_node_pages(sbi, wbc, true, FS_NODE_IO);
        blk_finish_plug(&plug);
        wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff);
+
+       if (wbc->sync_mode == WB_SYNC_ALL)
+               atomic_dec(&sbi->wb_sync_req[NODE]);
        return 0;
 
 skip_write:
index 25863cec143a568471e14e8e6fd3a3ad3cc61ac8..73d7d7e51a61e4ca0e87ba8f250dc9f4e6c0b1f5 100644 (file)
@@ -2362,7 +2362,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
        for (i = 0; i < NR_COUNT_TYPE; i++)
                atomic_set(&sbi->nr_pages[i], 0);
 
-       atomic_set(&sbi->wb_sync_req, 0);
+       for (i = 0; i < META; i++)
+               atomic_set(&sbi->wb_sync_req[i], 0);
 
        INIT_LIST_HEAD(&sbi->s_list);
        mutex_init(&sbi->umount_mutex);
This page took 0.086795 seconds and 4 git commands to generate.