📄 inode.c
字号:
*/
}
/*
* This is special! We do not need the spinlock
* when clearing I_LOCK, because we're guaranteed
* that nobody else tries to do anything about the
* state of the inode when it is locked, as we
* just created it (so there can be no old holders
* that haven't tested I_LOCK).
*/
inode->i_state &= ~I_LOCK;/*清除inode上的锁*/
wake_up(&inode->i_wait);/*唤醒在该inode上等待的进程*/
return inode;/*返回所分配的inode对象的指针*/
}
/*
* Uhhuh, somebody else created the same inode under
* us. Use the old inode instead of the one we just
* allocated.
*/
/*find_inode()返回一个有效的指针,
*则说明其它模块已经创建了(sb,ino)这个inode对象,
*那么,就用旧的inode替代我们刚刚分配的inode对象
*/
__iget(old);/*增加所找到的inode对象的引用计数*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
destroy_inode(inode);/*销毁一开始创建的inode对象*/
inode = old;/*inode指针指向旧的索引节点old*/
wait_on_inode(inode);/*等待inode被解锁*/
}
return inode;/*返回所分配的inode对象的指针*/
}
/*计算一个inode对象的哈希散列值*/
/*
Linux唯一确定一个inode对象的值是二元组(设备号,索引节点号),
而设备号与超级块对象是一一对应的,
因此,哈希散列值计算函数hash以super_block对象和索引节点号i_ino为参数。
*/
static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
{
/*声明unsigned long型tmp,并赋值为i_ino + ((unsigned long) sb / 32)*/
unsigned long tmp = i_ino + ((unsigned long) sb / L1_CACHE_BYTES);
tmp = tmp + (tmp >> I_HASHBITS);/*tmp按二进制右移I_HASHBITS,再加上tmp的值,并赋值给tmp*/
return tmp & I_HASHMASK;/*返回tmp和I_HASHMASK相与的结果,即inode对象的哈希散列值*/
}
/* Yeah, I know about quadratic hash. Maybe, later. */
/**
* iunique - get a unique inode number
* @sb: superblock
* @max_reserved: highest reserved inode number
*
* Obtain an inode number that is unique on the system for a given
* superblock. This is used by file systems that have no natural
* permanent inode numbering system. An inode number is returned that
* is higher than the reserved limit but unique.
*
* BUGS:
* With a large number of inodes live on the file system this function
* currently becomes quite slow.
*/
/*获得一个唯一的索引节点号*/
ino_t iunique(struct super_block *sb, ino_t max_reserved)
{
static ino_t counter = 0;/*声明ino_t 型变量counter,并初始化为0*/
struct inode *inode;/*声明inode指针*/
struct list_head * head;/*声明链表指针head*/
ino_t res;/*声明ino_t 型变量res*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
retry:
if (counter > max_reserved) {/*couter大于最大预留值*/
head = inode_hashtable + hash(sb,counter);/*head指向list_head结构数组inode_hashtable的基址
*加上inode对象的哈希散列值的位置
*/
inode = find_inode(sb, res = counter++, head, NULL, NULL);
/*在hash链表中查找由(sb,res)唯一标识的inode对象,res=counter,再将counter+1*/
if (!inode) {/*如果在哈希链表中没有找到相应的inode对象*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
return res;/*返回res*/
}
} else {/*couter小于等于最大预留值*/
counter = max_reserved + 1;/*counter赋值为max_reserved + 1*/
}
goto retry;/*跳转回retry*/
}
/*夺取一个inode对象*/
struct inode *igrab(struct inode *inode)
{
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
if (!(inode->i_state & I_FREEING))/*inode不空闲*/
__iget(inode);/*增加一个inode对象的引用计数*/
else/*inode空闲*/
/*
* Handle the case where s_op->clear_inode is not been
* called yet, and somebody is calling igrab
* while the inode is getting freed.
*/
inode = NULL;/*inode指向空索引节点*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
return inode;/*返回inode指针*/
}
/*引用一个inode对象
其他内核模块要想访问一个inode对象,必须通过iget()访问接口。
该函数会首先在icache的哈希链表中查找相应的inode对象,
如果找到,则将该对象的引用计数加1,然后返回该inode对象的指针。
如果没有找到,则通过调用get_new_inode()函数分配一个新的inode对象。
*/
/*(include/linux/fs.h):
static inline struct inode *iget(struct super_block *sb, unsigned long ino)
{
return iget4(sb, ino, NULL, NULL);
}
*/
struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
{
struct list_head * head = inode_hashtable + hash(sb,ino);
/*声明list_head指针head,
*head指向list_head结构数组inode_hashtable的基址加上inode对象的哈希散列值的位置
*/
struct inode * inode;/*声明inode指针*/
/*首先,通过散列函数hash找到该inode对象应该在那个哈希链表中,
然后调用find_inode()函数在该哈希链表中查找是否存在该inode对象
*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
inode = find_inode(sb, ino, head, find_actor, opaque);/*在hash链表中查找由(sb,ino)唯一标识的inode对象*/
if (inode) {/*如果在哈希链表中找到了相应的inode对象*/
__iget(inode);/*增加该inode 对象的引用计数*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
wait_on_inode(inode);/*等待该inode对象被其他内核模块解锁*/
return inode;/*直接返回这个inode对象的指针*/
}
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
/*
* get_new_inode() will do the right thing, re-trying the search
* in case it had to block at any point.
*/
return get_new_inode(sb, ino, head, find_actor, opaque);/*分配一个新的inode对象*/
}
/**
* insert_inode_hash - hash an inode
* @inode: unhashed inode
*
* Add an inode to the inode hash for this superblock. If the inode
* has no superblock it is added to a separate anonymous chain.
*/
/*对上面注释的翻译:
*将一个inode加入到hash表,如果inode的相应超块不存在,
*则把它链接到匿名索引节点哈希链表中
*/
/*将一个未散列的inode对象插入到相应的索引节点哈希链表中*/
void insert_inode_hash(struct inode *inode)
{
struct list_head *head = &anon_hash_chain;/*声明list_head 型指针head,并使其指向anon_hash_chain*/
if (inode->i_sb)/*inode->i_sb存在*/
head = inode_hashtable + hash(inode->i_sb, inode->i_ino);
/*
*head指向list_head结构数组inode_hashtable的基址
*加上inode对象的哈希散列值的位置,
*并根据该hash值找到应该插入的队列
*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
list_add(&inode->i_hash, head);/*用该inode的i_hash域,将它插入队列的队头*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
}
/**
* remove_inode_hash - remove an inode from the hash
* @inode: inode to unhash
*
* Remove an inode from the superblock or anonymous hash.
*/
/*对上面注释的翻译:
*将一个inode从相应的超块的hash表或匿名inode hash表中去除
*/
/*将一个inode对象从他所属的哈希链表中摘除*/
void remove_inode_hash(struct inode *inode)
{
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
list_del(&inode->i_hash);/*直接将该inode从hash队列中摘下*/
INIT_LIST_HEAD(&inode->i_hash);/*让inode->i_hash的两个指针都指向自己*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
}
/**
* iput - put an inode
* @inode: inode to put
*
* Puts an inode, dropping its usage count. If the inode use count hits
* zero the inode is also then freed and may be destroyed.
*/
/*释放对一个inode对象的引用*/
/*当其他内核对象或模块不再需要一个inode对象时,
必须通过iput()函数,来解除对该inode对象的引用。
iput()函数将inode对象的引用计数减1。
如果减到了0,则将该inode释放。
否则就直接返回。
*/
void iput(struct inode *inode)
{
if (inode) {/*如果inode不为空*/
struct super_block *sb = inode->i_sb;/*声明一个超块指针sb,
*指向inode相应的超块inode->i_sb*/
struct super_operations *op = NULL;/*声明一个对超块操作的结构体指针op*/
if (inode->i_state == I_CLEAR)/*如果i_state为I_CLEAR,即该inode中内容已被清除*/
BUG();/*调用BUG()*/
if (sb && sb->s_op)/*sb 存在,且sb->s_op存在*/
op = sb->s_op;/*op指向sb->s_op*/
if (op && op->put_inode)/*op存在,且op->put_inode()函数存在*/
op->put_inode(inode);/*调用超级块对象中的s_op->put_inode()方法释放这个inode对象*/
/*通过atomic_dec_and_lock原子操作将i_count减1,并同时对inode_lock进行加锁*/
if (!atomic_dec_and_lock(&inode->i_count, &inode_lock))
return; /*如果i_count在减1后还为非0值,则直接返回*/
if (!inode->i_nlink) {/*如果该inode的i_nlink值为0,
*则说明文件系统中已经没有任何文件链接到这个inode对象上
*该inode已不在任何目录中
*/
/*将这个 inode从其所属的哈希链表和“类型”链表中摘除*/
list_del(&inode->i_hash);/*将这个 inode从其所属的哈希链表中摘除*/
INIT_LIST_HEAD(&inode->i_hash);/*让inode->i_hash的两个指针都指向自己*/
list_del(&inode->i_list);/*将这个 inode从其所属的“类型”链表中摘除*/
INIT_LIST_HEAD(&inode->i_list);/*让inode->i_list的两个指针都指向自己*/
inode->i_state|=I_FREEING;/*在其i_count中设置I_FREEING标志,表示正在释放这个inode对象*/
inodes_stat.nr_inodes--;/*inode cache中的inode对象总数减一*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
if (inode->i_data.nrpages)/*inode地址空间的总页数不为0*/
truncate_inode_pages(&inode->i_data, 0);
/*截短inode的页缓冲,从超过偏移量的部分移出,
*如果该页被锁,那么等待该页被解锁
*/
/**
* truncate_inode_pages - truncate *all* the pages from an offset
* @mapping: mapping to truncate
* @lstart: offset from with to truncate
*
* Truncate the page cache at a set offset, removing the pages
* that are beyond that offset (and zeroing out partial pages).
* If any page is locked we wait for it to become unlocked.
*/
if (op && op->delete_inode) {/*如果对超块操作op存在,
*且定义了超级块对象方法s_op->delete_inode()
*/
void (*delete)(struct inode *) = op->delete_inode;/*则调用该方法删除相应的磁盘索引节点*/
if (!is_bad_inode(inode))/*inode可被文件系统读取,即不是受损inode*/
DQUOT_INIT(inode);/*初始化inode限额*/
/* s_op->delete_inode internally recalls clear_inode() */
delete(inode);/*执行delete(),从底层文件系统中删除inode*/
} else/*如果对超块操作op不存在,或未定义超级块对象方法s_op->delete_inode()*/
clear_inode(inode);/*则调用 clear_inode()函数来清除这个inode对象,
*释放物理内存页
*/
if (inode->i_state != I_CLEAR)/*如果i_state不为I_CLEAR,即该inode中内容没有被清除*/
BUG();/*调用BUG()*/
} else {/*如果该inode的i_nlink不为0,
*则说明虽然没有人引用这个inode对象,
*但fs中还有文件链接与这个inode对象相关联,
*因此这个 inode对象有可能再次被引用
*/
if (!list_empty(&inode->i_hash)) {/*inode->i_hash不为空*/
if (!(inode->i_state & (I_DIRTY|I_LOCK))) {/*inode不脏且未被上锁*/
list_del(&inode->i_list);/*将这个 inode从其所属的“类型”链表中摘除*/
list_add(&inode->i_list, &inode_unused);/*并链接在inode_unused链表上*/
}
inodes_stat.nr_unused++;/*inode cache中的未使用的inode个数加一*/
spin_unlock(&inode_lock);/*解除自旋锁inode_lock*/
if (!sb || (sb->s_flags & MS_ACTIVE))/*sb不存在,或sb的标志位为MS_ACTIVE*/
return;/*直接返回*/
write_inode_now(inode, 1); /*同步写inode到磁盘*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
inodes_stat.nr_unused--;/*inode cache中的未使用的inode个数减一*/
list_del_init(&inode->i_hash);/*删除inode->i_hash,并重新初始化*/
}
list_del_init(&inode->i_list);/*删除inode->i_list,并重新初始化*/
inode->i_state|=I_FREEING;/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -