xfs: split remote attr setting out from replace path
authorDave Chinner <dchinner@redhat.com>
Thu, 12 May 2022 05:12:55 +0000 (15:12 +1000)
committerDave Chinner <david@fromorbit.com>
Thu, 12 May 2022 05:12:55 +0000 (15:12 +1000)
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: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson<allison.henderson@oracle.com>
Reviewed-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
fs/xfs/libxfs/xfs_attr.c
fs/xfs/libxfs/xfs_attr.h
fs/xfs/xfs_trace.h

index d06998d8cbdb1015dc8e583a1c80fef672ade95e..513f0b1a6a4c1136713759727367445c60c44ebd 100644 (file)
@@ -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 @@ next_state:
        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) {
-                       error = xfs_attr_rmtval_find_space(attr);
-                       if (error)
-                               return error;
-               }
+       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);
-                               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);
+               error = xfs_attr_rmtval_alloc(attr);
+               if (error)
                        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 @@ next_state:
                         * 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 @@ next_state:
                ASSERT(0);
                break;
        }
+
+       trace_xfs_attr_set_iter_return(attr->xattri_dela_state, args->dp);
        return error;
 }
 
index 908a13d617163cfd84bf0d14bd375b7b0a8848cf..a0e631df1e24f076eab4143006241af6f5cf1621 100644 (file)
@@ -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" }, \
index 067ab31d7a20db4a0f0de004383836574f4392eb..cb9122327114ee05b39c12a3c7629813498f80a6 100644 (file)
@@ -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);