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

📄 alloc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		ret = ocfs2_cache_extent_block_free(dealloc, eb);		if (ret)			mlog_errno(ret);		ocfs2_remove_from_cache(inode, bh);	}}static void ocfs2_unlink_subtree(struct inode *inode, handle_t *handle,				 struct ocfs2_path *left_path,				 struct ocfs2_path *right_path,				 int subtree_index,				 struct ocfs2_cached_dealloc_ctxt *dealloc){	int i;	struct buffer_head *root_bh = left_path->p_node[subtree_index].bh;	struct ocfs2_extent_list *root_el = left_path->p_node[subtree_index].el;	struct ocfs2_extent_list *el;	struct ocfs2_extent_block *eb;	el = path_leaf_el(left_path);	eb = (struct ocfs2_extent_block *)right_path->p_node[subtree_index + 1].bh->b_data;	for(i = 1; i < le16_to_cpu(root_el->l_next_free_rec); i++)		if (root_el->l_recs[i].e_blkno == eb->h_blkno)			break;	BUG_ON(i >= le16_to_cpu(root_el->l_next_free_rec));	memset(&root_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));	le16_add_cpu(&root_el->l_next_free_rec, -1);	eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;	eb->h_next_leaf_blk = 0;	ocfs2_journal_dirty(handle, root_bh);	ocfs2_journal_dirty(handle, path_leaf_bh(left_path));	ocfs2_unlink_path(inode, handle, dealloc, right_path,			  subtree_index + 1);}static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,				     struct ocfs2_path *left_path,				     struct ocfs2_path *right_path,				     int subtree_index,				     struct ocfs2_cached_dealloc_ctxt *dealloc,				     int *deleted){	int ret, i, del_right_subtree = 0, right_has_empty = 0;	struct buffer_head *root_bh, *di_bh = path_root_bh(right_path);	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;	struct ocfs2_extent_list *right_leaf_el, *left_leaf_el;	struct ocfs2_extent_block *eb;	*deleted = 0;	right_leaf_el = path_leaf_el(right_path);	left_leaf_el = path_leaf_el(left_path);	root_bh = left_path->p_node[subtree_index].bh;	BUG_ON(root_bh != right_path->p_node[subtree_index].bh);	if (!ocfs2_is_empty_extent(&left_leaf_el->l_recs[0]))		return 0;	eb = (struct ocfs2_extent_block *)path_leaf_bh(right_path)->b_data;	if (ocfs2_is_empty_extent(&right_leaf_el->l_recs[0])) {		/*		 * It's legal for us to proceed if the right leaf is		 * the rightmost one and it has an empty extent. There		 * are two cases to handle - whether the leaf will be		 * empty after removal or not. If the leaf isn't empty		 * then just remove the empty extent up front. The		 * next block will handle empty leaves by flagging		 * them for unlink.		 *		 * Non rightmost leaves will throw -EAGAIN and the		 * caller can manually move the subtree and retry.		 */		if (eb->h_next_leaf_blk != 0ULL)			return -EAGAIN;		if (le16_to_cpu(right_leaf_el->l_next_free_rec) > 1) {			ret = ocfs2_journal_access(handle, inode,						   path_leaf_bh(right_path),						   OCFS2_JOURNAL_ACCESS_WRITE);			if (ret) {				mlog_errno(ret);				goto out;			}			ocfs2_remove_empty_extent(right_leaf_el);		} else			right_has_empty = 1;	}	if (eb->h_next_leaf_blk == 0ULL &&	    le16_to_cpu(right_leaf_el->l_next_free_rec) == 1) {		/*		 * We have to update i_last_eb_blk during the meta		 * data delete.		 */		ret = ocfs2_journal_access(handle, inode, di_bh,					   OCFS2_JOURNAL_ACCESS_WRITE);		if (ret) {			mlog_errno(ret);			goto out;		}		del_right_subtree = 1;	}	/*	 * Getting here with an empty extent in the right path implies	 * that it's the rightmost path and will be deleted.	 */	BUG_ON(right_has_empty && !del_right_subtree);	ret = ocfs2_journal_access(handle, inode, root_bh,				   OCFS2_JOURNAL_ACCESS_WRITE);	if (ret) {		mlog_errno(ret);		goto out;	}	for(i = subtree_index + 1; i < path_num_items(right_path); i++) {		ret = ocfs2_journal_access(handle, inode,					   right_path->p_node[i].bh,					   OCFS2_JOURNAL_ACCESS_WRITE);		if (ret) {			mlog_errno(ret);			goto out;		}		ret = ocfs2_journal_access(handle, inode,					   left_path->p_node[i].bh,					   OCFS2_JOURNAL_ACCESS_WRITE);		if (ret) {			mlog_errno(ret);			goto out;		}	}	if (!right_has_empty) {		/*		 * Only do this if we're moving a real		 * record. Otherwise, the action is delayed until		 * after removal of the right path in which case we		 * can do a simple shift to remove the empty extent.		 */		ocfs2_rotate_leaf(left_leaf_el, &right_leaf_el->l_recs[0]);		memset(&right_leaf_el->l_recs[0], 0,		       sizeof(struct ocfs2_extent_rec));	}	if (eb->h_next_leaf_blk == 0ULL) {		/*		 * Move recs over to get rid of empty extent, decrease		 * next_free. This is allowed to remove the last		 * extent in our leaf (setting l_next_free_rec to		 * zero) - the delete code below won't care.		 */		ocfs2_remove_empty_extent(right_leaf_el);	}	ret = ocfs2_journal_dirty(handle, path_leaf_bh(left_path));	if (ret)		mlog_errno(ret);	ret = ocfs2_journal_dirty(handle, path_leaf_bh(right_path));	if (ret)		mlog_errno(ret);	if (del_right_subtree) {		ocfs2_unlink_subtree(inode, handle, left_path, right_path,				     subtree_index, dealloc);		ocfs2_update_edge_lengths(inode, handle, left_path);		eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;		di->i_last_eb_blk = eb->h_blkno;		/*		 * Removal of the extent in the left leaf was skipped		 * above so we could delete the right path		 * 1st.		 */		if (right_has_empty)			ocfs2_remove_empty_extent(left_leaf_el);		ret = ocfs2_journal_dirty(handle, di_bh);		if (ret)			mlog_errno(ret);		*deleted = 1;	} else		ocfs2_complete_edge_insert(inode, handle, left_path, right_path,					   subtree_index);out:	return ret;}/* * Given a full path, determine what cpos value would return us a path * containing the leaf immediately to the right of the current one. * * Will return zero if the path passed in is already the rightmost path. * * This looks similar, but is subtly different to * ocfs2_find_cpos_for_left_leaf(). */static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,					  struct ocfs2_path *path, u32 *cpos){	int i, j, ret = 0;	u64 blkno;	struct ocfs2_extent_list *el;	*cpos = 0;	if (path->p_tree_depth == 0)		return 0;	blkno = path_leaf_bh(path)->b_blocknr;	/* Start at the tree node just above the leaf and work our way up. */	i = path->p_tree_depth - 1;	while (i >= 0) {		int next_free;		el = path->p_node[i].el;		/*		 * Find the extent record just after the one in our		 * path.		 */		next_free = le16_to_cpu(el->l_next_free_rec);		for(j = 0; j < le16_to_cpu(el->l_next_free_rec); j++) {			if (le64_to_cpu(el->l_recs[j].e_blkno) == blkno) {				if (j == (next_free - 1)) {					if (i == 0) {						/*						 * We've determined that the						 * path specified is already						 * the rightmost one - return a						 * cpos of zero.						 */						goto out;					}					/*					 * The rightmost record points to our					 * leaf - we need to travel up the					 * tree one level.					 */					goto next_node;				}				*cpos = le32_to_cpu(el->l_recs[j + 1].e_cpos);				goto out;			}		}		/*		 * If we got here, we never found a valid node where		 * the tree indicated one should be.		 */		ocfs2_error(sb,			    "Invalid extent tree at extent block %llu\n",			    (unsigned long long)blkno);		ret = -EROFS;		goto out;next_node:		blkno = path->p_node[i].bh->b_blocknr;		i--;	}out:	return ret;}static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,					    handle_t *handle,					    struct buffer_head *bh,					    struct ocfs2_extent_list *el){	int ret;	if (!ocfs2_is_empty_extent(&el->l_recs[0]))		return 0;	ret = ocfs2_journal_access(handle, inode, bh,				   OCFS2_JOURNAL_ACCESS_WRITE);	if (ret) {		mlog_errno(ret);		goto out;	}	ocfs2_remove_empty_extent(el);	ret = ocfs2_journal_dirty(handle, bh);	if (ret)		mlog_errno(ret);out:	return ret;}static int __ocfs2_rotate_tree_left(struct inode *inode,				    handle_t *handle, int orig_credits,				    struct ocfs2_path *path,				    struct ocfs2_cached_dealloc_ctxt *dealloc,				    struct ocfs2_path **empty_extent_path){	int ret, subtree_root, deleted;	u32 right_cpos;	struct ocfs2_path *left_path = NULL;	struct ocfs2_path *right_path = NULL;	BUG_ON(!ocfs2_is_empty_extent(&(path_leaf_el(path)->l_recs[0])));	*empty_extent_path = NULL;	ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, path,					     &right_cpos);	if (ret) {		mlog_errno(ret);		goto out;	}	left_path = ocfs2_new_path(path_root_bh(path),				   path_root_el(path));	if (!left_path) {		ret = -ENOMEM;		mlog_errno(ret);		goto out;	}	ocfs2_cp_path(left_path, path);	right_path = ocfs2_new_path(path_root_bh(path),				    path_root_el(path));	if (!right_path) {		ret = -ENOMEM;		mlog_errno(ret);		goto out;	}	while (right_cpos) {		ret = ocfs2_find_path(inode, right_path, right_cpos);		if (ret) {			mlog_errno(ret);			goto out;		}		subtree_root = ocfs2_find_subtree_root(inode, left_path,						       right_path);		mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",		     subtree_root,		     (unsigned long long)		     right_path->p_node[subtree_root].bh->b_blocknr,		     right_path->p_tree_depth);		ret = ocfs2_extend_rotate_transaction(handle, subtree_root,						      orig_credits, left_path);		if (ret) {			mlog_errno(ret);			goto out;		}		/*		 * Caller might still want to make changes to the		 * tree root, so re-add it to the journal here.		 */		ret = ocfs2_journal_access(handle, inode,					   path_root_bh(left_path),					   OCFS2_JOURNAL_ACCESS_WRITE);		if (ret) {			mlog_errno(ret);			goto out;		}		ret = ocfs2_rotate_subtree_left(inode, handle, left_path,						right_path, subtree_root,						dealloc, &deleted);		if (ret == -EAGAIN) {			/*			 * The rotation has to temporarily stop due to			 * the right subtree having an empty			 * extent. Pass it back to the caller for a			 * fixup.			 */			*empty_extent_path = right_path;			right_path = NULL;			goto out;		}		if (ret) {			mlog_errno(ret);			goto out;		}		/*		 * The subtree rotate might have removed records on		 * the rightmost edge. If so, then rotation is		 * complete.		 */		if (deleted)			break;		ocfs2_mv_path(left_path, right_path);		ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,						     &right_cpos);		if (ret) {			mlog_errno(ret);			goto out;		}	}out:	ocfs2_free_path(right_path);	ocfs2_free_path(left_path);	return ret;}static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,				       struct ocfs2_path *path,				       struct ocfs2_cached_dealloc_ctxt *dealloc){	int ret, subtree_index;	u32 cpos;	struct ocfs2_path *left_path = NULL;	struct ocfs2_dinode *di;	struct ocfs2_extent_block *eb;	struct ocfs2_extent_list *el;	/*	 * XXX: This code assumes that the root is an inode, which is	 * true for now but may change as tree code gets generic.	 */	di = (struct ocfs2_dinode *)path_root_bh(path)->b_data;	if (!OCFS2_IS_VALID_DINODE(di)) {		ret = -EIO;		ocfs2_error(inode->i_sb,			    "Inode %llu has invalid path root",			    (unsigned long long)OCFS2_I(inode)->ip_blkno);		goto out;	}	/*	 * There's two ways we handle this depending on	 * whether path is the only existing one.	 */	ret = ocfs2_extend_rotate_transaction(handle, 0,					      handle->h_buffer_credits,					      path);	if (ret) {		mlog_errno(ret);		goto out;	}	ret = ocfs2_journal_access_path(inode, handle, path);	if (ret) {		mlog_errno(ret);		goto out;	}	ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path, &cpos);	if (ret) {		mlog_errno(ret);		goto out;	}	if (cpos) {		/*		 * We have a path to the left of this one - it needs		 * an update too.		 */		left_path = ocfs2_new_path(path_root_bh(path),					   path_root_el(path));		if (!left_path) {			ret = -ENOMEM;			mlog_errno(ret);			goto out;		}		ret = ocfs2_find_path(inode, left_path, cpos);		if (ret) {			mlog_errno(ret);			goto out;		}		ret = ocfs2_journal_access_path(inode, handle, left_path);		if (ret) {			mlog_errno(ret);			goto out;		}		subtree_index = ocfs2_find_subtree_root(inode, left_path, path);		ocfs2_unlink_subtree(inode, handle, left_path, path,				     subtree_index, dealloc);		ocfs2_update_edge_lengths(inode,

⌨️ 快捷键说明

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