]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: rework deferred attribute operation setup
authorDave Chinner <dchinner@redhat.com>
Wed, 22 Jun 2022 19:28:52 +0000 (14:28 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Wed, 22 Jun 2022 19:28:52 +0000 (14:28 -0500)
Source kernel commit: 709c8632597c3276cd21324b0256628f1a7fd4df

Logged attribute intents only have set and remove types - there is
no separate intent type for a replace operation. We should have a
separate type for a replace operation, as it needs to perform
operations that neither SET or REMOVE can perform.

Add this type to the intent items and rearrange the deferred
operation setup to reflect the different operations we are
performing.

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>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
include/xfs_trace.h
libxfs/xfs_attr.c
libxfs/xfs_attr.h
libxfs/xfs_log_format.h

index e4959d622e45232627587dd80f2ad4e0f8c201a1..3484b53f3f2b4a8f28ee62ecaf35288f6076aa74 100644 (file)
@@ -39,6 +39,9 @@
 #define trace_xfs_alloc_vextent_loopfailed(a)  ((void) 0)
 #define trace_xfs_alloc_vextent_allfailed(a)   ((void) 0)
 
+#define trace_xfs_attr_defer_add(...)          ((void) 0)
+#define trace_xfs_attr_defer_replace(...)      ((void) 0)
+#define trace_xfs_attr_defer_remove(...)       ((void) 0)
 #define trace_xfs_attr_sf_addname_return(...)  ((void) 0)
 #define trace_xfs_attr_set_iter_return(...)    ((void) 0)
 #define trace_xfs_attr_leaf_addname_return(...)        ((void) 0)
index 0991f5dc53aa1af8a00ef14cfaeafb363ed24463..eb23d59ee18b96d34d13f2481c641181d2c52f88 100644 (file)
@@ -668,6 +668,81 @@ xfs_attr_lookup(
        return xfs_attr_node_hasname(args, NULL);
 }
 
+static int
+xfs_attr_item_init(
+       struct xfs_da_args      *args,
+       unsigned int            op_flags,       /* op flag (set or remove) */
+       struct xfs_attr_item    **attr)         /* new xfs_attr_item */
+{
+
+       struct xfs_attr_item    *new;
+
+       new = kmem_zalloc(sizeof(struct xfs_attr_item), KM_NOFS);
+       new->xattri_op_flags = op_flags;
+       new->xattri_da_args = args;
+
+       *attr = new;
+       return 0;
+}
+
+/* Sets an attribute for an inode as a deferred operation */
+static int
+xfs_attr_defer_add(
+       struct xfs_da_args      *args)
+{
+       struct xfs_attr_item    *new;
+       int                     error = 0;
+
+       error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_SET, &new);
+       if (error)
+               return error;
+
+       new->xattri_dela_state = XFS_DAS_UNINIT;
+       xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
+       trace_xfs_attr_defer_add(new->xattri_dela_state, args->dp);
+
+       return 0;
+}
+
+/* Sets an attribute for an inode as a deferred operation */
+static int
+xfs_attr_defer_replace(
+       struct xfs_da_args      *args)
+{
+       struct xfs_attr_item    *new;
+       int                     error = 0;
+
+       error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_REPLACE, &new);
+       if (error)
+               return error;
+
+       new->xattri_dela_state = XFS_DAS_UNINIT;
+       xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
+       trace_xfs_attr_defer_replace(new->xattri_dela_state, args->dp);
+
+       return 0;
+}
+
+/* Removes an attribute for an inode as a deferred operation */
+static int
+xfs_attr_defer_remove(
+       struct xfs_da_args      *args)
+{
+
+       struct xfs_attr_item    *new;
+       int                     error;
+
+       error  = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_REMOVE, &new);
+       if (error)
+               return error;
+
+       new->xattri_dela_state = XFS_DAS_UNINIT;
+       xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
+       trace_xfs_attr_defer_remove(new->xattri_dela_state, args->dp);
+
+       return 0;
+}
+
 /*
  * Note: If args->value is NULL the attribute will be removed, just like the
  * Linux ->setattr API.
@@ -756,29 +831,35 @@ xfs_attr_set(
        }
 
        error = xfs_attr_lookup(args);
-       if (args->value) {
-               if (error == -EEXIST && (args->attr_flags & XATTR_CREATE))
-                       goto out_trans_cancel;
-               if (error == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
-                       goto out_trans_cancel;
-               if (error != -ENOATTR && error != -EEXIST)
+       switch (error) {
+       case -EEXIST:
+               /* if no value, we are performing a remove operation */
+               if (!args->value) {
+                       error = xfs_attr_defer_remove(args);
+                       break;
+               }
+               /* Pure create fails if the attr already exists */
+               if (args->attr_flags & XATTR_CREATE)
                        goto out_trans_cancel;
 
