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

📄 inode.c

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

			/*
			 * 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 + -