Skip to content

Commit 13c2bea

Browse files
Jaegeuk KimHashcode
authored andcommitted
f2fs: introduce a radix_tree for the free_nid list
This patch introduces a radix tree for the list of free_nids, which enhances the performance on free nid management. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
1 parent 60e4952 commit 13c2bea

2 files changed

Lines changed: 18 additions & 19 deletions

File tree

fs/f2fs/f2fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ struct f2fs_nm_info {
247247
struct list_head dirty_nat_entries; /* cached nat entry list (dirty) */
248248

249249
/* free node ids management */
250+
struct radix_tree_root free_nid_root;/* root of the free_nid cache */
250251
struct list_head free_nid_list; /* a list for free nids */
251252
spinlock_t free_nid_list_lock; /* protect free nid list */
252253
unsigned int fcnt; /* the number of free node id */

fs/f2fs/node.c

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,21 +1268,17 @@ const struct address_space_operations f2fs_node_aops = {
12681268
.releasepage = f2fs_release_node_page,
12691269
};
12701270

1271-
static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head)
1271+
static struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i,
1272+
nid_t n)
12721273
{
1273-
struct list_head *this;
1274-
struct free_nid *i;
1275-
list_for_each(this, head) {
1276-
i = list_entry(this, struct free_nid, list);
1277-
if (i->nid == n)
1278-
return i;
1279-
}
1280-
return NULL;
1274+
return radix_tree_lookup(&nm_i->free_nid_root, n);
12811275
}
12821276

1283-
static void __del_from_free_nid_list(struct free_nid *i)
1277+
static void __del_from_free_nid_list(struct f2fs_nm_info *nm_i,
1278+
struct free_nid *i)
12841279
{
12851280
list_del(&i->list);
1281+
radix_tree_delete(&nm_i->free_nid_root, i->nid);
12861282
kmem_cache_free(free_nid_slab, i);
12871283
}
12881284

@@ -1303,7 +1299,8 @@ static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build)
13031299
/* do not add allocated nids */
13041300
read_lock(&nm_i->nat_tree_lock);
13051301
ne = __lookup_nat_cache(nm_i, nid);
1306-
if (ne && nat_get_blkaddr(ne) != NULL_ADDR)
1302+
if (ne &&
1303+
(!ne->checkpointed || nat_get_blkaddr(ne) != NULL_ADDR))
13071304
allocated = true;
13081305
read_unlock(&nm_i->nat_tree_lock);
13091306
if (allocated)
@@ -1315,7 +1312,7 @@ static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build)
13151312
i->state = NID_NEW;
13161313

13171314
spin_lock(&nm_i->free_nid_list_lock);
1318-
if (__lookup_free_nid_list(nid, &nm_i->free_nid_list)) {
1315+
if (radix_tree_insert(&nm_i->free_nid_root, i->nid, i)) {
13191316
spin_unlock(&nm_i->free_nid_list_lock);
13201317
kmem_cache_free(free_nid_slab, i);
13211318
return 0;
@@ -1330,9 +1327,9 @@ static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
13301327
{
13311328
struct free_nid *i;
13321329
spin_lock(&nm_i->free_nid_list_lock);
1333-
i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
1330+
i = __lookup_free_nid_list(nm_i, nid);
13341331
if (i && i->state == NID_NEW) {
1335-
__del_from_free_nid_list(i);
1332+
__del_from_free_nid_list(nm_i, i);
13361333
nm_i->fcnt--;
13371334
}
13381335
spin_unlock(&nm_i->free_nid_list_lock);
@@ -1456,9 +1453,9 @@ void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
14561453
struct free_nid *i;
14571454

14581455
spin_lock(&nm_i->free_nid_list_lock);
1459-
i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
1456+
i = __lookup_free_nid_list(nm_i, nid);
14601457
f2fs_bug_on(!i || i->state != NID_ALLOC);
1461-
__del_from_free_nid_list(i);
1458+
__del_from_free_nid_list(nm_i, i);
14621459
spin_unlock(&nm_i->free_nid_list_lock);
14631460
}
14641461

@@ -1474,10 +1471,10 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
14741471
return;
14751472

14761473
spin_lock(&nm_i->free_nid_list_lock);
1477-
i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
1474+
i = __lookup_free_nid_list(nm_i, nid);
14781475
f2fs_bug_on(!i || i->state != NID_ALLOC);
14791476
if (nm_i->fcnt > 2 * MAX_FREE_NIDS) {
1480-
__del_from_free_nid_list(i);
1477+
__del_from_free_nid_list(nm_i, i);
14811478
} else {
14821479
i->state = NID_NEW;
14831480
nm_i->fcnt++;
@@ -1811,6 +1808,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
18111808
nm_i->fcnt = 0;
18121809
nm_i->nat_cnt = 0;
18131810

1811+
INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC);
18141812
INIT_LIST_HEAD(&nm_i->free_nid_list);
18151813
INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC);
18161814
INIT_LIST_HEAD(&nm_i->nat_entries);
@@ -1864,7 +1862,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
18641862
spin_lock(&nm_i->free_nid_list_lock);
18651863
list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) {
18661864
f2fs_bug_on(i->state == NID_ALLOC);
1867-
__del_from_free_nid_list(i);
1865+
__del_from_free_nid_list(nm_i, i);
18681866
nm_i->fcnt--;
18691867
}
18701868
f2fs_bug_on(nm_i->fcnt);

0 commit comments

Comments
 (0)