-               error = xfs_attr_set_deferred(args);
-               if (error)
+               error = xfs_attr_defer_replace(args);
+               break;
+       case -ENOATTR:
+               /* Can't remove what isn't there. */
+               if (!args->value)
                        goto out_trans_cancel;
 
-               /* shortform attribute has already been committed */
-               if (!args->trans)
-                       goto out_unlock;
-       } else {
-               if (error != -EEXIST)
+               /* Pure replace fails if no existing attr to replace. */
+               if (args->attr_flags & XATTR_REPLACE)
                        goto out_trans_cancel;
 
-               error = xfs_attr_remove_deferred(args);
-               if (error)
-                       goto out_trans_cancel;
+               error = xfs_attr_defer_add(args);
+               break;
+       default:
+               goto out_trans_cancel;
        }
+       if (error)
+               goto out_trans_cancel;
 
        /*
         * If this is a synchronous mount, make sure that the
@@ -842,58 +923,6 @@ xfs_attrd_destroy_cache(void)
        xfs_attrd_cache = NULL;
 }
 
-STATIC int
-xfs_attr_item_init(
-       struct xfs_da_args      *args,
-       unsigned int            op_flags,       /* op flag (set or remove) */
-       struct xfs_attr_item    **attr)         /* new xfs_attr_item */
-{
-
-       struct xfs_attr_item    *new;
-
-       new = kmem_zalloc(sizeof(struct xfs_attr_item), KM_NOFS);
-       new->xattri_op_flags = op_flags;
-       new->xattri_da_args = args;
-
-       *attr = new;
-       return 0;
-}
-
-/* Sets an attribute for an inode as a deferred operation */
-int
-xfs_attr_set_deferred(
-       struct xfs_da_args      *args)
-{
-       struct xfs_attr_item    *new;
-       int                     error = 0;
-
-       error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_SET, &new);
-       if (error)
-               return error;
-
-       xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
-
-       return 0;
-}
-
-/* Removes an attribute for an inode as a deferred operation */
-int
-xfs_attr_remove_deferred(
-       struct xfs_da_args      *args)
-{
-
-       struct xfs_attr_item    *new;
-       int                     error;
-
-       error  = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_REMOVE, &new);
-       if (error)
-               return error;
-
-       xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
-
-       return 0;
-}
-
 /*========================================================================
  * External routines when attribute list is inside the inode
  *========================================================================*/
index f6c13d2bfbcd37754d9f1fd98ebe6670e543de56..c9c867e3406c02cff05bd45d63db93994f95118a 100644 (file)
@@ -521,8 +521,6 @@ bool xfs_attr_namecheck(const void *name, size_t length);
 int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
 void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres,
                         unsigned int *total);
-int xfs_attr_set_deferred(struct xfs_da_args *args);
-int xfs_attr_remove_deferred(struct xfs_da_args *args);
 
 extern struct kmem_cache       *xfs_attri_cache;
 extern struct kmem_cache       *xfs_attrd_cache;
index a27492e9967365e144deafdb4d98d61d7cd8d53d..f7edd1ecf6d98e352bd30ac8e1d2cdc7f63fc82e 100644 (file)
@@ -908,6 +908,7 @@ struct xfs_icreate_log {
  */
 #define XFS_ATTR_OP_FLAGS_SET          1       /* Set the attribute */
 #define XFS_ATTR_OP_FLAGS_REMOVE       2       /* Remove the attribute */
+#define XFS_ATTR_OP_FLAGS_REPLACE      3       /* Replace the attribute */
 #define XFS_ATTR_OP_FLAGS_TYPE_MASK    0xFF    /* Flags type mask */
 
 /*