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

📄 inode.c

📁 linux的文件系统的部分代码的详细注释
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	write_inode_now	-	write an inode to disk
 *	@inode: inode to write to disk
 *	@sync: whether the write should be synchronous or not
 *
 *	This function commits an inode to disk immediately if it is
 *	dirty. This is primarily needed by knfsd.
 */
 /*写inode到磁盘*/
void write_inode_now(struct inode *inode, int sync)
{
	struct super_block * sb = inode->i_sb;/*声明一个超块指针,指向inode->i_sb*/

	if (sb) {/*如果sb不为空*/
		spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
		while (inode->i_state & I_DIRTY)/*当inode脏时*/
			sync_one(inode, sync);
		spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
		if (sync)/*需要同步写*/
			wait_on_inode(inode);/*测试一个inode对象是否已经被加锁,加锁则等待其被解锁*/
	}
	else/*sb不存在*/
		printk(KERN_ERR "write_inode_now: no super block\n");/*输出错误提示*/
}

/**
 * generic_osync_inode - flush all dirty data for a given inode to disk
 * @inode: inode to write
 * @datasync: if set, don't bother flushing timestamps
 *
 * This can be called by file_write functions for files which have the
 * O_SYNC flag set, to flush dirty writes to disk.  
 */
/*刷新所给inode的脏数据到磁盘*/
int generic_osync_inode(struct inode *inode, int what)
{
	int err = 0, err2 = 0, need_write_inode_now = 0;
	
	/* 
	 * WARNING
	 *
	 * Currently, the filesystem write path does not pass the
	 * filp down to the low-level write functions.  Therefore it
	 * is impossible for (say) __block_commit_write to know if
	 * the operation is O_SYNC or not.
	 *
	 * Ideally, O_SYNC writes would have the filesystem call
	 * ll_rw_block as it went to kick-start the writes, and we
	 * could call osync_inode_buffers() here to wait only for
	 * those IOs which have already been submitted to the device
	 * driver layer.  As it stands, if we did this we'd not write
	 * anything to disk since our writes have not been queued by
	 * this point: they are still on the dirty LRU.
	 * 
	 * So, currently we will call fsync_inode_buffers() instead,
	 * to flush _all_ dirty buffers for this inode to disk on 
	 * every O_SYNC write, not just the synchronous I/Os.  --sct
	 */

	if (what & OSYNC_METADATA)
		err = fsync_inode_buffers(inode);/*同步所有inode的脏缓冲区到磁盘*/
	       /* Synchronise all the inode's dirty buffers to the disk.*/
	if (what & OSYNC_DATA)
		err2 = fsync_inode_data_buffers(inode);/*同步所有inode的脏数据缓冲区到磁盘*/
	if (!err)/*err==0*/
		err = err2;/*err赋值为err2*/

	spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
	if ((inode->i_state & I_DIRTY) &&
	    ((what & OSYNC_INODE) || (inode->i_state & I_DIRTY_DATASYNC)))
		need_write_inode_now = 1;
	spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/

	if (need_write_inode_now)/*如果需要现在写inode到磁盘*/
		write_inode_now(inode, 1); /*写inode到磁盘*/
	else/*不需要现在就写inode*/
		wait_on_inode(inode);/*测试一个inode对象是否已经被加锁,
		                                      *加锁则等待其被解锁
		                                      */

	return err;
}

/**
 * clear_inode - clear an inode
 * @inode: inode to clear
 *
 * This is called by the filesystem to tell us
 * that the inode is no longer useful. We just
 * terminate it with extreme prejudice.
 */
 /*清除一个inode对象中的内容*/
