⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 linux的文件系统的部分代码的详细注释
💻 C
📖 第 1 页 / 共 5 页
字号:
}


/*
 * This is called with the inode lock held. It searches
 * the in-use for freeable inodes, which are moved to a
 * temporary list and then placed on the unused list by
 * dispose_list. 
 *
 * We don't expect to have to call this very often.
 *
 * N.B. The spinlock is released during the call to
 *      dispose_list.
 */

/*宏定义判断一个inode是否是可以利用的未使用的inode*/
#define CAN_UNUSE(inode) \
	((((inode)->i_state | (inode)->i_data.nrpages) == 0)  && \
	 !inode_has_buffers(inode))
	 /*如果(inode)->i_state==0,且inode的地址空间总页数为0,
	   *且inode没有脏缓冲区,则inode是可用的未使用的inode
	   */

/*宏定义从entry结构指针得到inode结构体的指针*/
#define INODE(entry)	(list_entry(entry, struct inode, i_list))
/**
 * list_entry - get the struct for this entry
 * @ptr:	the &struct list_head pointer.
 * @type:	the type of the struct this is embedded in.
 * @member:	the name of the list_struct within the struct.
 */
 /*
#define list_entry(ptr, type, member) \
	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
*/

/*按照目标要求剪除索引节点缓冲区*/
void prune_icache(int goal)
{
	LIST_HEAD(list);
	struct list_head *entry, *freeable = &list;/*声明list_head类型指针entry,freeable*/
	int count;/*声明int型count*/
	struct inode * inode;/*声明inode指针*/

	spin_lock(&inode_lock);/*持有自旋锁inode_lock*/

	count = 0;/*置count为0*/
	entry = inode_unused.prev;/*entry指向inode_unused.prev*/
	while (entry != &inode_unused)/*循环扫描节点*/
	{
		struct list_head *tmp = entry;/*声明list_head型指针tmp,指向entry*/

		entry = entry->prev;/*置entry为entry->prev*/
		inode = INODE(tmp);/*宏定义从tmp结构指针得到inode结构体的指针*/
		if (inode->i_state & (I_FREEING|I_CLEAR|I_LOCK))/*inode正在释放、或已被清除、或被上锁*/
			continue;/*跳过本次循环,继续执行下次循环*/
		if (!CAN_UNUSE(inode))/*判断一个inode是否是可以利用的未使用的inode*/
			continue;/*不能利用,则跳过本次循环,继续执行下次循环*/
		if (atomic_read(&inode->i_count))/*原子操作读inode->i_count,判断其是否为0*/
			continue;/*跳过本次循环,继续执行下次循环*/
		list_del(tmp);/*将该 inode对象从tmp链表中删除*/
		list_del(&inode->i_hash);/*将该 inode对象从哈希链表中删除*/
		INIT_LIST_HEAD(&inode->i_hash);/*初始化哈希链表*/
		list_add(tmp, freeable);/*并链入freeable链表中*/
		inode->i_state |= I_FREEING;/*置inode标志为正在释放*/
		count++;/*count值加一*/
		if (!--goal)/*goal减一后值为0*/
			break;/*跳出循环体*/
	}
	inodes_stat.nr_unused -= count;/*cache中未使用的inode个数=原未使用个数-count*/
	spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/

	dispose_list(freeable);/*处理临时链表上的inode,
	                                    *删除inode的相关数据,销毁inode
	                                    */

	/* 
	 * If we didn't freed enough clean inodes schedule
	 * a sync of the dirty inodes, we cannot do it
	 * from here or we're either synchronously dogslow
	 * or we deadlock with oom.
	 */
	if (goal)/*goal不为0*/
		schedule_task(&unused_inodes_flush_task);/*并发执行进程上下文*/
	/*schedule_task - schedule a function for subsequent execution in process context.*/

}

/*缩短inode缓存*/
int shrink_icache_memory(int priority, int gfp_mask)
{
	int count = 0;/*声明int型count,置初值为0*/

	/*
	 * Nasty deadlock avoidance..
	 *
	 * We may hold various FS locks, and we don't
	 * want to recurse into the FS that called us
	 * in clear_inode() and friends..
	 */
	 /*避免死锁,我们尽可能持有各种文件系统锁
	  *避免递归的进入在clear_ionde及相关函数中调用我们的文件系统*/
	if (!(gfp_mask & __GFP_FS))
		return 0;

	count = inodes_stat.nr_unused / priority;/*为count赋值*/

	prune_icache(count);/*按照目标要求剪除索引节点缓冲区*/
	kmem_cache_shrink(inode_cachep);/*缩短slab分配缓存*/
	return 0;
}

/*
 * Called with the inode lock held.
 * NOTE: we are not increasing the inode-refcount, you must call __iget()
 * by hand after calling find_inode now! This simplifies iunique and won't
 * add any additional branch in the common code.
 */
 /*在某个链表中查找由(sb,ino)唯一标识的inode对象
  *调用find_inode()函数时一定要持有inode_lock锁
  */
