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

📄 inode.c

📁 linux的文件系统的部分代码的详细注释
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * linux/fs/inode.c
 *
 * (C) 1997 Linus Torvalds
 */

#include <linux/config.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/dcache.h>
#include <linux/init.h>
#include <linux/quotaops.h>
#include <linux/slab.h>
#include <linux/cache.h>
#include <linux/swap.h>
#include <linux/swapctl.h>
#include <linux/prefetch.h>
#include <linux/locks.h>

/*
 * New inode.c implementation.
 *
 * This implementation has the basic premise of trying
 * to be extremely low-overhead and SMP-safe, yet be
 * simple enough to be "obviously correct".
 *
 * Famous last words.
 */

/* inode dynamic allocation 1999, Andrea Arcangeli <andrea@suse.de> */

/* #define INODE_PARANOIA 1 */
/* #define INODE_DEBUG 1 */

/*
 * Inode lookup is no longer as critical as it used to be:
 * most of the lookups are going to be through the dcache.
 */
#define I_HASHBITS	i_hash_shift/*宏定义哈希链表表头数组的位数*/
#define I_HASHMASK	i_hash_mask/*宏定义哈希链表表头数组的位掩码*/

static unsigned int i_hash_mask;/*哈希链表表头数组的位掩码*/
static unsigned int i_hash_shift;/*哈希链表表头数组的位数*/

/*
 * Each inode can be on two separate lists. One is
 * the hash list of the inode, used for lookups. The
 * other linked list is the "type" list:
 *  "in_use" - valid inode, i_count > 0, i_nlink > 0
 *  "dirty"  - as "in_use" but also dirty
 *  "unused" - valid inode, i_count = 0
 *
 * A "dirty" list is maintained for each super block,
 * allowing for low-overhead inode sync() operations.
 */
 /*每一个inode对象都会存在于两个分离的双向链表中:
一个是inode哈希链表inode_hashtable,用来加快inode查找,
每个inode对象都通过i_hash指针链入哈希链表中。
另一个是inode的“类型”链表:
 如果i_count>0、i_nlink>0,且该inode不脏,
 则这个inode就通过其i_list指针链入系统全局的inode_in_use双向链表。
 如果i_count>0、i_nlink>0,但是这个inode为脏(即i_state域中设置了I_DIRTY标志),
 则这个inode通过i_list指针链入他所属的super_block对象的s_dirty链表。
 如果i_count=0,则通过其i_list链入inode_unused链表。
对于那些不属于任何超级块对象(即i_sb=NULL)的匿名inode对象,
则通过i_hash指针链入系统全局的匿名inode哈希链表anon_hash_chain。
*/

static LIST_HEAD(inode_in_use);/*正在使用的未更改信息的节点链表*/
static LIST_HEAD(inode_unused);/*未使用的信息节点链表*/
static struct list_head *inode_hashtable;/*索引节点哈希链表*/
static LIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb *//*匿名索引节点哈希链表*/
/*每个超级块对象super_block中还有一条被修改过的、且正在使用的inode双向链表s_dirty*/

/*
 * A simple spinlock to protect the list manipulations.
 *
 * NOTE! You also have to own the lock if you change
 * the i_state of an inode while it is in use..
 */
 /*定义了自旋锁inode_lock,来实现对所有inode缓存链表的互斥访问。
  *任何访问任意一条inode缓存链表的代码段,
  *都必须通过调用spin_lock()函数持有该自旋锁,
  *并在结束访问后通过spin_unlock()释放该自旋锁。
  *如果要改变一个正在使用的inode对象的i_state域,也必须先持有该自旋锁
  */
static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;/*定义静态自旋锁变量inode_lock*/

/*
 * Statistics gathering..
 */
struct inodes_stat_t inodes_stat;
/*全局变量inodes_stat定义了inode cache的统计信息,
主要包括cache中的inode对象总数和其中未使用的inode个数,具体定义如下:
struct {
int nr_inodes;
int nr_unused;
int dummy[5];
} inodes_stat;
*/

/*索引节点的slab分配缓存由一个kmem_cache_t类型的指针变量inode_cachep来定义,
 *这个slab分配器缓存是在inode cache的初始化函数inode_init()中
 *通过kmem_cache_create()函数来创建的。
 */
static kmem_cache_t * inode_cachep;/*定义静态kmem_cache_t类型的指针变量inode_cachep,
                                                           *用来给inode的slab分配缓存
                                                           */

/*宏定义分配索引节点*/
#define alloc_inode() \
	 ((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL)) 
	 /*从inode_cachep slab分配器缓存中分配一个inode对象*/

