Commit 7d035336 authored by Dave Chinner's avatar Dave Chinner Committed by Dave Chinner
Browse files

xfs: split remote attr setting out from replace path



When we set a new xattr, we have three exit paths:

	1. nothing else to do
	2. allocate and set the remote xattr value
	3. perform the rest of a replace operation

Currently we push both 2 and 3 into the same state, regardless of
whether we just set a remote attribute or not. Once we've set the
remote xattr, we have two exit states:

	1. nothing else to do
	2. perform the rest of a replace operation

Hence we can split the remote xattr allocation and setting into
their own states and factor it out of xfs_attr_set_iter() to further
clean up the state machine and the implementation of the state
machine.

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarAllison <Henderson&lt;allison.henderson@oracle.com>
Reviewed-by: default avatarDave Chinner <david@fromorbit.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 251b29c8
Loading
Loading
Loading
Loading
+62 −51
Original line number Diff line number Diff line
@@ -333,9 +333,11 @@ xfs_attr_leaf_addname(
	 * or perform more xattr manipulations. Otherwise there is nothing more
	 * to do and we can return success.
	 */
	if (args->rmtblkno ||
	    (args->op_flags & XFS_DA_OP_RENAME)) {
		attr->xattri_dela_state = XFS_DAS_FOUND_LBLK;
	if (args->rmtblkno) {
		attr->xattri_dela_state = XFS_DAS_LEAF_SET_RMT;
		error = -EAGAIN;
	} else if (args->op_flags & XFS_DA_OP_RENAME) {
		attr->xattri_dela_state = XFS_DAS_LEAF_REPLACE;
		error = -EAGAIN;
	} else {
		attr->xattri_dela_state = XFS_DAS_DONE;
@@ -362,9 +364,11 @@ xfs_attr_node_addname(
	if (error)
		return error;

	if (args->rmtblkno ||
	    (args->op_flags & XFS_DA_OP_RENAME)) {
		attr->xattri_dela_state = XFS_DAS_FOUND_NBLK;
	if (args->rmtblkno) {
		attr->xattri_dela_state = XFS_DAS_NODE_SET_RMT;
		error = -EAGAIN;
	} else if (args->op_flags & XFS_DA_OP_RENAME) {
		attr->xattri_dela_state = XFS_DAS_NODE_REPLACE;
		error = -EAGAIN;
	} else {
		attr->xattri_dela_state = XFS_DAS_DONE;
@@ -374,6 +378,40 @@ xfs_attr_node_addname(
	return error;
}

static int
xfs_attr_rmtval_alloc(
	struct xfs_attr_item		*attr)
{
	struct xfs_da_args              *args = attr->xattri_da_args;
	int				error = 0;

	/*
	 * If there was an out-of-line value, allocate the blocks we
	 * identified for its storage and copy the value.  This is done
	 * after we create the attribute so that we don't overflow the
	 * maximum size of a transaction and/or hit a deadlock.
	 */
	if (attr->xattri_blkcnt > 0) {
		error = xfs_attr_rmtval_set_blk(attr);
		if (error)
			return error;
		error = -EAGAIN;
		goto out;
	}

	error = xfs_attr_rmtval_set_value(args);
	if (error)
		return error;

	/* If this is not a rename, clear the incomplete flag and we're done. */
	if (!(args->op_flags & XFS_DA_OP_RENAME)) {
		error = xfs_attr3_leaf_clearflag(args);
		attr->xattri_dela_state = XFS_DAS_DONE;
	}
out:
	trace_xfs_attr_rmtval_alloc(attr->xattri_dela_state, args->dp);
	return error;
}

/*
 * Set the attribute specified in @args.
@@ -405,54 +443,26 @@ xfs_attr_set_iter(
	case XFS_DAS_NODE_ADD:
		return xfs_attr_node_addname(attr);

	case XFS_DAS_FOUND_LBLK:
	case XFS_DAS_FOUND_NBLK:
		/*
		 * Find space for remote blocks and fall into the allocation
		 * state.
		 */
		if (args->rmtblkno > 0) {
	case XFS_DAS_LEAF_SET_RMT:
	case XFS_DAS_NODE_SET_RMT:
		error = xfs_attr_rmtval_find_space(attr);
		if (error)
			return error;
		}
		attr->xattri_dela_state++;
		fallthrough;

	case XFS_DAS_LEAF_ALLOC_RMT:
	case XFS_DAS_NODE_ALLOC_RMT:

		/*
		 * If there was an out-of-line value, allocate the blocks we
		 * identified for its storage and copy the value.  This is done
		 * after we create the attribute so that we don't overflow the
		 * maximum size of a transaction and/or hit a deadlock.
		 */
		if (args->rmtblkno > 0) {
			if (attr->xattri_blkcnt > 0) {
				error = xfs_attr_rmtval_set_blk(attr);
		error = xfs_attr_rmtval_alloc(attr);
		if (error)
			return error;
				trace_xfs_attr_set_iter_return(
						attr->xattri_dela_state,
						args->dp);
				return -EAGAIN;
			}

			error = xfs_attr_rmtval_set_value(args);
			if (error)
				return error;
		}

		/*
		 * If this is not a rename, clear the incomplete flag and we're
		 * done.
		 */
		if (!(args->op_flags & XFS_DA_OP_RENAME)) {
			if (args->rmtblkno > 0)
				error = xfs_attr3_leaf_clearflag(args);
			return error;
		}
		if (attr->xattri_dela_state == XFS_DAS_DONE)
			break;
		attr->xattri_dela_state++;
		fallthrough;

	case XFS_DAS_LEAF_REPLACE:
	case XFS_DAS_NODE_REPLACE:
		/*
		 * If this is an atomic rename operation, we must "flip" the
		 * incomplete flags on the "new" and "old" attribute/value pairs
@@ -470,10 +480,9 @@ xfs_attr_set_iter(
			 * Commit the flag value change and start the next trans
			 * in series at FLIP_FLAG.
			 */
			error = -EAGAIN;
			attr->xattri_dela_state++;
			trace_xfs_attr_set_iter_return(attr->xattri_dela_state,
						       args->dp);
			return -EAGAIN;
			break;
		}

		attr->xattri_dela_state++;
@@ -548,6 +557,8 @@ xfs_attr_set_iter(
		ASSERT(0);
		break;
	}

	trace_xfs_attr_set_iter_return(attr->xattri_dela_state, args->dp);
	return error;
}

+9 −5
Original line number Diff line number Diff line
@@ -452,15 +452,17 @@ enum xfs_delattr_state {
	XFS_DAS_RM_SHRINK,		/* We are shrinking the tree */

	/* Leaf state set sequence */
	XFS_DAS_FOUND_LBLK,		/* We found leaf blk for attr */
	XFS_DAS_LEAF_SET_RMT,		/* set a remote xattr from a leaf */
	XFS_DAS_LEAF_ALLOC_RMT,		/* We are allocating remote blocks */
	XFS_DAS_LEAF_REPLACE,		/* Perform replace ops on a leaf */
	XFS_DAS_FLIP_LFLAG,		/* Flipped leaf INCOMPLETE attr flag */
	XFS_DAS_RM_LBLK,		/* A rename is removing leaf blocks */
	XFS_DAS_RD_LEAF,		/* Read in the new leaf */

	/* Node state set sequence, must match leaf state above */
	XFS_DAS_FOUND_NBLK,		/* We found node blk for attr */
	XFS_DAS_NODE_SET_RMT,		/* set a remote xattr from a node */
	XFS_DAS_NODE_ALLOC_RMT,		/* We are allocating remote blocks */
	XFS_DAS_NODE_REPLACE,		/* Perform replace ops on a node */
	XFS_DAS_FLIP_NFLAG,		/* Flipped node INCOMPLETE attr flag */
	XFS_DAS_RM_NBLK,		/* A rename is removing node blocks */
	XFS_DAS_CLR_FLAG,		/* Clear incomplete flag */
@@ -476,13 +478,15 @@ enum xfs_delattr_state {
	{ XFS_DAS_RMTBLK,	"XFS_DAS_RMTBLK" }, \
	{ XFS_DAS_RM_NAME,	"XFS_DAS_RM_NAME" }, \
	{ XFS_DAS_RM_SHRINK,	"XFS_DAS_RM_SHRINK" }, \
	{ XFS_DAS_FOUND_LBLK,	"XFS_DAS_FOUND_LBLK" }, \
	{ XFS_DAS_LEAF_SET_RMT,	"XFS_DAS_LEAF_SET_RMT" }, \
	{ XFS_DAS_LEAF_ALLOC_RMT, "XFS_DAS_LEAF_ALLOC_RMT" }, \
	{ XFS_DAS_FOUND_NBLK,	"XFS_DAS_FOUND_NBLK" }, \
	{ XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" },  \
	{ XFS_DAS_LEAF_REPLACE,	"XFS_DAS_LEAF_REPLACE" }, \
	{ XFS_DAS_FLIP_LFLAG,	"XFS_DAS_FLIP_LFLAG" }, \
	{ XFS_DAS_RM_LBLK,	"XFS_DAS_RM_LBLK" }, \
	{ XFS_DAS_RD_LEAF,	"XFS_DAS_RD_LEAF" }, \
	{ XFS_DAS_NODE_SET_RMT,	"XFS_DAS_NODE_SET_RMT" }, \
	{ XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" },  \
	{ XFS_DAS_NODE_REPLACE,	"XFS_DAS_NODE_REPLACE" },  \
	{ XFS_DAS_FLIP_NFLAG,	"XFS_DAS_FLIP_NFLAG" }, \
	{ XFS_DAS_RM_NBLK,	"XFS_DAS_RM_NBLK" }, \
	{ XFS_DAS_CLR_FLAG,	"XFS_DAS_CLR_FLAG" }, \
+6 −3
Original line number Diff line number Diff line
@@ -4136,13 +4136,15 @@ TRACE_DEFINE_ENUM(XFS_DAS_NODE_ADD);
TRACE_DEFINE_ENUM(XFS_DAS_RMTBLK);
TRACE_DEFINE_ENUM(XFS_DAS_RM_NAME);
TRACE_DEFINE_ENUM(XFS_DAS_RM_SHRINK);
TRACE_DEFINE_ENUM(XFS_DAS_FOUND_LBLK);
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_SET_RMT);
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_ALLOC_RMT);
TRACE_DEFINE_ENUM(XFS_DAS_FOUND_NBLK);
TRACE_DEFINE_ENUM(XFS_DAS_NODE_ALLOC_RMT);
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_REPLACE);
TRACE_DEFINE_ENUM(XFS_DAS_FLIP_LFLAG);
TRACE_DEFINE_ENUM(XFS_DAS_RM_LBLK);
TRACE_DEFINE_ENUM(XFS_DAS_RD_LEAF);
TRACE_DEFINE_ENUM(XFS_DAS_NODE_SET_RMT);
TRACE_DEFINE_ENUM(XFS_DAS_NODE_ALLOC_RMT);
TRACE_DEFINE_ENUM(XFS_DAS_NODE_REPLACE);
TRACE_DEFINE_ENUM(XFS_DAS_FLIP_NFLAG);
TRACE_DEFINE_ENUM(XFS_DAS_RM_NBLK);
TRACE_DEFINE_ENUM(XFS_DAS_CLR_FLAG);
@@ -4172,6 +4174,7 @@ DEFINE_DAS_STATE_EVENT(xfs_attr_set_iter_return);
DEFINE_DAS_STATE_EVENT(xfs_attr_leaf_addname_return);
DEFINE_DAS_STATE_EVENT(xfs_attr_node_addname_return);
DEFINE_DAS_STATE_EVENT(xfs_attr_remove_iter_return);
DEFINE_DAS_STATE_EVENT(xfs_attr_rmtval_alloc);
DEFINE_DAS_STATE_EVENT(xfs_attr_rmtval_remove_return);
DEFINE_DAS_STATE_EVENT(xfs_attr_defer_add);
DEFINE_DAS_STATE_EVENT(xfs_attr_defer_replace);