static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque)
{
	struct list_head *tmp;/*声明链表指针tmp*/
	struct inode * inode;/*声明inode指针*/

	tmp = head;/*tmp指向head*/
	for (;;) {/*无条件循环*/
		tmp = tmp->next;/*tmp指向其后继next*/
		inode = NULL;/*赋值inode为空*/
		if (tmp == head)/*如果tmp现指向head,说明搜索完整个队列,
		                           *找不到需要的inode,返回NULL*/
			break;/*跳出循环体*/
		inode = list_entry(tmp, struct inode, i_hash);/*从list_head类型的域找到inode类型的域*/
		if (inode->i_ino != ino)/*inode的节点号与参数中的ino不同*/
			continue;/*跳过循环剩下的部分,直接进入下次循环*/
		if (inode->i_sb != sb)/*inode的相关超块与参数中的超块不符*/
			continue;/*跳过循环剩下的部分,直接进入下次循环*/
		if (find_actor && !find_actor(inode, ino, opaque))/*用参数组成的find_actor(inode, ino, opaque)
		                                                                               *与参数给定的find_actor不符
		                                                                               */
		/*typedef int (*find_inode_t)(struct inode *, unsigned long, void *);*/
			continue;/*跳过循环剩下的部分,直接进入下次循环*/
		break;/*跳出循环体*/
	}
	return inode;/*返回由(sb,ino)唯一标识的inode对象*/
}

/*
 * This just initializes the inode fields
 * to known values before returning the inode..
 *
 * i_sb, i_ino, i_count, i_state and the lists have
 * been initialized elsewhere..
 */
 /*初始化部分inode对象成员域*/
/*将一个刚从inode_cachep slab分配器中分配得到的inode对象中的某些成员初始化
为已知的值(通常为0),但是有一个例外,即链接数i_nlink被初始化为1。
这是一个静态的静态内部函数,因此它只能被inode.c中的其他函数所调用,
如:get_empty_inode()和get_new_inode()。
*/
static void clean_inode(struct inode *inode)
{
	static struct address_space_operations empty_aops;/*声明对地址空间操作的结构体empty_aops*/
	static struct inode_operations empty_iops;/*声明对索引节点操作的结构体empty_iops*/
	static struct file_operations empty_fops;/*声明对文件操作的结构体empty_fops*/
	memset(&inode->u, 0, sizeof(inode->u));/*用给定的值填充一块内存区域,即用0填充inode->u*/
	inode->i_sock = 0;/*初始化不是套接字*/
	inode->i_op = &empty_iops;/*初始化索引节点操作表指向empty_iops*/
	inode->i_fop = &empty_fops;/*初始化文件操作表指向empty_fops*/
	inode->i_nlink = 1;/*i初始化硬链接数为1*/
	atomic_set(&inode->i_writecount, 0);/*原子操作初始化写者使用计数为0*/
	inode->i_size = 0;/*初始化以字节为单位的文件大小为0*/
	inode->i_blocks = 0;/*初始化文件的块数为0*/
	inode->i_generation = 0;/*初始化索引节点版本号为0*/
	memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));/*用给定的值填充一块内存区域,
	                                                                                   *即用0填充节点的磁盘限额inode->i_dquot
	                                                                                   */
	inode->i_pipe = NULL;/*初始化管道信息为空*/
	inode->i_bdev = NULL;/*初始化块设备驱动为空*/
	inode->i_cdev = NULL;/*初始化字符设备为空*/
	inode->i_data.a_ops = &empty_aops;/*初始化设备地址空间的相应操作表指向empty_aops*/
	inode->i_data.host = inode;/*初始化设备地址空间的拥有者为inode*/
	inode->i_data.gfp_mask = GFP_HIGHUSER;/* 初始化设备地址空间的分配页方式为GFP_HIGHUSER*/
	inode->i_mapping = &inode->i_data;/*初始化备份地址空间i_mapping 指向inode的设备地址空间i_data*/
}

/**
 * get_empty_inode 	- obtain an inode
 *
 * This is called by things like the networking layer
 * etc that want to get an inode without any inode
 * number, or filesystems that allocate new inodes with
 * no pre-existing information.
 *
 * On a successful return the inode pointer is returned. On a failure
 * a %NULL pointer is returned. The returned inode is not on any superblock
 * lists.
 */
 /*从slab分配器中分配一个空的inode对象*/
/*
该函数通过调用alloc_inode宏从slab分配器中分配一个inode对象,
然后把除了i_count引用计数和链接计数i_nlink之外的所有域
都初始化为NULL(部分域的初始化通过调用clean_inode()函数来完成),
并将这个inode对象链入inode_in_use链表中。

Linux内核模块通常并不会调用这个函数来分配一个inode对象。
那些想获取一个没有索引节点号的inode对象的内核模块(如网络层等),
以及那些没有任何已知信息的fs,通常会用这个函数来获取一个新的inode对象。
*/
struct inode * get_empty_inode(void)
{
	static unsigned long last_ino;/*声明unsigned long型的last_ino*/
	struct inode * inode;/*声明inode指针*/

