Commit 586d1492 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim

f2fs: skip scanning free nid bitmap of full NAT blocks

This patch adds to account free nids for each NAT blocks, and while
scanning all free nid bitmap, do check count and skip lookuping in
full NAT block.
Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 23380b85
...@@ -196,6 +196,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi) ...@@ -196,6 +196,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
si->base_mem += (NM_I(sbi)->nat_bits_blocks << F2FS_BLKSIZE_BITS); si->base_mem += (NM_I(sbi)->nat_bits_blocks << F2FS_BLKSIZE_BITS);
si->base_mem += NM_I(sbi)->nat_blocks * NAT_ENTRY_BITMAP_SIZE; si->base_mem += NM_I(sbi)->nat_blocks * NAT_ENTRY_BITMAP_SIZE;
si->base_mem += NM_I(sbi)->nat_blocks / 8; si->base_mem += NM_I(sbi)->nat_blocks / 8;
si->base_mem += NM_I(sbi)->nat_blocks * sizeof(unsigned short);
get_cache: get_cache:
si->cache_mem = 0; si->cache_mem = 0;
......
...@@ -561,6 +561,8 @@ struct f2fs_nm_info { ...@@ -561,6 +561,8 @@ struct f2fs_nm_info {
struct mutex build_lock; /* lock for build free nids */ struct mutex build_lock; /* lock for build free nids */
unsigned char (*free_nid_bitmap)[NAT_ENTRY_BITMAP_SIZE]; unsigned char (*free_nid_bitmap)[NAT_ENTRY_BITMAP_SIZE];
unsigned char *nat_block_bitmap; unsigned char *nat_block_bitmap;
unsigned short *free_nid_count; /* free nid count of NAT block */
spinlock_t free_nid_lock; /* protect updating of nid count */
/* for checkpoint */ /* for checkpoint */
char *nat_bitmap; /* NAT bitmap pointer */ char *nat_bitmap; /* NAT bitmap pointer */
......
...@@ -1824,7 +1824,7 @@ static void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid) ...@@ -1824,7 +1824,7 @@ static void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid)
} }
static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid,
bool set) bool set, bool build)
{ {
struct f2fs_nm_info *nm_i = NM_I(sbi); struct f2fs_nm_info *nm_i = NM_I(sbi);
unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid); unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid);
...@@ -1837,6 +1837,13 @@ static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, ...@@ -1837,6 +1837,13 @@ static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid,
__set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); __set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]);
else else
__clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); __clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]);
spin_lock(&nm_i->free_nid_lock);
if (set)
nm_i->free_nid_count[nat_ofs]++;
else if (!build)
nm_i->free_nid_count[nat_ofs]--;
spin_unlock(&nm_i->free_nid_lock);
} }
static void scan_nat_page(struct f2fs_sb_info *sbi, static void scan_nat_page(struct f2fs_sb_info *sbi,
...@@ -1848,6 +1855,9 @@ static void scan_nat_page(struct f2fs_sb_info *sbi, ...@@ -1848,6 +1855,9 @@ static void scan_nat_page(struct f2fs_sb_info *sbi,
unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid); unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid);
int i; int i;
if (test_bit_le(nat_ofs, nm_i->nat_block_bitmap))
return;
__set_bit_le(nat_ofs, nm_i->nat_block_bitmap); __set_bit_le(nat_ofs, nm_i->nat_block_bitmap);
i = start_nid % NAT_ENTRY_PER_BLOCK; i = start_nid % NAT_ENTRY_PER_BLOCK;
...@@ -1862,7 +1872,7 @@ static void scan_nat_page(struct f2fs_sb_info *sbi, ...@@ -1862,7 +1872,7 @@ static void scan_nat_page(struct f2fs_sb_info *sbi,
f2fs_bug_on(sbi, blk_addr == NEW_ADDR); f2fs_bug_on(sbi, blk_addr == NEW_ADDR);
if (blk_addr == NULL_ADDR) if (blk_addr == NULL_ADDR)
freed = add_free_nid(sbi, start_nid, true); freed = add_free_nid(sbi, start_nid, true);
update_free_nid_bitmap(sbi, start_nid, freed); update_free_nid_bitmap(sbi, start_nid, freed, true);
} }
} }
...@@ -1878,6 +1888,8 @@ static void scan_free_nid_bits(struct f2fs_sb_info *sbi) ...@@ -1878,6 +1888,8 @@ static void scan_free_nid_bits(struct f2fs_sb_info *sbi)
for (i = 0; i < nm_i->nat_blocks; i++) { for (i = 0; i < nm_i->nat_blocks; i++) {
if (!test_bit_le(i, nm_i->nat_block_bitmap)) if (!test_bit_le(i, nm_i->nat_block_bitmap))
continue; continue;
if (!nm_i->free_nid_count[i])
continue;
for (idx = 0; idx < NAT_ENTRY_PER_BLOCK; idx++) { for (idx = 0; idx < NAT_ENTRY_PER_BLOCK; idx++) {
nid_t nid; nid_t nid;
...@@ -2082,7 +2094,7 @@ bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) ...@@ -2082,7 +2094,7 @@ bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
__insert_nid_to_list(sbi, i, ALLOC_NID_LIST, false); __insert_nid_to_list(sbi, i, ALLOC_NID_LIST, false);
nm_i->available_nids--; nm_i->available_nids--;
update_free_nid_bitmap(sbi, *nid, false); update_free_nid_bitmap(sbi, *nid, false, false);
spin_unlock(&nm_i->nid_list_lock); spin_unlock(&nm_i->nid_list_lock);
return true; return true;
...@@ -2138,7 +2150,7 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) ...@@ -2138,7 +2150,7 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
nm_i->available_nids++; nm_i->available_nids++;
update_free_nid_bitmap(sbi, nid, true); update_free_nid_bitmap(sbi, nid, true, false);
spin_unlock(&nm_i->nid_list_lock); spin_unlock(&nm_i->nid_list_lock);
...@@ -2468,11 +2480,11 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, ...@@ -2468,11 +2480,11 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
add_free_nid(sbi, nid, false); add_free_nid(sbi, nid, false);
spin_lock(&NM_I(sbi)->nid_list_lock); spin_lock(&NM_I(sbi)->nid_list_lock);
NM_I(sbi)->available_nids++; NM_I(sbi)->available_nids++;
update_free_nid_bitmap(sbi, nid, true); update_free_nid_bitmap(sbi, nid, true, false);
spin_unlock(&NM_I(sbi)->nid_list_lock); spin_unlock(&NM_I(sbi)->nid_list_lock);
} else { } else {
spin_lock(&NM_I(sbi)->nid_list_lock); spin_lock(&NM_I(sbi)->nid_list_lock);
update_free_nid_bitmap(sbi, nid, false); update_free_nid_bitmap(sbi, nid, false, false);
spin_unlock(&NM_I(sbi)->nid_list_lock); spin_unlock(&NM_I(sbi)->nid_list_lock);
} }
} }
...@@ -2652,6 +2664,14 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi) ...@@ -2652,6 +2664,14 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
GFP_KERNEL); GFP_KERNEL);
if (!nm_i->nat_block_bitmap) if (!nm_i->nat_block_bitmap)
return -ENOMEM; return -ENOMEM;
nm_i->free_nid_count = f2fs_kvzalloc(nm_i->nat_blocks *
sizeof(unsigned short), GFP_KERNEL);
if (!nm_i->free_nid_count)
return -ENOMEM;
spin_lock_init(&nm_i->free_nid_lock);
return 0; return 0;
} }
...@@ -2731,6 +2751,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi) ...@@ -2731,6 +2751,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
kvfree(nm_i->nat_block_bitmap); kvfree(nm_i->nat_block_bitmap);
kvfree(nm_i->free_nid_bitmap); kvfree(nm_i->free_nid_bitmap);
kvfree(nm_i->free_nid_count);
kfree(nm_i->nat_bitmap); kfree(nm_i->nat_bitmap);
kfree(nm_i->nat_bits); kfree(nm_i->nat_bits);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment