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

📄 xfs_attr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	} else if (args->rmtblkno > 0) {		/*		 * Added a "remote" value, just clear the incomplete flag.		 */		error = xfs_attr_leaf_clearflag(args);		if (error)			goto out;	}	retval = error = 0;out:	if (state)		xfs_da_state_free(state);	if (error)		return(error);	return(retval);}/* * Remove a name from a B-tree attribute list. * * This will involve walking down the Btree, and may involve joining * leaf nodes and even joining intermediate nodes up to and including * the root node (a special case of an intermediate node). */STATIC intxfs_attr_node_removename(xfs_da_args_t *args){	xfs_da_state_t *state;	xfs_da_state_blk_t *blk;	xfs_inode_t *dp;	xfs_dabuf_t *bp;	int retval, error, committed, forkoff;	/*	 * Tie a string around our finger to remind us where we are.	 */	dp = args->dp;	state = xfs_da_state_alloc();	state->args = args;	state->mp = dp->i_mount;	state->blocksize = state->mp->m_sb.sb_blocksize;	state->node_ents = state->mp->m_attr_node_ents;	/*	 * Search to see if name exists, and get back a pointer to it.	 */	error = xfs_da_node_lookup_int(state, &retval);	if (error || (retval != EEXIST)) {		if (error == 0)			error = retval;		goto out;	}	/*	 * If there is an out-of-line value, de-allocate the blocks.	 * This is done before we remove the attribute so that we don't	 * overflow the maximum size of a transaction and/or hit a deadlock.	 */	blk = &state->path.blk[ state->path.active-1 ];	ASSERT(blk->bp != NULL);	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);	if (args->rmtblkno > 0) {		/*		 * Fill in disk block numbers in the state structure		 * so that we can get the buffers back after we commit		 * several transactions in the following calls.		 */		error = xfs_attr_fillstate(state);		if (error)			goto out;		/*		 * Mark the attribute as INCOMPLETE, then bunmapi() the		 * remote value.		 */		error = xfs_attr_leaf_setflag(args);		if (error)			goto out;		error = xfs_attr_rmtval_remove(args);		if (error)			goto out;		/*		 * Refill the state structure with buffers, the prior calls		 * released our buffers.		 */		error = xfs_attr_refillstate(state);		if (error)			goto out;	}	/*	 * Remove the name and update the hashvals in the tree.	 */	blk = &state->path.blk[ state->path.active-1 ];	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);	retval = xfs_attr_leaf_remove(blk->bp, args);	xfs_da_fixhashpath(state, &state->path);	/*	 * Check to see if the tree needs to be collapsed.	 */	if (retval && (state->path.active > 1)) {		XFS_BMAP_INIT(args->flist, args->firstblock);		error = xfs_da_join(state);		if (!error) {			error = xfs_bmap_finish(&args->trans, args->flist,						&committed);		}		if (error) {			ASSERT(committed);			args->trans = NULL;			xfs_bmap_cancel(args->flist);			goto out;		}		/*		 * bmap_finish() may have committed the last trans and started		 * a new one.  We need the inode to be in all transactions.		 */		if (committed) {			xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);			xfs_trans_ihold(args->trans, dp);		}		/*		 * Commit the Btree join operation and start a new trans.		 */		if ((error = xfs_attr_rolltrans(&args->trans, dp)))			goto out;	}	/*	 * If the result is small enough, push it all into the inode.	 */	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {		/*		 * Have to get rid of the copy of this dabuf in the state.		 */		ASSERT(state->path.active == 1);		ASSERT(state->path.blk[0].bp);		xfs_da_buf_done(state->path.blk[0].bp);		state->path.blk[0].bp = NULL;		error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,						     XFS_ATTR_FORK);		if (error)			goto out;		ASSERT(be16_to_cpu(((xfs_attr_leafblock_t *)				      bp->data)->hdr.info.magic)						       == XFS_ATTR_LEAF_MAGIC);		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {			XFS_BMAP_INIT(args->flist, args->firstblock);			error = xfs_attr_leaf_to_shortform(bp, args, forkoff);			/* bp is gone due to xfs_da_shrink_inode */			if (!error) {				error = xfs_bmap_finish(&args->trans,							args->flist,							&committed);			}			if (error) {				ASSERT(committed);				args->trans = NULL;				xfs_bmap_cancel(args->flist);				goto out;			}			/*			 * bmap_finish() may have committed the last trans			 * and started a new one.  We need the inode to be			 * in all transactions.			 */			if (committed) {				xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);				xfs_trans_ihold(args->trans, dp);			}		} else			xfs_da_brelse(args->trans, bp);	}	error = 0;out:	xfs_da_state_free(state);	return(error);}/* * Fill in the disk block numbers in the state structure for the buffers * that are attached to the state structure. * This is done so that we can quickly reattach ourselves to those buffers * after some set of transaction commits have released these buffers. */STATIC intxfs_attr_fillstate(xfs_da_state_t *state){	xfs_da_state_path_t *path;	xfs_da_state_blk_t *blk;	int level;	/*	 * Roll down the "path" in the state structure, storing the on-disk	 * block number for those buffers in the "path".	 */	path = &state->path;	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {		if (blk->bp) {			blk->disk_blkno = xfs_da_blkno(blk->bp);			xfs_da_buf_done(blk->bp);			blk->bp = NULL;		} else {			blk->disk_blkno = 0;		}	}	/*	 * Roll down the "altpath" in the state structure, storing the on-disk	 * block number for those buffers in the "altpath".	 */	path = &state->altpath;	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {		if (blk->bp) {			blk->disk_blkno = xfs_da_blkno(blk->bp);			xfs_da_buf_done(blk->bp);			blk->bp = NULL;		} else {			blk->disk_blkno = 0;		}	}	return(0);}/* * Reattach the buffers to the state structure based on the disk block * numbers stored in the state structure. * This is done after some set of transaction commits have released those * buffers from our grip. */STATIC intxfs_attr_refillstate(xfs_da_state_t *state){	xfs_da_state_path_t *path;	xfs_da_state_blk_t *blk;	int level, error;	/*	 * Roll down the "path" in the state structure, storing the on-disk	 * block number for those buffers in the "path".	 */	path = &state->path;	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {		if (blk->disk_blkno) {			error = xfs_da_read_buf(state->args->trans,						state->args->dp,						blk->blkno, blk->disk_blkno,						&blk->bp, XFS_ATTR_FORK);			if (error)				return(error);		} else {			blk->bp = NULL;		}	}	/*	 * Roll down the "altpath" in the state structure, storing the on-disk	 * block number for those buffers in the "altpath".	 */	path = &state->altpath;	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {		if (blk->disk_blkno) {			error = xfs_da_read_buf(state->args->trans,						state->args->dp,						blk->blkno, blk->disk_blkno,						&blk->bp, XFS_ATTR_FORK);			if (error)				return(error);		} else {			blk->bp = NULL;		}	}	return(0);}/* * Look up a filename in a node attribute list. * * This routine gets called for any attribute fork that has more than one * block, ie: both true Btree attr lists and for single-leaf-blocks with * "remote" values taking up more blocks. */STATIC intxfs_attr_node_get(xfs_da_args_t *args){	xfs_da_state_t *state;	xfs_da_state_blk_t *blk;	int error, retval;	int i;	state = xfs_da_state_alloc();	state->args = args;	state->mp = args->dp->i_mount;	state->blocksize = state->mp->m_sb.sb_blocksize;	state->node_ents = state->mp->m_attr_node_ents;	/*	 * Search to see if name exists, and get back a pointer to it.	 */	error = xfs_da_node_lookup_int(state, &retval);	if (error) {		retval = error;	} else if (retval == EEXIST) {		blk = &state->path.blk[ state->path.active-1 ];		ASSERT(blk->bp != NULL);		ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);		/*		 * Get the value, local or "remote"		 */		retval = xfs_attr_leaf_getvalue(blk->bp, args);		if (!retval && (args->rmtblkno > 0)		    && !(args->flags & ATTR_KERNOVAL)) {			retval = xfs_attr_rmtval_get(args);		}	}	/*	 * If not in a transaction, we have to release all the buffers.	 */	for (i = 0; i < state->path.active; i++) {		xfs_da_brelse(args->trans, state->path.blk[i].bp);		state->path.blk[i].bp = NULL;	}	xfs_da_state_free(state);	return(retval);}STATIC int							/* error */xfs_attr_node_list(xfs_attr_list_context_t *context){	attrlist_cursor_kern_t *cursor;	xfs_attr_leafblock_t *leaf;	xfs_da_intnode_t *node;	xfs_da_node_entry_t *btree;	int error, i;	xfs_dabuf_t *bp;	cursor = context->cursor;	cursor->initted = 1;	/*	 * Do all sorts of validation on the passed-in cursor structure.	 * If anything is amiss, ignore the cursor and look up the hashval	 * starting from the btree root.	 */	bp = NULL;	if (cursor->blkno > 0) {		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,					      &bp, XFS_ATTR_FORK);		if ((error != 0) && (error != EFSCORRUPTED))			return(error);		if (bp) {			node = bp->data;			switch (be16_to_cpu(node->hdr.info.magic)) {			case XFS_DA_NODE_MAGIC:				xfs_attr_trace_l_cn("wrong blk", context, node);				xfs_da_brelse(NULL, bp);				bp = NULL;				break;			case XFS_ATTR_LEAF_MAGIC:				leaf = bp->data;				if (cursor->hashval > be32_to_cpu(leaf->entries[				    be16_to_cpu(leaf->hdr.count)-1].hashval)) {					xfs_attr_trace_l_cl("wrong blk",							   context, leaf);					xfs_da_brelse(NULL, bp);					bp = NULL;				} else if (cursor->hashval <=					     be32_to_cpu(leaf->entries[0].hashval)) {					xfs_attr_trace_l_cl("maybe wrong blk",							   context, leaf);					xfs_da_brelse(NULL, bp);					bp = NULL;				}				break;			default:				xfs_attr_trace_l_c("wrong blk - ??", context);				xfs_da_brelse(NULL, bp);				bp = NULL;			}		}	}	/*	 * We did not find what we expected given the cursor's contents,	 * so we start from the top and work down based on the hash value.	 * Note that start of node block is same as start of leaf block.	 */	if (bp == NULL) {		cursor->blkno = 0;		for (;;) {			error = xfs_da_read_buf(NULL, context->dp,						      cursor->blkno, -1, &bp,						      XFS_ATTR_FORK);			if (error)				return(error);			if (unlikely(bp == NULL)) {				XFS_ERROR_REPORT("xfs_attr_node_list(2)",						 XFS_ERRLEVEL_LOW,						 context->dp->i_mount);				return(XFS_ERROR(EFSCORRUPTED));			}			node = bp->data;			if (be16_to_cpu(node->hdr.info.magic)							== XFS_ATTR_LEAF_MAGIC)				break;			if (unlikely(be16_to_cpu(node->hdr.info.magic)							!= XFS_DA_NODE_MAGIC)) {				XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",						     XFS_ERRLEVEL_LOW,						     context->dp->i_mount,						     node);				xfs_da_brelse(NULL, bp);				return(XFS_ERROR(EFSCORRUPTED));			}			btree = node->btree;			for (i = 0; i < be16_to_cpu(node->hdr.count);								btree++, i++) {				if (cursor->hashval						<= be32_to_cpu(btree->hashval)) {					cursor->blkno = be32_to_cpu(btree->before);					xfs_attr_trace_l_cb("descending",							    context, btree);					break;				}			}			if (i == be16_to_cpu(node->hdr.count)) {				xfs_da_brelse(NULL, bp);				return(0);			}			xfs_da_brelse(NULL, bp);		}	}	ASSERT(bp != NULL);	/*	 * Roll upward through the blocks, processing each leaf block in	 * order.  As long as there is space in the result buffer, keep	 * adding the information.	 */	for (;;) {		leaf = bp->data;		if (unlikely(be16_to_cpu(leaf->hdr.info.magic)						!= XFS_ATTR_LEAF_MAGIC)) {			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",					     XFS_ERRLEVEL_LOW,					     context->dp->i_mount, leaf);			xfs_da_brelse(NULL, bp);			return(XFS_ERROR(EFSCORRUPTED));		}		error = xfs_attr_leaf_list_int(bp, context);		if (error) {			xfs_da_brelse(NULL, bp);			return error;		}		if (context->seen_enough || leaf->hdr.info.forw == 0)			break;		cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);		xfs_da_brelse(NULL, bp);		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,					      &bp, XFS_ATTR_FORK);		if (error)			return(error);		if (unlikely((bp == NULL))) {			XFS_ERROR_REPORT("xfs_attr_node_list(5)",					 XFS_ERRLEVEL_LOW,					 context->dp->i_mount);			return(XFS_ERROR(EFSCORRUPTED));		}	}	xfs_da_brelse(NULL, bp);	return(0);}/*======================================================================== * External routines for manipulating out-of-line attribute values. *========================================================================*//*

⌨️ 快捷键说明

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