	spin_lock_prefetch(&inode_lock);/*预取持有自旋锁inode_lock*/
	
	inode = alloc_inode();/*调用alloc_inode宏从slab分配器中分配一个inode对象*/
	if (inode)/*inode分配成功*/
	{
		spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
		inodes_stat.nr_inodes++;/*inode对象总数加一*/
		list_add(&inode->i_list, &inode_in_use);/*将inode->i_list链入到inode_in_use链表中*/
		inode->i_sb = NULL;/*初始化相关超块为空*/
		inode->i_dev = 0;/*初始化设备标识符为0*/
		inode->i_blkbits = 0;/*初始化以位为单位的块大小为0*/
		inode->i_ino = ++last_ino;/*将last_ino先加一,再赋值给节点号inode->i_ino */
		inode->i_flags = 0;/*初始化文件系统标志为0*/
		atomic_set(&inode->i_count, 1);/*原子操作初始化引用计数为1*/
		inode->i_state = 0;/*初始化状态标志为0*/
		spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
		clean_inode(inode); /*初始化部分inode对象成员域*/
	}
	return inode; /*返回分配的一个空inode对象*/
}

/*
 * This is called without the inode lock held.. Be careful.
 *
 * We no longer cache the sb_flags in i_flags - see fs.h
 *	-- rmk@arm.uk.linux.org
 */
 /*用于得到一个新的inode对象*/
static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque)
{
	struct inode * inode;/*声明一个inode指针对象*/

	inode = alloc_inode();/*调用alloc_inode宏从inode_cachep这个slab分配器缓存中分配一个新的inode对象*/
	if (inode) {/*若分配了inode对象*/
		struct inode * old;/*声明一个inode指针对象old*/

		spin_lock(&inode_lock);/*持有自旋锁,实现对inode缓存链表的互斥访问*/
		/* We released the lock, so.. */
		/*由于在调用get_new_inode函数时,调用者已经释放了inode_lock锁,
		 *因此在inode_lock被释放到调用 get_new_inode函数期间,
		 *其他内核模块有可能已经创建了(sb,ino)所确定的索引节点。
		 *所以,get_new_inode函数必须重新调用find_inode()函数,
		 *以再一次在哈希链表中查找是否已存在相应的inode对象。
               */
		old = find_inode(sb, ino, head, find_actor, opaque);/*在哈希链表中查找是否已存在相应的inode对象*/
		if (!old) {/*如果find_inode()返回NULL,则对先前所分配的inode对象进行初始化*/
			inodes_stat.nr_inodes++;/*inode对象总数加一*/
			list_add(&inode->i_list, &inode_in_use);/*将inode->i_list链入到inode_in_use链表中*/
			list_add(&inode->i_hash, head);/*将inode->i_hash链入到参数所给的head链表中*/
			inode->i_sb = sb;/*初始化相关超块为参数所给的超块sb*/
			inode->i_dev = sb->s_dev;/*初始化设备标识符i_dev 为参数所给超块的设备标识符s_dev*/
			inode->i_blkbits = sb->s_blocksize_bits;/*初始化inode的以位为单位的块大小
			                                                             *为参数所给超块以位为单位的块大小s_blocksize_bits
			                                                             */
			inode->i_ino = ino;/*初始化节点号为参数ino的值 */
			inode->i_flags = 0;/*初始化文件系统标志为0*/
			atomic_set(&inode->i_count, 1);/*原子操作初始化引用计数为1*/
			inode->i_state = I_LOCK;/*初始化状态标志为I_LOCK,即已上锁*/
			spin_unlock(&inode_lock); /*释放自旋锁inode_lock*/

		       /*调用clean_inode()函数和超级块的 s_op->read_inode()方法,
		       以从块设备上读取磁盘索引节点的内容
		       */
			clean_inode(inode); /*初始化部分inode对象成员域*/

			/* reiserfs specific hack right here.  We don't
			** want this to last, and are looking for VFS changes
			** that will allow us to get rid of it.
			** -- mason@suse.com 
			*/
			if (sb->s_op->read_inode2) {/*如果sb->s_op->read_inode2函数存在*/
				sb->s_op->read_inode2(inode, opaque) ;/*以inode->i_ino为索引,
				                                                                *从磁盘上读取索引节点,
				                                                                *并填充内存中对应的inode结构的剩余部分
				                                                                */
			} else {/*如果sb->s_op->read_inode2函数不存在*/
				sb->s_op->read_inode(inode);/*以inode->i_ino为索引,
				                                               *从磁盘上读取索引节点,
				                                               *并填充内存中对应的inode结构的剩余部分

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -