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