+}
+
/*
* Return EEXIST if attr is found, or ENOATTR if not
*/
@@ -773,145 +888,6 @@ xfs_attr_leaf_try_add(
/*
- * Add a name to the leaf attribute list structure
- *
- * This leaf block cannot have a "remote" value, we only call this routine
- * if bmap_one_block() says there is only one block (ie: no remote blks).
- *
- * This routine is meant to function as a delayed operation, and may return
- * -EAGAIN when the transaction needs to be rolled. Calling functions will need
- * to handle this, and recall the function until a successful error code is
- * returned.
- */
-STATIC int
-xfs_attr_leaf_addname(
- struct xfs_attr_item *attr)
-{
- struct xfs_da_args *args = attr->xattri_da_args;
- struct xfs_buf *bp = NULL;
- int error, forkoff;
- struct xfs_inode *dp = args->dp;
- struct xfs_mount *mp = args->dp->i_mount;
-
- /* State machine switch */
- switch (attr->xattri_dela_state) {
- case XFS_DAS_FLIP_LFLAG:
- goto das_flip_flag;
- case XFS_DAS_RM_LBLK:
- goto das_rm_lblk;
- default:
- break;
- }
-
- /*
- * 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.
- */
-
- /* Open coded xfs_attr_rmtval_set without trans handling */
- if ((attr->xattri_flags & XFS_DAC_LEAF_ADDNAME_INIT) == 0) {
- attr->xattri_flags |= XFS_DAC_LEAF_ADDNAME_INIT;
- if (args->rmtblkno > 0) {
- error = xfs_attr_rmtval_find_space(attr);
- if (error)
- return error;
- }
- }
-
- /*
- * Roll through the "value", allocating blocks on disk as
- * required.
- */
- if (attr->xattri_blkcnt > 0) {
- error = xfs_attr_rmtval_set_blk(attr);
- if (error)
- return error;
-
- trace_xfs_das_state_return(attr->xattri_dela_state);
- return -EAGAIN;
- }
-
- error = xfs_attr_rmtval_set_value(args);
- if (error)
- return error;
-
- if (!(args->op_flags & XFS_DA_OP_RENAME)) {
- /*
- * Added a "remote" value, just clear the incomplete flag.
- */
- if (args->rmtblkno > 0)
- error = xfs_attr3_leaf_clearflag(args);
-
- return error;
- }
-
- /*
- * If this is an atomic rename operation, we must "flip" the incomplete
- * flags on the "new" and "old" attribute/value pairs so that one
- * disappears and one appears atomically. Then we must remove the "old"
- * attribute/value pair.
- *
- * In a separate transaction, set the incomplete flag on the "old" attr
- * and clear the incomplete flag on the "new" attr.
- */
- if (!xfs_hasdelattr(mp)) {
- error = xfs_attr3_leaf_flipflags(args);
- if (error)
- return error;
- /*
- * Commit the flag value change and start the next trans in series.
- */
- attr->xattri_dela_state = XFS_DAS_FLIP_LFLAG;
- trace_xfs_das_state_return(attr->xattri_dela_state);
- return -EAGAIN;
- }
-das_flip_flag:
- /*
- * Dismantle the "old" attribute/value pair by removing a "remote" value
- * (if it exists).
- */
- xfs_attr_restore_rmt_blk(args);
-
- error = xfs_attr_rmtval_invalidate(args);
- if (error)
- return error;
-
- /* Set state in case xfs_attr_rmtval_remove returns -EAGAIN */
- attr->xattri_dela_state = XFS_DAS_RM_LBLK;
-das_rm_lblk:
- if (args->rmtblkno) {
- error = xfs_attr_rmtval_remove(attr);
- if (error == -EAGAIN)
- trace_xfs_das_state_return(attr->xattri_dela_state);
- if (error)
- return error;
- }
-
- /*
- * Read in the block containing the "old" attr, then remove the "old"
- * attr from that block (neat, huh!)
- */
- error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
- &bp);
- if (error)
- return error;
-
- xfs_attr3_leaf_remove(bp, args);
-
- /*
- * If the result is small enough, shrink it all into the inode.
- */
- forkoff = xfs_attr_shortform_allfit(bp, dp);
- if (forkoff)
- error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
- /* bp is gone due to xfs_da_shrink_inode */
-
- return error;
-}
-
-/*
* Return EEXIST if attr is found, or ENOATTR if not
*/
STATIC int
@@ -1065,24 +1041,9 @@ xfs_attr_node_addname(
struct xfs_da_state_blk *blk;
int retval = 0;
int error = 0;
- struct xfs_mount *mp = args->dp->i_mount;
trace_xfs_attr_node_addname(args);
- /* State machine switch */
- switch (attr->xattri_dela_state) {
- case XFS_DAS_FLIP_NFLAG:
- goto das_flip_flag;
- case XFS_DAS_FOUND_NBLK:
- goto das_found_nblk;
- case XFS_DAS_ALLOC_NODE:
- goto das_alloc_node;
- case XFS_DAS_RM_NBLK:
- goto das_rm_nblk;
- default:
- break;
- }
-
/*
* Search to see if name already exists, and get back a pointer
* to where it should go.
@@ -1171,93 +1132,24 @@ xfs_attr_node_addname(
attr->xattri_dela_state = XFS_DAS_FOUND_NBLK;
trace_xfs_das_state_return(attr->xattri_dela_state);
return -EAGAIN;
-das_found_nblk:
-
- /*
- * 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) {
- /* Open coded xfs_attr_rmtval_set without trans handling */
- error = xfs_attr_rmtval_find_space(attr);
- if (error)
- return error;
-
- /*
- * Roll through the "value", allocating blocks on disk as
- * required. Set the state in case of -EAGAIN return code
- */
- attr->xattri_dela_state = XFS_DAS_ALLOC_NODE;
-das_alloc_node:
- if (attr->xattri_blkcnt > 0) {
- error = xfs_attr_rmtval_set_blk(attr);
- if (error)
- return error;
-
- trace_xfs_das_state_return(attr->xattri_dela_state);
- return -EAGAIN;
- }
-
- error = xfs_attr_rmtval_set_value(args);
- if (error)
- return error;
- }
-
- if (!(args->op_flags & XFS_DA_OP_RENAME)) {
- /*
- * Added a "remote" value, just clear the incomplete flag.
- */
- if (args->rmtblkno > 0)
- error = xfs_attr3_leaf_clearflag(args);
- retval = error;
- goto out;
- }
-
- /*
- * If this is an atomic rename operation, we must "flip" the incomplete
- * flags on the "new" and "old" attribute/value pairs so that one
- * disappears and one appears atomically. Then we must remove the "old"
- * attribute/value pair.
- *
- * In a separate transaction, set the incomplete flag on the "old" attr
- * and clear the incomplete flag on the "new" attr.
- */
- if (!xfs_hasdelattr(mp)) {
- error = xfs_attr3_leaf_flipflags(args);
- if (error)
- goto out;
- /*
- * Commit the flag value change and start the next trans in series
- */
- attr->xattri_dela_state = XFS_DAS_FLIP_NFLAG;
- trace_xfs_das_state_return(attr->xattri_dela_state);
- return -EAGAIN;
- }
-das_flip_flag:
- /*
- * Dismantle the "old" attribute/value pair by removing a "remote" value
- * (if it exists).
- */
- xfs_attr_restore_rmt_blk(args);
+out:
+ if (state)
+ xfs_da_state_free(state);
- error = xfs_attr_rmtval_invalidate(args);
if (error)
return error;
+ return retval;
+}
- /* Set state in case xfs_attr_rmtval_remove returns -EAGAIN */
- attr->xattri_dela_state = XFS_DAS_RM_NBLK;
-das_rm_nblk:
- if (args->rmtblkno) {
- error = xfs_attr_rmtval_remove(attr);
-
- if (error == -EAGAIN)
- trace_xfs_das_state_return(attr->xattri_dela_state);
-
- if (error)
- return error;
- }
+STATIC
+int xfs_attr_node_addname_work(
+ struct xfs_attr_item *attr)
+{
+ struct xfs_da_args *args = attr->xattri_da_args;
+ struct xfs_da_state *state = NULL;
+ struct xfs_da_state_blk *blk;
+ int retval = 0;
+ int error = 0;
/*
* Re-find the "old" attribute entry after any split ops. The INCOMPLETE
diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
index c80575a..050e5be 100644
--- a/fs/xfs/libxfs/xfs_attr.h
+++ b/fs/xfs/libxfs/xfs_attr.h
@@ -376,8 +376,10 @@ enum xfs_delattr_state {
XFS_DAS_UNINIT = 0, /* No state has been set yet */
XFS_DAS_RM_SHRINK, /* We are shrinking the tree */
XFS_DAS_FOUND_LBLK, /* We found leaf blk for attr */
+ XFS_DAS_ALLOC_LBLK,
+ XFS_DAS_SET_LBLK,
XFS_DAS_FOUND_NBLK, /* We found node blk for attr */
- XFS_DAS_FLIP_LFLAG, /* Flipped leaf INCOMPLETE attr flag */
+ XFS_DAS_INVAL_LBLK, /* Invalidate leaf blks */
XFS_DAS_RM_LBLK, /* A rename is removing leaf blocks */
XFS_DAS_ALLOC_NODE, /* We are allocating node blocks */
XFS_DAS_FLIP_NFLAG, /* Flipped node INCOMPLETE attr flag */
--
2.7.4