/*释放inode指针指向的inode对象*/
static void destroy_inode(struct inode *inode) 
{
	if (inode_has_buffers(inode))/*如果i_dirty_buffers链表不空或i_dirty_data_buffers链表不空*/
		BUG();/*调用BUG()*/
	kmem_cache_free(inode_cachep, (inode)); /*将一个不再使用的inode对象释放给slab分配器*/
}


/*
 * These are initializations that only need to be done
 * once, because the fields are idempotent across use
 * of the inode, so let the slab aware of that.
 */
 /*只需要做一次的初始化函数*/
static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
{
	struct inode * inode = (struct inode *) foo;
	/*声明inode指针,指向foo的强制类型转换的inode*/

	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
	    SLAB_CTOR_CONSTRUCTOR)/*判断构造器标志是否被设置过*/
	{
		memset(inode, 0, sizeof(*inode));/*用给定的值填充一块内存区域,即用0填充inode*/
		/*
               * memset - Fill a region of memory with the given value
               * @s: Pointer to the start of the area.
               * @c: The byte to fill the area with
               * @count: The size of the area.*/
		init_waitqueue_head(&inode->i_wait);/*初始化inode->i_wait等待队列为空*/
		INIT_LIST_HEAD(&inode->i_hash);/*初始化inode->i_hash链表为空*/
		INIT_LIST_HEAD(&inode->i_data.clean_pages);/*初始化inode->i_data.clean_pages链表为空*/
		INIT_LIST_HEAD(&inode->i_data.dirty_pages);/*初始化inode->i_data.dirty_pages链表为空*/
		INIT_LIST_HEAD(&inode->i_data.locked_pages);/*初始化inode->i_data.locked_pages链表为空*/
		INIT_LIST_HEAD(&inode->i_dentry);/*初始化inode->i_dentry链表为空*/
		INIT_LIST_HEAD(&inode->i_dirty_buffers);/*初始化inode->i_dirty_buffers链表为空*/
		INIT_LIST_HEAD(&inode->i_dirty_data_buffers);/*初始化inode->i_dirty_data_buffers链表为空*/
		INIT_LIST_HEAD(&inode->i_devices);/*初始化inode->i_devices链表为空*/
		sema_init(&inode->i_sem, 1);/*初始化信号量inode->i_sem的count值为1,wait等待队列为空*/
		sema_init(&inode->i_zombie, 1);/*初始化信号量inode->i_zombie的count值为1,wait等待队列为空*/
		spin_lock_init(&inode->i_data.i_shared_lock);/*初始化inode->i_data.i_shared_lock自旋锁*/
	}
}

/*
 * Put the inode on the super block's dirty list.
 *
 * CAREFUL! We mark it dirty unconditionally, but
 * move it onto the dirty list only if it is hashed.
 * If it was not hashed, it will never be added to
 * the dirty list even if it is later hashed, as it
 * will have been marked dirty already.
 *
 * In short, make sure you hash any inodes _before_
 * you start marking them dirty..
 */

/*对上面注释的翻译:
 *把inode放到超块的dirty list上,标记脏是无条件的,
 *但是只有当被散列后才可以将inode移到dirty list。
 *如果没有被散列过,即使以后将被散列,
 *也不能加到dirty list上,虽然它已经被标记为脏了

 *总之,在标记inode为脏前要确认其已被散列
 */ 
/**
 *	__mark_inode_dirty -	internal function
 *	@inode: inode to mark
 *	@flags: what kind of dirty (i.e. I_DIRTY_SYNC)
 *	Mark an inode as dirty. Callers should use mark_inode_dirty or
 *  	mark_inode_dirty_sync.
 */
 /*标记一个inode为脏,
  *将一个位于inode_in_use中的一个脏inode转移到超块的s_dirty队列中
  */
void __mark_inode_dirty(struct inode *inode, int flags)
{
	struct super_block * sb = inode->i_sb;/*声明一个超块指针,指向inode->i_sb*/

	if (!sb)/*inode->i_sb为空*/
		return;/*直接返回*/

	/* Don't do this for I_DIRTY_PAGES - that doesn't actually dirty the inode itself *//*不需要判断I_DIRTY_PAGES */
	if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {/*判断flags是否要设置为I_DIRTY_SYNC或I_DIRTY_DATASYNC*/
		if (sb->s_op && sb->s_op->dirty_inode)/*判断sb->s_op 和sb->s_op->dirty_inode函数是否存在*/
			sb->s_op->dirty_inode(inode);/*存在,调用函数将inode置脏*/
	}

	/* avoid the locking if we can */
	if ((inode->i_state & flags) == flags)/*检测需要标志的flag是否已经在i_state上标记过*/
		return;/*已标记过,则直接返回*/

	spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
	if ((inode->i_state & flags) != flags) {/*需要标志的flag没有在i_state上标记过*/
		inode->i_state |= flags;/*i_state与flag做按位或运算,结果赋值给i_state,
		                                       *即将需要标志的位置进行重新标志
		                                       */
		/* Only add valid (ie hashed) inodes to the dirty list */
		if (!(inode->i_state & I_LOCK) && !list_empty(&inode->i_hash)) {/*i_state的I_LOCK位不为1,且inode->i_hash不为空*/
			list_del(&inode->i_list);/*将该 inode对象从原来的“类型”链表中删除*/
			list_add(&inode->i_list, &sb->s_dirty);/*并将其链入到sb->s_dirty链表中*/
		}
	}
	spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
}

