aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs/xfs_attr.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2022-05-12 15:12:55 +1000
committerDave Chinner <david@fromorbit.com>2022-05-12 15:12:55 +1000
commit411b434a63248ecff58aaf498b09eaf3b3f52f90 (patch)
tree4fcf36e2d8aabfb78cb2a7407222e9374dfee78b /fs/xfs/libxfs/xfs_attr.c
parentxfs: split remote attr setting out from replace path (diff)
downloadlinux-dev-411b434a63248ecff58aaf498b09eaf3b3f52f90.tar.xz
linux-dev-411b434a63248ecff58aaf498b09eaf3b3f52f90.zip
xfs: XFS_DAS_LEAF_REPLACE state only needed if !LARP
We can skip the REPLACE state when LARP is enabled, but that means the XFS_DAS_FLIP_LFLAG state is now poorly named - it indicates something that has been done rather than what the state is going to do. Rename it to "REMOVE_OLD" to indicate that we are now going to perform removal of the old attr. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Allison Henderson<allison.henderson@oracle.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/libxfs/xfs_attr.c')
-rw-r--r--fs/xfs/libxfs/xfs_attr.c81
1 files changed, 51 insertions, 30 deletions
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 513f0b1a6a4c..9b5ef38b09b2 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -295,6 +295,26 @@ out:
return error;
}
+/*
+ * When we bump the state to REPLACE, we may actually need to skip over the
+ * state. When LARP mode is enabled, we don't need to run the atomic flags flip,
+ * so we skip straight over the REPLACE state and go on to REMOVE_OLD.
+ */
+static void
+xfs_attr_dela_state_set_replace(
+ struct xfs_attr_item *attr,
+ enum xfs_delattr_state replace)
+{
+ struct xfs_da_args *args = attr->xattri_da_args;
+
+ ASSERT(replace == XFS_DAS_LEAF_REPLACE ||
+ replace == XFS_DAS_NODE_REPLACE);
+
+ attr->xattri_dela_state = replace;
+ if (xfs_has_larp(args->dp->i_mount))
+ attr->xattri_dela_state++;
+}
+
static int
xfs_attr_leaf_addname(
struct xfs_attr_item *attr)
@@ -337,7 +357,7 @@ xfs_attr_leaf_addname(
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;
+ xfs_attr_dela_state_set_replace(attr, XFS_DAS_LEAF_REPLACE);
error = -EAGAIN;
} else {
attr->xattri_dela_state = XFS_DAS_DONE;
@@ -368,7 +388,7 @@ xfs_attr_node_addname(
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;
+ xfs_attr_dela_state_set_replace(attr, XFS_DAS_NODE_REPLACE);
error = -EAGAIN;
} else {
attr->xattri_dela_state = XFS_DAS_DONE;
@@ -395,8 +415,11 @@ xfs_attr_rmtval_alloc(
error = xfs_attr_rmtval_set_blk(attr);
if (error)
return error;
- error = -EAGAIN;
- goto out;
+ /* Roll the transaction only if there is more to allocate. */
+ if (attr->xattri_blkcnt > 0) {
+ error = -EAGAIN;
+ goto out;
+ }
}
error = xfs_attr_rmtval_set_value(args);
@@ -407,6 +430,13 @@ xfs_attr_rmtval_alloc(
if (!(args->op_flags & XFS_DA_OP_RENAME)) {
error = xfs_attr3_leaf_clearflag(args);
attr->xattri_dela_state = XFS_DAS_DONE;
+ } else {
+ /*
+ * We are running a REPLACE operation, so we need to bump the
+ * state to the step in that operation.
+ */
+ attr->xattri_dela_state++;
+ xfs_attr_dela_state_set_replace(attr, attr->xattri_dela_state);
}
out:
trace_xfs_attr_rmtval_alloc(attr->xattri_dela_state, args->dp);
@@ -428,7 +458,6 @@ xfs_attr_set_iter(
struct xfs_inode *dp = args->dp;
struct xfs_buf *bp = NULL;
int forkoff, error = 0;
- struct xfs_mount *mp = args->dp->i_mount;
/* State machine switch */
next_state:
@@ -458,37 +487,29 @@ next_state:
return error;
if (attr->xattri_dela_state == XFS_DAS_DONE)
break;
- attr->xattri_dela_state++;
- fallthrough;
+ goto next_state;
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
- * 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.
+ * 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.
*/
- if (!xfs_has_larp(mp)) {
- error = xfs_attr3_leaf_flipflags(args);
- if (error)
- return error;
- /*
- * Commit the flag value change and start the next trans
- * in series at FLIP_FLAG.
- */
- error = -EAGAIN;
- attr->xattri_dela_state++;
- break;
- }
-
+ error = xfs_attr3_leaf_flipflags(args);
+ if (error)
+ return error;
+ /*
+ * Commit the flag value change and start the next trans
+ * in series at REMOVE_OLD.
+ */
+ error = -EAGAIN;
attr->xattri_dela_state++;
- fallthrough;
- case XFS_DAS_FLIP_LFLAG:
- case XFS_DAS_FLIP_NFLAG:
+ break;
+
+ case XFS_DAS_LEAF_REMOVE_OLD:
+ case XFS_DAS_NODE_REMOVE_OLD:
/*
* Dismantle the "old" attribute/value pair by removing a
* "remote" value (if it exists).