free_info 功成身退,node_info顺利接班。
// 这里还是蛮复杂的一件事,如果不搞清除的话,这个历史性的接班工作我们就接不上
上面说到 alloc_nid 和 alloc_nid_done 之后,这个free_nid算是被完全清除了。我们知道free_info 和 node_info 结构体的桥梁就是nid了,那么我们看下这个nid干什么用了!搜alloc_nid,主要有两处:1)创建一个新的inode【函数f2fs_mkdir, f2fs_create】;2)创建文件的索引的时候:【函数 get_dnode_of_data】。
我们发现这两条线到最后都不约而同地调用了接口new_node_page
1)__f2fs_add_link --> init_inode_metadata --> new_inode_page --> new_node_page --> grab_cache_page
2)get_dnode_of_data --> new_node_page -->grab_cache_page
到这里,我们知道page中这个nid的页就建立起来了,这个得到这个页alloc_nid的工作也算是完成了,那么node_info中blk_addr是怎么设置的呢?
我们自动想到了address_spacing中的写回的钩子:f2fs_write_node_page;
在f2fs_write_node_page函数中,nid的信息首先会通过get_node_info 函数得到, 但是由于node管理器中的nat_root树中并没有相关的nid的信息,所以此时就会在最后的cache_nat_entry中建立啦! 可见此时打配合的两个管理结构是:1)基数树,nat_root;2)链表,nat_entries。
247 static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid) 248 { 249 struct nat_entry *new; 250 251 new = f2fs_kmem_cache_alloc(nat_entry_slab, GFP_ATOMIC); 252 f2fs_radix_tree_insert(&nm_i->nat_root, nid, new); 253 memset(new, 0, sizeof(struct nat_entry)); 254 nat_set_nid(new, nid); 255 nat_reset_flag(new); 256 list_add_tail(&new->list, &nm_i->nat_entries); 257 nm_i->nat_cnt++; 258 return new; 259 }
但是根据日志文件系统的原理,我此时此刻还是不能确定最后的这个nid的节点要落到何处。
但是函数f2fs_write_node_page,继续向下执行,就会有set_node_addr函数,将nat_root中的地址填充完整,于是node_info完整了。
好了,到这里我们明白了node_info 与 free_nid 这个历史性交接过程:一个nid如何从free_list 到 nat_entries中去了。