This patch including two changes:
1. We introduce nat journal to cache nat blocks which has less
dirty nat entries, nat entry sets are ranked by dirty nat entry
count if the count less than NAT_JOURNAL_ENTRIES. This method
will break the continuity of nat blocks write back order, and
this patch make a change of that prior to flush continuous nat
blocks.

2. Add read ahead nat blocks in case of a lot of serial synchronized
read as below:

336.785911: f2fs_write_checkpoint: dev = (259,44), checkpoint for Sync, state = 
start flush nat
336.785980: flush_nat_entries: flush sum = 278 dirty nat pages
336.786002: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0x129f, 
oldaddr = 0x129f, newaddr = 0x129f rw = READ_SYNC(MP), type = META
336.791681: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0x148e, 
oldaddr = 0x148e, newaddr = 0x148e rw = READ_SYNC(MP), type = META
336.797802: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0x1482, 
oldaddr = 0x1482, newaddr = 0x1482 rw = READ_SYNC(MP), type = META
336.799155: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0x1481, 
oldaddr = 0x1481, newaddr = 0x1481 rw = READ_SYNC(MP), type = META
336.800603: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0x147f, 
oldaddr = 0x147f, newaddr = 0x147f rw = READ_SYNC(MP), type = META
336.802102: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0x147b, 
oldaddr = 0x147b, newaddr = 0x147b rw = READ_SYNC(MP), type = META
336.803528: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0x1474, 
oldaddr = 0x1474, newaddr = 0x1474 rw = READ_SYNC(MP), type = META
336.805026: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0x1455, 
oldaddr = 0x1455, newaddr = 0x1455 rw = READ_SYNC(MP), type = META
336.806537: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0xc1e, 
oldaddr = 0xc1e, newaddr = 0xc1e rw = READ_SYNC(MP), type = META
336.807864: f2fs_submit_page_bio: dev = (259,44), ino = 2, page_index = 0x1307, 
oldaddr = 0x1307, newaddr = 0x1307 rw = READ_SYNC(MP), type = META
336.833539: f2fs_write_checkpoint: dev = (259,44), checkpoint for Sync, state = 
end flush nat

Signed-off-by: Yunlei He <heyun...@huawei.com>
Signed-off-by: Wei Fang <fangw...@huawei.com>
---
 fs/f2fs/node.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 fs/f2fs/node.h |  1 +
 2 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 833b46b..3b29fcb 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -209,6 +209,7 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
                INIT_LIST_HEAD(&head->set_list);
                head->set = set;
                head->entry_cnt = 0;
+               head->continue_io = false;
                f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head);
        }
 
@@ -2403,16 +2404,50 @@ static void remove_nats_in_journal(struct f2fs_sb_info 
*sbi)
        up_write(&curseg->journal_rwsem);
 }
 
-static void __adjust_nat_entry_set(struct nat_entry_set *nes,
-                                               struct list_head *head, int max)
+static bool nat_block_is_continuous(struct f2fs_nm_info *nm_i,
+                                       struct nat_entry_set *nes)
+{
+       unsigned int nat_index = nes->set;
+       unsigned char bit_cur =
+               f2fs_test_bit(nat_index, nm_i->nat_bitmap) ? 1 : 0;
+
+       if (nat_index && radix_tree_lookup(&nm_i->nat_set_root, nat_index - 1)) 
{
+               unsigned char bit_pre =
+                       f2fs_test_bit(nat_index - 1, nm_i->nat_bitmap) ? 1 : 0;
+
+               if (bit_pre == bit_cur) {
+                       nes->continue_io = true;
+                       return true;
+               }
+       }
+
+       if (nat_index < nm_i->nat_blocks &&
+                       radix_tree_lookup(&nm_i->nat_set_root, nat_index + 1)) {
+               unsigned char bit_next =
+                       f2fs_test_bit(nat_index + 1, nm_i->nat_bitmap) ? 1 : 0;
+
+               if (bit_next == bit_cur) {
+                       nes->continue_io = true;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static void __adjust_nat_entry_set(struct f2fs_nm_info *nm_i,
+                       struct nat_entry_set *nes, struct list_head *head, int 
max)
 {
        struct nat_entry_set *cur;
 
        if (nes->entry_cnt >= max)
                goto add_out;
 
+       if (nat_block_is_continuous(nm_i, nes))
+               goto add_out;
+
        list_for_each_entry(cur, head, set_list) {
-               if (cur->entry_cnt >= nes->entry_cnt) {
+               if (cur->entry_cnt >= nes->entry_cnt || cur->continue_io) {
                        list_add(&nes->set_list, cur->set_list.prev);
                        return;
                }
@@ -2471,7 +2506,8 @@ static void __flush_nat_entry_set(struct f2fs_sb_info 
*sbi,
         * #2, flush nat entries to nat page.
         */
        if (enabled_nat_bits(sbi, cpc) ||
-               !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
+               !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL) ||
+               set->continue_io)
                to_journal = false;
 
        if (to_journal) {
@@ -2536,6 +2572,7 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
        struct nat_entry_set *setvec[SETVEC_SIZE];
        struct nat_entry_set *set, *tmp;
        unsigned int found;
+       unsigned int nats_to_journal = 0;
        nid_t set_idx = 0;
        LIST_HEAD(sets);
 
@@ -2558,10 +2595,23 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
                unsigned idx;
                set_idx = setvec[found - 1]->set + 1;
                for (idx = 0; idx < found; idx++)
-                       __adjust_nat_entry_set(setvec[idx], &sets,
+                       __adjust_nat_entry_set(nm_i, setvec[idx], &sets,
                                                MAX_NAT_JENTRIES(journal));
        }
 
+       list_for_each_entry_safe(set, tmp, &sets, set_list) {
+               block_t blk_addr;
+
+               nats_to_journal += set->entry_cnt;
+
+               if (nats_to_journal > NAT_JOURNAL_ENTRIES ||
+                                               set->continue_io) {
+                       blk_addr = current_nat_addr(sbi,
+                                       set->set * NAT_ENTRY_PER_BLOCK);
+                       ra_meta_pages(sbi, blk_addr, 1, META_NAT, true);
+               }
+       }
+
        /* flush dirty nats in nat entry set */
        list_for_each_entry_safe(set, tmp, &sets, set_list)
                __flush_nat_entry_set(sbi, set, cpc);
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index 081ef0d..91414de 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -149,6 +149,7 @@ struct nat_entry_set {
        struct list_head entry_list;    /* link with dirty nat entries */
        nid_t set;                      /* set number*/
        unsigned int entry_cnt;         /* the # of nat entries in set */
+       bool continue_io;
 };
 
 struct free_nid {
-- 
1.9.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to