/*
在调用destroy_inode()函数释放一个inode对象之前,
通常调用该函数来清除该inode对象中内容,
如:使inode引用的缓冲区无效、解除对其它对象的引用等。
*/
void clear_inode(struct inode *inode)
{
	invalidate_inode_buffers(inode);/*使inode中任何且所有的脏缓冲链表无效,即清除*/
/*
 * Invalidate any and all dirty buffers on a given inode.  We are
 * probably unmounting the fs, but that doesn't mean we have already
 * done a sync().  Just drop the buffers from the inode list.
 */
       
	if (inode->i_data.nrpages)/*总页数不等于0*/
		BUG();/*调用BUG()*/
	if (!(inode->i_state & I_FREEING))/*inode不是正在被释放*/
		BUG();/*调用BUG()*/
	if (inode->i_state & I_CLEAR)/*inode->i_state是I_CLEAR态*/
		BUG();/*调用BUG()*/
	wait_on_inode(inode);/*测试一个inode对象是否已经被加锁,加锁则等待其被解锁*/
	DQUOT_DROP(inode);/*对inode相应的文件系统限额停止*/
	if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode)
	/*inode->i_sb 存在,inode->i_sb->s_op 存在,i_sb->s_op->clear_inode函数存在*/
		inode->i_sb->s_op->clear_inode(inode);/*调用clear_inode()函数,
	                                                                       *释放inode,并清空包含相关数据的所有页面
	                                                                       */
	if (inode->i_bdev)/*inode->i_bdev块设备驱动存在*/
		bd_forget(inode);/*删除inode->i_devices,并重新初始化,
		                              *置inode->i_bdev块设备驱动为空,
		                              *inode->i_mapping 指向inode->i_data
		                              */
		                              /*
	list_del_init(&inode->i_devices);list_del_init - deletes entry from list and reinitialize it.
	inode->i_bdev = NULL;
	inode->i_mapping = &inode->i_data;*/
	else if (inode->i_cdev) {/*inode->i_cdev字符设备存在,inode->i_bdev块设备驱动不存在*/
		cdput(inode->i_cdev);/*原子操作cdev->count减一,给cdev_lock上锁,
		                                     *删除cdev->hash,解锁,释放已分配的缓冲
		                                     */
		inode->i_cdev = NULL;/*清空i_cdev */
	}
	inode->i_state = I_CLEAR;/*设置i_state为清除态,即该inode中内容已被清除*/
}

/*
 * Dispose-list gets a local list with local inodes in it, so it doesn't
 * need to worry about list corruption and SMP locks.
 */
 /*清理处置一个inode链表*/
static void dispose_list(struct list_head * head)
{
	struct list_head * inode_entry;/*声明list_head型指针inode_entry*/
	struct inode * inode;/*声明inode指针*/

       /*inode_entry赋值为head->next,当inode_entry不指向head时,持续循环*/
	while ((inode_entry = head->next) != head)
	{
		list_del(inode_entry);/*将该inode_entry对象从原来的链表中删除*/

		inode = list_entry(inode_entry, struct inode, i_list);/*inode指向从inode_entry的域找到inode类型的域*/
		if (inode->i_data.nrpages)/*inode的地址空间总页数不为0*/
			truncate_inode_pages(&inode->i_data, 0);
		       /*截短inode的页缓冲,从超过偏移量的部分移出,
			  *如果该页被锁,那么等待该页被解锁
			  */
		clear_inode(inode); /*清除一个inode对象中的内容*/
		destroy_inode(inode);/*释放inode指针指向的inode对象*/
		inodes_stat.nr_inodes--;/*cache中的inode对象总数减一*/
	}
}

/*
 * Invalidate all inodes for a device.
 */
 /*清理回收一个设备的所有inode*/
static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose)
{
	struct list_head *next;/*声明list_head 型指针next*/
	int busy = 0, count = 0;/*声明int型busy、count,并均赋初值为0*/

	next = head->next;/*next指向head->next*/
	for (;;) {/*无条件循环*/
		struct list_head * tmp = next;/*声明list_head 型指针tmp*/
		struct inode * inode;/*声明inode指针*/

		next = next->next;/*next指向next->next*/
		if (tmp == head)/*如果tmp指向head*/
			break;/*跳出循环*/
		inode = list_entry(tmp, struct inode, i_list);/*inode指向从list_head的域找到inode类型的域*/
		if (inode->i_sb != sb)/*inode的相应块设备i_sb 指针不指向sb*/
			continue;/*跳过本次循环剩余的部分,直接执行下次循环*/
		invalidate_inode_buffers(inode);/*使任何所有inode上的脏缓冲区无效*/
		if (!atomic_read(&inode->i_count)) {/*原子操作读inode->i_count,且inode->i_count为0*/
			list_del_init(&inode->i_hash);/*删除inode->i_hash,并将其初始化*/
			list_del(&inode->i_list);/*将该 inode对象从原来的“类型”链表中删除*/
			list_add(&inode->i_list, dispose);/*并将其链到链表dispose上*/
			inode->i_state |= I_FREEING;/*设置inode->i_state为I_FREEING空闲态*/
			count++;/*count加一*/
			continue;/*跳过本次循环剩余的部分,直接执行下次循环*/
		}
		busy = 1;/*置busy为1*/
	}
	/* only unused inodes may be cached with i_count zero */
	inodes_stat.nr_unused -= count;/*cache中的未使用的inode个数=nr_unused -count*/
	return busy;/*返回busy*/
}

