除了node_info之外, node管理器中还有还有个重要的数据结构:
145 struct free_nid { 146 struct list_head list; /* for free node id list */ 147 nid_t nid; /* node id */ 148 int state; /* in use or not: NID_NEW or NID_ALLOC */ 149 };
这个结构体体很简单,比刚才的node_info轻量级多了,仅仅是标识了当前可以使用的nid,以及这个nid的状态,一个指针将其与别的free_nid连成一串。
别看这个结构简单,也被node管理器中两个 “索引” 管理着呢:1)基数树 free_nid_root; 2)链表 free_nid_list;【参见函数add_free_nid】
但是咱这个free_nid 也总得有个出栈的时候吧,你得为国家建设做贡献,不然在占个位置干嘛呢!
alloc_nid 函数会从 free_nid_list 链表中选出一个free_nid出来,这个nid算是被选中了,但是此时并不会把这个节点从list删除,为什么呢?因为选中nid只是万里长征的第一步,后面还有许多事情要做呢,这些事情没做完我们就不能删除,如果中途失败,那么咱这个nid算是分配出去了,到哪儿找呢!所以要给自己回旋的余地啊,f2fs的代码巧妙地把此时free_nid的状态从NID_NEW变成了NID_ALLOC,什么时候完全从链表中删除呢?
函数:alloc_nid_done ! 其中,狠心的__del_from_free_nid_list,会将这个节点从链表中删除,并删除基数树中的索引。然后其在slab中的位置也被释放了!
1634 /* 1635 * alloc_nid() should be called prior to this function. 1636 */ 1637 void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) 1638 { 1643 i = __lookup_free_nid_list(nm_i, nid); //从基数树中删除这个节点 1644 f2fs_bug_on(sbi, !i || i->state != NID_ALLOC); 1645 __del_from_free_nid_list(nm_i, i); //从链表中删除.. 1648 kmem_cache_free(free_nid_slab, i); 1649 } 1650
1451 static void __del_from_free_nid_list(struct f2fs_nm_info *nm_i, 1452 struct free_nid *i) 1453 { 1454 list_del(&i->list); 1455 radix_tree_delete(&nm_i->free_nid_root, i->nid); 1456 } 1
到这里我们基本了解了free_nid的一生。并且也基本猜到了他的一个作用:为node_info的出场暖场呢!
时间: 2024-10-24 10:08:14