本文阅读fs/inode.c,进行学习。
分配inode
一般在fs的lookup函数,或者create函数中,调用new_inode(sb)分配inode,然后fill inode,初始化inode的fops等成员。
fs/inode.c
struct inode *new_inode(struct super_block *sb)
alloc_inode(sb), 分配inode。
inode_sb_list_add(inode),将inode加到super block的inode list中。
这个是一个导出符号的函数,各个fs可以调用。
static struct inode *alloc_inode(struct super_block *sb)
这是个静态函数
如果定义了sb->s_op->alloc_inode,就调用这个函数。
否则调用:
inode = alloc_inode_sb(sb, inode_cachep, GFP_KERNEL);
从系统的inode cache分配。
fs定义的alloc_inode接口
struct mirrorfs_inode *mi = alloc_inode_sb(sb, mirrorfs_inode_cachep, GFP_KERNEL);
fs自己的inode是一个大的inode包含了内核的inode。这里从fs自己的inode cache分配。
然后初始化自定义结构体的成员。
new_inode()的时候,会调用inode_sb_list_add(),把inode加入到sb的inodes list中。
void inode_sb_list_add(struct inode *inode)
{
spin_lock(&inode->i_sb->s_inode_list_lock);
list_add(&inode->i_sb_list, &inode->i_sb->s_inodes);
spin_unlock(&inode->i_sb->s_inode_list_lock);
}
EXPORT_SYMBOL_GPL(inode_sb_list_add);这个s_inodes是一个链表,这个链表有大作用,用来遍历super block的所有加入该链表的inode。实现下列几大功能:
1 drop caches会遍历这个链表,来实现清理page cache。
2 实现quota功能(根据注释)
3 实现writeback功能 (根据注释)
和dentry一样,inode也有hashtable。用来实现inode的插入和查找。
这个是vfs提供的一个便利的机制,fs可以选择不插入到vfs的哈希表,也可以自己维护。
哈希值也不一定使用inode id。fs可以根据具体业务需求选定。
static unsigned long hash(struct super_block *sb, unsigned long hashval)
计算哈希值,直接得到哈希桶的index。
void __insert_inode_hash(struct inode *inode, unsigned long hashval)
将inode插入到哈希表中
这里里面会上,全局的inode_hash_lock锁,以及inode的i_lock锁。
void __remove_inode_hash(struct inode *inode)
将inode从哈希表中移除
有一系列插入、查找的函数:
inode_insert5
iget5_locked
iget5_locked_rcu
iget_locked
ilookup5_nowait
ilookup5
ilookup
find_inode_nowait
find_inode_rcu
find_inode_by_ino_rcu
insert_inode_locked
insert_inode_locked4
void __iget(struct inode *inode)
增加引用计数。调用者需要上inode->i_lock
struct inode *igrab(struct inode *inode)
这个接口,会上锁,如果inode处于I_FREEING|I_WILL_FREE状态,返回NULL。
否则,增加引用计数,并且返回inode。
void iput(struct inode *inode)
释放一个引用计数,如果引用计数达到0,则释放inode。