/*
 * This is a two-stage process. First we collect all
 * offending inodes onto the throw-away list, and in
 * the second stage we actually dispose of them. This
 * is because we don't want to sleep while messing
 * with the global lists..
 */
 
/**
 *	invalidate_inodes	- discard the inodes on a device
 *	@sb: superblock
 *
 *	Discard all of the inodes for a given superblock. If the discard
 *	fails because there are busy inodes then a non zero value is returned.
 *	If the discard is successful all the inodes have been discarded.
 */
 /*丢弃一个设备上的inode*/
int invalidate_inodes(struct super_block * sb)
{
	int busy;/*声明int型busy*/
	LIST_HEAD(throw_away);/*创建一个throw_away队列*/

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

	/*顺序搜索队列inode_in_use,
	 *将其中属于sb、引用计数为0的inode从hash表中摘下,
	 *从inode_in_use队列中摘下,加入throw_away队列
	 */
	busy = invalidate_list(&inode_in_use, sb, &throw_away);

	/*顺序搜索队列inode_unused,
	 *将其中属于sb、引用计数为0的inode从hash表中摘下,
	 *从inode_unused队列中摘下,加入throw_away队列
	 */
	busy |= invalidate_list(&inode_unused, sb, &throw_away);

	/*顺序搜索队列sb->s_dirty,
	 *将其中属于sb、引用计数为0的inode从hash表中摘下,
	 *从sb->s_dirty队列中摘下,加入throw_away队列
	 */
	busy |= invalidate_list(&sb->s_dirty, sb, &throw_away);

	/*顺序搜索队列sb->s_locked_inodes,,
	 *将其中属于sb、引用计数为0的inode从hash表中摘下,
	 *从sb->s_locked_inodes,队列中摘下,加入throw_away队列
	 */
	busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away);
	spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/

	dispose_list(&throw_away);/*清理throw_away队列中的所有inode*/

	return busy;
}

 /*整理一个设备*/
int invalidate_device(kdev_t dev, int do_sync)
{
	struct super_block *sb;/*声明super_block型指针sb*/
	int res;/*声明int型res*/

	if (do_sync)/*做同步处理,do_sync==1*/
		fsync_dev(dev);/*同步缓冲区、inode同步回写、
		                            *inode限额同步、同步文件系统
		                            */

	res = 0;/*置res为0*/
	sb = get_super(dev);/*获得一个设备的超块*/
/**
 *	get_super	-	get the superblock of a device
 *	@dev: device to get the superblock for
 *	
 *	Scans the superblock list and finds the superblock of the file system
 *	mounted on the device given. %NULL is returned if no match is found.
 */
	if (sb) {
		/*
		 * no need to lock the super, get_super holds the
		 * read semaphore so the filesystem cannot go away
		 * under us (->put_super runs with the write lock
		 * hold).
		 */
		shrink_dcache_sb(sb);/*缩短超块sb的目录项缓存*/
/**
 * shrink_dcache_sb - shrink dcache for a superblock
 * @sb: superblock
 *
 * Shrink the dcache for the specified super block. This
 * is used to free the dcache before unmounting a file
 * system
 */
		res = invalidate_inodes(sb); /*丢弃一个设备上的inode*/
		drop_super(sb);/*卸载超块,读引用模块的信号量加一,减少一个超块的引用*/
	}
	invalidate_buffers(dev);/*使缓冲区无效*/
	return res;/*返回res*/

⌨️ 快捷键说明

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