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

📄 alloc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* This will cause us to go off the end of our extent list. */	BUG_ON(next_free >= count);	num_bytes = sizeof(struct ocfs2_extent_rec) * next_free;	memmove(&el->l_recs[1], &el->l_recs[0], num_bytes);}static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el,			      struct ocfs2_extent_rec *insert_rec){	int i, insert_index, next_free, has_empty, num_bytes;	u32 insert_cpos = le32_to_cpu(insert_rec->e_cpos);	struct ocfs2_extent_rec *rec;	next_free = le16_to_cpu(el->l_next_free_rec);	has_empty = ocfs2_is_empty_extent(&el->l_recs[0]);	BUG_ON(!next_free);	/* The tree code before us didn't allow enough room in the leaf. */	if (el->l_next_free_rec == el->l_count && !has_empty)		BUG();	/*	 * The easiest way to approach this is to just remove the	 * empty extent and temporarily decrement next_free.	 */	if (has_empty) {		/*		 * If next_free was 1 (only an empty extent), this		 * loop won't execute, which is fine. We still want		 * the decrement above to happen.		 */		for(i = 0; i < (next_free - 1); i++)			el->l_recs[i] = el->l_recs[i+1];		next_free--;	}	/*	 * Figure out what the new record index should be.	 */	for(i = 0; i < next_free; i++) {		rec = &el->l_recs[i];		if (insert_cpos < le32_to_cpu(rec->e_cpos))			break;	}	insert_index = i;	mlog(0, "ins %u: index %d, has_empty %d, next_free %d, count %d\n",	     insert_cpos, insert_index, has_empty, next_free, le16_to_cpu(el->l_count));	BUG_ON(insert_index < 0);	BUG_ON(insert_index >= le16_to_cpu(el->l_count));	BUG_ON(insert_index > next_free);	/*	 * No need to memmove if we're just adding to the tail.	 */	if (insert_index != next_free) {		BUG_ON(next_free >= le16_to_cpu(el->l_count));		num_bytes = next_free - insert_index;		num_bytes *= sizeof(struct ocfs2_extent_rec);		memmove(&el->l_recs[insert_index + 1],			&el->l_recs[insert_index],			num_bytes);	}	/*	 * Either we had an empty extent, and need to re-increment or	 * there was no empty extent on a non full rightmost leaf node,	 * in which case we still need to increment.	 */	next_free++;	el->l_next_free_rec = cpu_to_le16(next_free);	/*	 * Make sure none of the math above just messed up our tree.	 */	BUG_ON(le16_to_cpu(el->l_next_free_rec) > le16_to_cpu(el->l_count));	el->l_recs[insert_index] = *insert_rec;}static void ocfs2_remove_empty_extent(struct ocfs2_extent_list *el){	int size, num_recs = le16_to_cpu(el->l_next_free_rec);	BUG_ON(num_recs == 0);	if (ocfs2_is_empty_extent(&el->l_recs[0])) {		num_recs--;		size = num_recs * sizeof(struct ocfs2_extent_rec);		memmove(&el->l_recs[0], &el->l_recs[1], size);		memset(&el->l_recs[num_recs], 0,		       sizeof(struct ocfs2_extent_rec));		el->l_next_free_rec = cpu_to_le16(num_recs);	}}/* * Create an empty extent record . * * l_next_free_rec may be updated. * * If an empty extent already exists do nothing. */static void ocfs2_create_empty_extent(struct ocfs2_extent_list *el){	int next_free = le16_to_cpu(el->l_next_free_rec);	BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);	if (next_free == 0)		goto set_and_inc;	if (ocfs2_is_empty_extent(&el->l_recs[0]))		return;	mlog_bug_on_msg(el->l_count == el->l_next_free_rec,			"Asked to create an empty extent in a full list:\n"			"count = %u, tree depth = %u",			le16_to_cpu(el->l_count),			le16_to_cpu(el->l_tree_depth));	ocfs2_shift_records_right(el);set_and_inc:	le16_add_cpu(&el->l_next_free_rec, 1);	memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));}/* * For a rotation which involves two leaf nodes, the "root node" is * the lowest level tree node which contains a path to both leafs. This * resulting set of information can be used to form a complete "subtree" * * This function is passed two full paths from the dinode down to a * pair of adjacent leaves. It's task is to figure out which path * index contains the subtree root - this can be the root index itself * in a worst-case rotation. * * The array index of the subtree root is passed back. */static int ocfs2_find_subtree_root(struct inode *inode,				   struct ocfs2_path *left,				   struct ocfs2_path *right){	int i = 0;	/*	 * Check that the caller passed in two paths from the same tree.	 */	BUG_ON(path_root_bh(left) != path_root_bh(right));	do {		i++;		/*		 * The caller didn't pass two adjacent paths.		 */		mlog_bug_on_msg(i > left->p_tree_depth,				"Inode %lu, left depth %u, right depth %u\n"				"left leaf blk %llu, right leaf blk %llu\n",				inode->i_ino, left->p_tree_depth,				right->p_tree_depth,				(unsigned long long)path_leaf_bh(left)->b_blocknr,				(unsigned long long)path_leaf_bh(right)->b_blocknr);	} while (left->p_node[i].bh->b_blocknr ==		 right->p_node[i].bh->b_blocknr);	return i - 1;}typedef void (path_insert_t)(void *, struct buffer_head *);/* * Traverse a btree path in search of cpos, starting at root_el. * * This code can be called with a cpos larger than the tree, in which * case it will return the rightmost path. */static int __ocfs2_find_path(struct inode *inode,			     struct ocfs2_extent_list *root_el, u32 cpos,			     path_insert_t *func, void *data){	int i, ret = 0;	u32 range;	u64 blkno;	struct buffer_head *bh = NULL;	struct ocfs2_extent_block *eb;	struct ocfs2_extent_list *el;	struct ocfs2_extent_rec *rec;	struct ocfs2_inode_info *oi = OCFS2_I(inode);	el = root_el;	while (el->l_tree_depth) {		if (le16_to_cpu(el->l_next_free_rec) == 0) {			ocfs2_error(inode->i_sb,				    "Inode %llu has empty extent list at "				    "depth %u\n",				    (unsigned long long)oi->ip_blkno,				    le16_to_cpu(el->l_tree_depth));			ret = -EROFS;			goto out;		}		for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {			rec = &el->l_recs[i];			/*			 * In the case that cpos is off the allocation			 * tree, this should just wind up returning the			 * rightmost record.			 */			range = le32_to_cpu(rec->e_cpos) +				ocfs2_rec_clusters(el, rec);			if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range)			    break;		}		blkno = le64_to_cpu(el->l_recs[i].e_blkno);		if (blkno == 0) {			ocfs2_error(inode->i_sb,				    "Inode %llu has bad blkno in extent list "				    "at depth %u (index %d)\n",				    (unsigned long long)oi->ip_blkno,				    le16_to_cpu(el->l_tree_depth), i);			ret = -EROFS;			goto out;		}		brelse(bh);		bh = NULL;		ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), blkno,				       &bh, OCFS2_BH_CACHED, inode);		if (ret) {			mlog_errno(ret);			goto out;		}		eb = (struct ocfs2_extent_block *) bh->b_data;		el = &eb->h_list;		if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {			OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);			ret = -EIO;			goto out;		}		if (le16_to_cpu(el->l_next_free_rec) >		    le16_to_cpu(el->l_count)) {			ocfs2_error(inode->i_sb,				    "Inode %llu has bad count in extent list "				    "at block %llu (next free=%u, count=%u)\n",				    (unsigned long long)oi->ip_blkno,				    (unsigned long long)bh->b_blocknr,				    le16_to_cpu(el->l_next_free_rec),				    le16_to_cpu(el->l_count));			ret = -EROFS;			goto out;		}		if (func)			func(data, bh);	}out:	/*	 * Catch any trailing bh that the loop didn't handle.	 */	brelse(bh);	return ret;}/* * Given an initialized path (that is, it has a valid root extent * list), this function will traverse the btree in search of the path * which would contain cpos. * * The path traveled is recorded in the path structure. * * Note that this will not do any comparisons on leaf node extent * records, so it will work fine in the case that we just added a tree * branch. */struct find_path_data {	int index;	struct ocfs2_path *path;};static void find_path_ins(void *data, struct buffer_head *bh){	struct find_path_data *fp = data;	get_bh(bh);	ocfs2_path_insert_eb(fp->path, fp->index, bh);	fp->index++;}static int ocfs2_find_path(struct inode *inode, struct ocfs2_path *path,			   u32 cpos){	struct find_path_data data;	data.index = 1;	data.path = path;	return __ocfs2_find_path(inode, path_root_el(path), cpos,				 find_path_ins, &data);}static void find_leaf_ins(void *data, struct buffer_head *bh){	struct ocfs2_extent_block *eb =(struct ocfs2_extent_block *)bh->b_data;	struct ocfs2_extent_list *el = &eb->h_list;	struct buffer_head **ret = data;	/* We want to retain only the leaf block. */	if (le16_to_cpu(el->l_tree_depth) == 0) {		get_bh(bh);		*ret = bh;	}}/* * Find the leaf block in the tree which would contain cpos. No * checking of the actual leaf is done. * * Some paths want to call this instead of allocating a path structure * and calling ocfs2_find_path(). * * This function doesn't handle non btree extent lists. */int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,		    u32 cpos, struct buffer_head **leaf_bh){	int ret;	struct buffer_head *bh = NULL;	ret = __ocfs2_find_path(inode, root_el, cpos, find_leaf_ins, &bh);	if (ret) {		mlog_errno(ret);		goto out;	}	*leaf_bh = bh;out:	return ret;}/* * Adjust the adjacent records (left_rec, right_rec) involved in a rotation. * * Basically, we've moved stuff around at the bottom of the tree and * we need to fix up the extent records above the changes to reflect * the new changes. * * left_rec: the record on the left. * left_child_el: is the child list pointed to by left_rec * right_rec: the record to the right of left_rec * right_child_el: is the child list pointed to by right_rec * * By definition, this only works on interior nodes. */static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,				  struct ocfs2_extent_list *left_child_el,				  struct ocfs2_extent_rec *right_rec,				  struct ocfs2_extent_list *right_child_el){	u32 left_clusters, right_end;	/*	 * Interior nodes never have holes. Their cpos is the cpos of	 * the leftmost record in their child list. Their cluster	 * count covers the full theoretical range of their child list	 * - the range between their cpos and the cpos of the record	 * immediately to their right.	 */	left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);	if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) {		BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);		left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);	}	left_clusters -= le32_to_cpu(left_rec->e_cpos);	left_rec->e_int_clusters = cpu_to_le32(left_clusters);	/*	 * Calculate the rightmost cluster count boundary before	 * moving cpos - we will need to adjust clusters after	 * updating e_cpos to keep the same highest cluster count.	 */	right_end = le32_to_cpu(right_rec->e_cpos);	right_end += le32_to_cpu(right_rec->e_int_clusters);	right_rec->e_cpos = left_rec->e_cpos;	le32_add_cpu(&right_rec->e_cpos, left_clusters);	right_end -= le32_to_cpu(right_rec->e_cpos);	right_rec->e_int_clusters = cpu_to_le32(right_end);}/* * Adjust the adjacent root node records involved in a * rotation. left_el_blkno is passed in as a key so that we can easily * find it's index in the root list. */static void ocfs2_adjust_root_records(struct ocfs2_extent_list *root_el,				      struct ocfs2_extent_list *left_el,				      struct ocfs2_extent_list *right_el,				      u64 left_el_blkno){	int i;	BUG_ON(le16_to_cpu(root_el->l_tree_depth) <=	       le16_to_cpu(left_el->l_tree_depth));	for(i = 0; i < le16_to_cpu(root_el->l_next_free_rec) - 1; i++) {		if (le64_to_cpu(root_el->l_recs[i].e_blkno) == left_el_blkno)			break;	}	/*	 * The path walking code should have never returned a root and	 * two paths which are not adjacent.	 */	BUG_ON(i >= (le16_to_cpu(root_el->l_next_free_rec) - 1));	ocfs2_adjust_adjacent_records(&root_el->l_recs[i], left_el,				      &root_el->l_recs[i + 1], right_el);}/* * We've changed a leaf block (in right_path) and need to reflect that * change back up the subtree. * * This happens in multiple places: *   - When we've moved an extent record from the left path leaf to the right *     path leaf to make room for an empty extent in the left path leaf. *   - When our insert into the right path leaf is at the leftmost edge *     and requires an update of the path immediately to it's left. This *     can occur at the end of some types of rotation and appending inserts. */static void ocfs2_complete_edge_insert(struct inode *inode, handle_t *handle,				       struct ocfs2_path *left_path,				       struct ocfs2_path *right_path,				       int subtree_index){	int ret, i, idx;	struct ocfs2_extent_list *el, *left_el, *right_el;	struct ocfs2_extent_rec *left_rec, *right_rec;	struct buffer_head *root_bh = left_path->p_node[subtree_index].bh;	/*	 * Update the counts and position values within all the	 * interior nodes to reflect the leaf rotation we just did.	 *	 * The root node is handled below the loop.	 *	 * We begin the loop with right_el and left_el pointing to the	 * leaf lists and work our way up.	 *	 * NOTE: within this loop, left_el and right_el always refer	 * to the *child* lists.	 */	left_el = path_leaf_el(left_path);	right_el = path_leaf_el(right_path);	for(i = left_path->p_tree_depth - 1; i > subtree_index; i--) {		mlog(0, "Adjust records at index %u\n", i);		/*		 * One nice property of knowing that all of these		 * nodes are below the root is that we only deal with		 * the leftmost right node record and the rightmost		 * left node record.		 */		el = left_path->p_node[i].el;		idx = le16_to_cpu(left_el->l_next_free_rec) - 1;		left_rec = &el->l_recs[idx];		el = right_path->p_node[i].el;		right_rec = &el->l_recs[0];		ocfs2_adjust_adjacent_records(left_rec, left_el, right_rec,					      right_el);		ret = ocfs2_journal_dirty(handle, left_path->p_node[i].bh);		if (ret)			mlog_errno(ret);		ret = ocfs2_journal_dirty(handle, right_path->p_node[i].bh);		if (ret)			mlog_errno(ret);		/*		 * Setup our list pointers now so that the current		 * parents become children in the next iteration.		 */		left_el = left_path->p_node[i].el;		right_el = right_path->p_node[i].el;	}	/*	 * At the root node, adjust the two adjacent records which	 * begin our path to the leaves.

⌨️ 快捷键说明

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