Search nat_block_bitmap to accelerate free nids built process.

Signed-off-by: Yunlei He <[email protected]>
---
 fs/f2fs/f2fs.h |  3 ++-
 fs/f2fs/node.c | 47 +++++++++++++++++++++++++++++++++--------------
 2 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 398ed95..afbe705 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -733,7 +733,8 @@ struct f2fs_nm_info {
        spinlock_t nid_list_lock;       /* protect nid lists ops */
        struct mutex build_lock;        /* lock for build free nids */
        unsigned char (*free_nid_bitmap)[NAT_ENTRY_BITMAP_SIZE];
-       unsigned char *nat_block_bitmap;
+       unsigned long *nat_block_bitmap;
+       unsigned int scaned_nat_blocks; /* # of nat blocks have been read */
        unsigned short *free_nid_count; /* free nid count of NAT block */
 
        /* for checkpoint */
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 35b079d..e00d7a7 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1935,6 +1935,7 @@ static void scan_nat_page(struct f2fs_sb_info *sbi,
        int i;
 
        __set_bit_le(nat_ofs, nm_i->nat_block_bitmap);
+       nm_i->scaned_nat_blocks++;
 
        i = start_nid % NAT_ENTRY_PER_BLOCK;
 
@@ -2031,6 +2032,9 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, 
bool sync, bool mount)
                        return;
        }
 
+       if (nm_i->scaned_nat_blocks == nm_i->nat_blocks)
+               return;
+
        /* readahead nat pages to be scanned */
        ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
                                                        META_NAT, true);
@@ -2038,19 +2042,35 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, 
bool sync, bool mount)
        down_read(&nm_i->nat_tree_lock);
 
        while (1) {
-               if (!test_bit_le(NAT_BLOCK_OFFSET(nid),
-                                               nm_i->nat_block_bitmap)) {
-                       struct page *page = get_current_nat_page(sbi, nid);
+               unsigned int start;
+               struct page *page;
 
-                       scan_nat_page(sbi, page, nid);
-                       f2fs_put_page(page, 1);
+               start = find_next_zero_bit(nm_i->nat_block_bitmap,
+                               nm_i->nat_blocks, NAT_BLOCK_OFFSET(nid));
+
+               if (start >= nm_i->nat_blocks) {
+                       if (nm_i->scaned_nat_blocks > nm_i->nat_blocks) {
+                               f2fs_bug_on(sbi, 1);
+                               break;
+                       } else if (nm_i->scaned_nat_blocks == nm_i->nat_blocks){
+                               break;
+                       } else {
+                               nid = 0;
+                               continue;
+                       }
                }
 
-               nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
-               if (unlikely(nid >= nm_i->max_nid))
-                       nid = 0;
+               nid = start * NAT_ENTRY_PER_BLOCK;
+               page = get_current_nat_page(sbi, nid);
+               scan_nat_page(sbi, page, nid);
+               f2fs_put_page(page, 1);
+               nid += NAT_ENTRY_PER_BLOCK;
 
-               if (++i >= FREE_NID_PAGES)
+               /* background or mount build, no more than 8 pages */
+               if ((!sync || mount) && ++i >= FREE_NID_PAGES)
+                       break;
+               /* foreground build, until get free nids */
+               if (sync && !mount && nm_i->nid_cnt[FREE_NID])
                        break;
        }
 
@@ -2061,9 +2081,6 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, 
bool sync, bool mount)
        scan_curseg_cache(sbi);
 
        up_read(&nm_i->nat_tree_lock);
-
-       ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
-                                       nm_i->ra_nid_pages, META_NAT, false);
 }
 
 void build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
@@ -2656,6 +2673,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
        nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
        nm_i->nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg);
        nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks;
+       nm_i->scaned_nat_blocks = 0;
 
        /* not used nids: 0, node, meta, (and root counted as valid node) */
        nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count -
@@ -2705,14 +2723,15 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
 static int init_free_nid_cache(struct f2fs_sb_info *sbi)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
+       unsigned int bitmap_size;
 
        nm_i->free_nid_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks *
                                        NAT_ENTRY_BITMAP_SIZE, GFP_KERNEL);
        if (!nm_i->free_nid_bitmap)
                return -ENOMEM;
 
-       nm_i->nat_block_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks / 8,
-                                                               GFP_KERNEL);
+       bitmap_size = f2fs_bitmap_size(nm_i->nat_blocks);
+       nm_i->nat_block_bitmap = f2fs_kvzalloc(sbi, bitmap_size, GFP_KERNEL);
        if (!nm_i->nat_block_bitmap)
                return -ENOMEM;
 
-- 
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to