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

📄 inode.c

📁 linux的文件系统的部分代码的详细注释
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* No such thing, so let's try location of indirect block */       /*再查找间接块*/	if (ind->bh)		return ind->bh->b_blocknr;/*返回目录块本身*/	/*	 * It is going to be refered from inode itself? OK, just put it into	 * the same cylinder group then.	 */	 /*返回该inode所在块组的第一个块*/	return (inode->u.ext2_i.i_block_group * 		EXT2_BLOCKS_PER_GROUP(inode->i_sb)) +	       le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_first_data_block);}/** *	ext2_find_goal - find a prefered place for allocation. *	@inode: owner *	@block:  block we want *	@chain:  chain of indirect blocks *	@partial: pointer to the last triple within a chain *	@goal:	place to store the result. * *	Normally this function find the prefered place for block allocation, *	stores it in *@goal and returns zero. If the branch had been changed *	under us we return -EAGAIN. *//*寻找一个合适的块进行分配*//*先按顺序试图分配下一个连续的物理块号,  *如果失败就调用ext2_find_near()函数从附近找一个物理块号。  *查找规则是:先看当前位置的前面附近是否有合适块,  *再看指针是否在间接块号中,  *最后,如果指针在节点上,就分配用一柱面的块  */static inline int ext2_find_goal(struct inode *inode,/*文件节点*/				 long block,/*需分配的逻辑块号*/				 Indirect chain[4],/*间接块的链表*/				 Indirect *partial,/*指向chain中最后的三次间接块*/				 unsigned long *goal)/*存放找到的物理块号*/{	/* Writer: ->i_next_alloc* */	/*如果逻辑块号正好是按顺序中的下一块号	 *即当要分配的文件块号恰好为前次分配操作的后继文件块号,	 *预示着使用预分配块的可能性	 */	if (block == inode->u.ext2_i.i_next_alloc_block + 1) {		inode->u.ext2_i.i_next_alloc_block++;		inode->u.ext2_i.i_next_alloc_goal++;	} 	/* Writer: end */	/* Reader: pointers, ->i_next_alloc* */	if (verify_chain(chain, partial)) {/*检验iblock的索引路径有没有发生变化*/		/*		 * try the heuristic for sequential allocation,		 * failing that at least try to get decent locality.		 */		 /*得到顺序中的下一个物理块号*/		if (block == inode->u.ext2_i.i_next_alloc_block)			*goal = inode->u.ext2_i.i_next_alloc_goal;/*使用原分配点的下一块*/		/*得到附近的物理块号*/		if (!*goal)			*goal = ext2_find_near(inode, partial);/*在当前目录块上寻找文件的边缘区域*/		return 0;	}	/* Reader: end */	return -EAGAIN;}/** *	ext2_alloc_branch - allocate and set up a chain of blocks. *	@inode: owner *	@num: depth of the chain (number of blocks to allocate) *	@offsets: offsets (in the blocks) to store the pointers to next. *	@branch: place to store the chain in. * *	This function allocates @num blocks, zeroes out all but the last one, *	links them into chain and (if we are synchronous) writes them to disk. *	In other words, it prepares a branch that can be spliced onto the *	inode. It stores the information about that chain in the branch[], in *	the same format as ext2_get_branch() would do. We are calling it after *	we had read the existing part of chain and partial points to the last *	triple of that (one with zero ->key). Upon the exit we have the same *	picture as after the successful ext2_get_block(), excpet that in one *	place chain is disconnected - *branch->p is still zero (we did not *	set the last link), but branch->key contains the number that should *	be placed into *branch->p to fill that gap. * *	If allocation fails we free all blocks we've allocated (and forget *	their buffer_heads) and return the error value the from failed *	ext2_alloc_block() (normally -ENOSPC). Otherwise we set the chain *	as described above and return 0. *//*分配并建立一个块链表*/static int ext2_alloc_branch(struct inode *inode,/*需分配块的节点*/			     int num,/*间接块的深度,例如:二次间接,num=1*/			     unsigned long goal,			     int *offsets,/*数组offset[num]*/			     Indirect *branch)/*储存链表的地方*/{	int blocksize = inode->i_sb->s_blocksize;	int n = 0;	int err;	int i;	int parent = ext2_alloc_block(inode, goal, &err);/*分配块*/	branch[0].key = cpu_to_le32(parent);/*分配一块作为iblock在branch[0]上所指的下一块*/	if (parent) for (n = 1; n < num; n++) {		struct buffer_head *bh;		/* Allocate the next block */		/*分配下一个块,作为iblock在parent所指的下一块,		 *可能是目录块,也可能是数据块		 */		int nr = ext2_alloc_block(inode, parent, &err);/*分配块*/		if (!nr)			break;		branch[n].key = cpu_to_le32(nr);		/*		 * Get buffer_head for parent block, zero it out and set 		 * the pointer to new one, then send parent to disk.		 */		bh = sb_getblk(inode->i_sb, parent); /*得到父块的buffer_head结构*/		lock_buffer(bh);/*给缓冲区上锁*/		memset(bh->b_data, 0, blocksize);/*将buffer设置为0*/		branch[n].bh = bh;		branch[n].p = (u32*) bh->b_data + offsets[n];		*branch[n].p = branch[n].key;/*初始化iblock在parent块中的索引*/		mark_buffer_uptodate(bh, 1);/*把buffer标志为更新*/		unlock_buffer(bh);/*给缓冲区解锁*/		mark_buffer_dirty_inode(bh, inode);/*将节点与buffer标志为脏*/		if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {			ll_rw_block (WRITE, 1, &bh);/*将bh写入块设备*/			wait_on_buffer (bh);/*在等待队列上等待buffer写入设备*/		}		parent = nr;	}	if (n == num)		return 0;/*循环自然结束*/	/* Allocation failed, free what we already allocated */	/*分配失败时,释放已被分配的块*/	for (i = 1; i < n; i++)		bforget(branch[i].bh);	for (i = 0; i < n; i++)		ext2_free_blocks(inode, le32_to_cpu(branch[i].key), 1);/*释放块*/	return err;}/** *	ext2_splice_branch - splice the allocated branch onto inode. *	@inode: owner *	@block: (logical) number of block we are adding *	@chain: chain of indirect blocks (with a missing link - see *		ext2_alloc_branch) *	@where: location of missing link *	@num:   number of blocks we are adding * *	This function verifies that chain (up to the missing link) had not *	changed, fills the missing link and does all housekeeping needed in *	inode (->i_blocks, etc.). In case of success we end up with the full *	chain to new block and return 0. Otherwise (== chain had been changed) *	we free the new blocks (forgetting their buffer_heads, indeed) and *	return -EAGAIN. *//*接合块链表*/static inline int ext2_splice_branch(struct inode *inode,				     long block,				     Indirect chain[4],				     Indirect *where,				     int num){	int i;	/* Verify that place we are splicing to is still there and vacant */       /*检验要结合的是否还在并是空闲的*/	/* Writer: pointers, ->i_next_alloc* */	if (!verify_chain(chain, where-1) || *where->p)/*检验iblock的索引路径有没有发生变化*/		/* Writer: end */		goto changed;	/* That's it */	*where->p = where->key;	inode->u.ext2_i.i_next_alloc_block = block;	inode->u.ext2_i.i_next_alloc_goal = le32_to_cpu(where[num-1].key);       /*该逻辑块所对应的物理块,作为下一次分配的目的块*/       	/* Writer: end */	/* We are done with atomic stuff, now do the rest of housekeeping */	inode->i_ctime = CURRENT_TIME;/*节点的修改时间置为当前时间*/	/* had we spliced it onto indirect block? */	if (where->bh) {		mark_buffer_dirty_inode(where->bh, inode);		if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {			ll_rw_block (WRITE, 1, &where->bh);/*将bh写入块设备*/			wait_on_buffer(where->bh);/*在等待队列上等待buffer写入设备*/		}	}	if (IS_SYNC(inode) || inode->u.ext2_i.i_osync)/*inode标志需要同步*/		ext2_sync_inode (inode);/*把节点缓存中数据写入设备*/	else		mark_inode_dirty(inode);/*标志inode为脏*/	return 0;changed:	for (i = 1; i < num; i++)		bforget(where[i].bh);	for (i = 0; i < num; i++)		ext2_free_blocks(inode, le32_to_cpu(where[i].key), 1);/*释放块*/	return -EAGAIN;}/* * Allocation strategy is simple: if we have to allocate something, we will * have to go the whole way to leaf. So let's do it before attaching anything * to tree, set linkage between the newborn blocks, write them if sync is * required, recheck the path, free and repeat if check fails, otherwise * set the last missing link (that will protect us from any truncate-generated * removals - all blocks on the path are immune now) and possibly force the * write on the parent block. * That has a nice additional property: no special recovery from the failed * allocations is needed - we simply release blocks and do not touch anything * reachable from inode. *//*从逻辑块序号得到对应的物理块, *如果对应物理块被删除,则重新分配,并得到它间接块路径 */ /*这种转换关系是由ext2_inode结构中i_block[]数组描述的。  *i_block[]的前12项为直接块索引表,第13项为间接索引块指针,  *第14项为二重索引块指针,第15项为三重索引块指针。  *当文件长度不超过12个块时,可通过直接块索引表直接定位目标块,  *当文件长度超过12块并且剩余的部分不超过间接索引块索引数量时,  *就在间接索引块中定位目标块,依次类推  */static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create){	int err = -EIO;	int offsets[4];/*描述最多4级的目录项索引*/	Indirect chain[4];/*描述最多4级的索引目录项*/	Indirect *partial;	unsigned long goal;	int left;	/*将文件系统的逻辑块号iblock分解成对索引块的索引路径	 *即offset[0]->offset[1]->offset[2]->offset[3]	 *depth为1表示立即索引,2表示间接索引,	 *3表示二重索引,4表示三重索引	 *offsets[]为iblock在各级索引块上的索引号,depth最大为4,	 *则offsets[0]指向三重目录块,	 *offsets[1]为其索引,其值指向二重目录块,	 *offsets[2]为其索引,其值指向一重目录块,	 *offsets[3]为其索引,其值指向最终iblock所对应的目的块	 */	int depth = ext2_block_to_path(inode, iblock, offsets);/*以逻辑块号为索引查找物理块*/	if (depth == 0)		goto out;	lock_kernel();/*给内核上锁*/reread:	partial = ext2_get_branch(inode, depth, offsets, chain, &err);	/*沿着索引路径读取末一个索引块*/	/*加载iblock的各级目录块,	  *chain[]描述iblock在各级目录块上的索引项和索引值	  *chain[0]描述iblock在直接索引目录上的索引项和索引值	  *chain[1]描述iblock在间接目录块上的索引项和索引值,依次类推         */	/* Simplest case - block found, no allocation needed */       /*如果iblock对应的物理块存在,当发现block并读取数据正常时*/	if (!partial) {got_it:		bh_result->b_dev = inode->i_dev;		bh_result->b_blocknr = le32_to_cpu(chain[depth-1].key);		bh_result->b_state |= (1UL << BH_Mapped);		/* Clean up and exit */		partial = chain+depth-1; /* the whole chain *//* 使partial指向chain[]的未端*/		goto cleanup;	}	/* Next simple case - plain lookup or failed read of indirect block */       /*清除partial中多余的空间*/	if (!create || err == -EIO) {cleanup:		while (partial > chain) {			brelse(partial->bh);/*释放各级目录块*/			partial--;		}		unlock_kernel();/*给内核解锁*/out:		return err;	}	/*	 * Indirect block might be removed by truncate while we were	 * reading it. Handling of that case (forget what we've got and	 * reread) is taken out of the main path.	 */	 /*当正在读取间接块时,间接块可能被truncate命令删除掉,        *处理这种情况时必须重新得到间接块路径,        *通过重分配块等,然后再去重读取它        */	if (err == -EAGAIN)		goto changed;              /*如果iblock对应的物理块不存在,         *这时partial指向iblock对应的某一级目录项,该目录项的索引值为空	  *这时需要为这个空目录项分配一个块	  */	if (ext2_find_goal(inode, iblock, chain, partial, &goal) < 0)		goto changed;	/*寻找一个合适的分配点,	  *使新分配的块与inode所在的物理块区域尽可能接近	  */	left = (chain + depth) - partial;/*需要新建目录块的数目*/	err = ext2_alloc_branch(inode, left, goal,					offsets+(partial-chain), partial);/*分配并建立一个块链表*/	/*完成中断的索引路径*/	if (err)		goto cleanup;	if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0)/*接合块链表*/		goto changed;	bh_result->b_state |= (1UL << BH_New);	goto got_it;

⌨️ 快捷键说明

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