/*等待一个inode对象被解锁的函数*/
static void __wait_on_inode(struct inode * inode)
{
	DECLARE_WAITQUEUE(wait, current);/*宏定义一个wait_queue_t,用当前的task_struct定义*/

	add_wait_queue(&inode->i_wait, &wait);/*将wait_queue_t类型的wait添加到wait_queue_head_t型的inode->i_wait中 */
repeat:
	set_current_state(TASK_UNINTERRUPTIBLE);/*设置当前进程的task_struct的state为不可中断*/
	if (inode->i_state & I_LOCK) {/*如果i_state的I_LOCK位为1,即inode被加锁*/
		schedule();/*执行调度程序函数*/
		goto repeat;/*跳转到repeat程序段*/
	}
	remove_wait_queue(&inode->i_wait, &wait);/*将wait_queue_t类型的wait从wait_queue_head_t型的inode->i_wait中删除 */
	current->state = TASK_RUNNING;/*设置当前进程的task_struct的state为运行态*/
}

/*测试一个inode对象是否已经被加锁,加锁则等待其被解锁的函数*/
static inline void wait_on_inode(struct inode *inode)
{
	if (inode->i_state & I_LOCK)/*测试一个inode对象是否已经被加锁*/
		__wait_on_inode(inode);/*被加锁,则调用__wait_on_inode()函数等待该inode被解锁*/
}

/*将指定inode对象写入设备*/
static inline void write_inode(struct inode *inode, int sync)
{
       /*inode->i_sb存在,inode->i_sb->s_op存在,
        *inode->i_sb->s_op->write_inode ()函数存在,且不是受损的inode
        */
	if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->write_inode && !is_bad_inode(inode))
		inode->i_sb->s_op->write_inode(inode, sync);/*调用write_inode ()函数把inode回写到磁盘
	                                                                                 *更新某个文件系统的inode
	                                                                                 */
}

/*内联函数__iget()用来增加一个inode对象的引用计数*/
static inline void __iget(struct inode * inode)
{
	if (atomic_read(&inode->i_count)) {/*判断inode->i_count的当前值*/
		atomic_inc(&inode->i_count);/*如果不为0,则将i_count加1*/
		return;/*直接返回*/
	}
	atomic_inc(&inode->i_count);/*如果为0,则先将i_count加1*/
	if (!(inode->i_state & (I_DIRTY|I_LOCK))) {/*该inode对象不脏,也没有被上锁*/
		list_del(&inode->i_list);/*将该 inode对象从原来的“类型”链表(应该在inode_unused链表中)中删除*/
		list_add(&inode->i_list, &inode_in_use);/*并将其链入到inode_in_use链表中*/
	}
	inodes_stat.nr_unused--;/*将inode cache 统计信息中的未使用inode个数减1*/
}

/*将一个指定的脏inode同步写回块设备*/
static inline void __sync_one(struct inode *inode, int sync)
/*
Avoid looping in write_inode_now since the sync_one changes now ensure __sync_one 
is called once the inode is unlocked.
*/
{
	unsigned dirty;/*声明unsigned类型变量dirty*/

	list_del(&inode->i_list);/*将该 inode对象从原来的“类型”链表中删除*/
	list_add(&inode->i_list, &inode->i_sb->s_locked_inodes);/*并将其链入到inode->i_sb->s_locked_inodes链表中*/

	if (inode->i_state & I_LOCK)/*inode被上锁*/
		BUG();/*调用BUG()*/

	/* Set I_LOCK, reset I_DIRTY */
	dirty = inode->i_state & I_DIRTY;/*将i_state与I_DIRTY相与的结果赋值给dirty*/
	inode->i_state |= I_LOCK;/*i_state与I_LOCK做按位或运算,结果赋值给i_state,
		                                   *即将需要标志的位置进行重新标志,标志为上锁
		                                   */
	inode->i_state &= ~I_DIRTY;/*清除脏位*/
	spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/

⌨️ 快捷键说明

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