]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: log parent pointer xattr replace operations
authorAllison Henderson <allison.henderson@oracle.com>
Tue, 9 Jan 2024 17:41:32 +0000 (09:41 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 10 Apr 2024 00:21:29 +0000 (17:21 -0700)
The parent pointer code needs to do a deferred parent pointer replace
operation with the xattr log intent code.  Declare a new logged xattr
opcode and push it through the log.

(Formerly titled "xfs: Add new name to attri/d" and described as
follows:

This patch adds two new fields to the atti/d.  They are nname and
nnamelen.  This will be used for parent pointer updates since a
rename operation may cause the parent pointer to update both the
name and value.  So we need to carry both the new name as well as
the target name in the attri/d.)

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
[djwong: reworked to handle new disk format]
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/defer_item.c
libxfs/xfs_attr.c
libxfs/xfs_attr.h
libxfs/xfs_da_btree.h
libxfs/xfs_log_format.h

index 0786fdef569e4c3145e58ac58769111d7f6805c4..aed9a0559a353f4e8210255af19db0b508dd0689 100644 (file)
@@ -716,8 +716,8 @@ xfs_attr_defer_parent(
                new->xattri_dela_state = xfs_attr_init_add_state(args);
                break;
        case XFS_ATTR_DEFER_REPLACE:
-               /* will be added in subsequent patches */
-               ASSERT(0);
+               new->xattri_op_flags = XFS_ATTRI_OP_FLAGS_PPTR_REPLACE;
+               new->xattri_dela_state = xfs_attr_init_replace_state(args);
                break;
        case XFS_ATTR_DEFER_REMOVE:
                new->xattri_op_flags = XFS_ATTRI_OP_FLAGS_PPTR_REMOVE;
index f0d8db9fad3482732f981554a9d545723304b991..1b3012413409365af035dabff5644d1088d6e9de 100644 (file)
@@ -440,6 +440,23 @@ xfs_attr_hashval(
        return xfs_attr_hashname(name, namelen);
 }
 
+/*
+ * PPTR_REPLACE operations require the caller to set the old and new names and
+ * values explicitly.  Update the canonical fields to the new name and value
+ * here now that the removal phase has finished.
+ */
+static void
+xfs_attr_update_pptr_replace_args(
+       struct xfs_da_args      *args)
+{
+       ASSERT(args->new_namelen > 0);
+       args->name = args->new_name;
+       args->namelen = args->new_namelen;
+       args->value = args->new_value;
+       args->valuelen = args->new_valuelen;
+       xfs_attr_sethash(args);
+}
+
 /*
  * Handle the state change on completion of a multi-state attr operation.
  *
@@ -460,6 +477,8 @@ xfs_attr_complete_op(
 
        if (!(args->op_flags & XFS_DA_OP_REPLACE))
                replace_state = XFS_DAS_DONE;
+       else if (xfs_attr_intent_op(attr) == XFS_ATTRI_OP_FLAGS_PPTR_REPLACE)
+               xfs_attr_update_pptr_replace_args(args);
 
        args->op_flags &= ~XFS_DA_OP_REPLACE;
        args->attr_filter &= ~XFS_ATTR_INCOMPLETE;
index df91c94d5bf5c13deaf32e2a1be2222cfc8263df..d63305fc541553454b15749ef5a01ce6163e67de 100644 (file)
@@ -510,8 +510,8 @@ struct xfs_attr_intent {
        struct xfs_da_args              *xattri_da_args;
 
        /*
-        * Shared buffer containing the attr name and value so that the logging
-        * code can share large memory buffers between log items.
+        * Shared buffer containing the attr name, new name, and value so that
+        * the logging code can share large memory buffers between log items.
         */
        struct xfs_attri_log_nameval    *xattri_nameval;
 
index 47485f5edae86c6188046ab9e1cbb0b075e40be7..8d7a38fe2a5c075b55b1afad01107f2e4d021b5a 100644 (file)
@@ -55,7 +55,9 @@ enum xfs_dacmp {
 typedef struct xfs_da_args {
        struct xfs_da_geometry *geo;    /* da block geometry */
        const uint8_t   *name;          /* string (maybe not NULL terminated) */
+       const uint8_t   *new_name;      /* new attr name */
        void            *value;         /* set of bytes (maybe contain NULLs) */
+       void            *new_value;     /* new xattr value (may contain NULLs) */
        struct xfs_inode *dp;           /* directory inode to manipulate */
        struct xfs_trans *trans;        /* current trans (changes over time) */
 
@@ -63,11 +65,13 @@ typedef struct xfs_da_args {
        xfs_ino_t       owner;          /* inode that owns the dir/attr data */
 
        int             valuelen;       /* length of value */
+       int             new_valuelen;   /* length of new_value */
        uint8_t         filetype;       /* filetype of inode for directories */
        uint8_t         op_flags;       /* operation flags */
        uint8_t         attr_filter;    /* XFS_ATTR_{ROOT,SECURE,INCOMPLETE} */
        uint8_t         xattr_flags;    /* XATTR_{CREATE,REPLACE} */
        short           namelen;        /* length of string (maybe no NULL) */
+       short           new_namelen;    /* length of new attr name */
        xfs_dahash_t    hashval;        /* hash value of name */
        xfs_extlen_t    total;          /* total blocks needed, for 1st bmap */
        int             whichfork;      /* data or attribute fork */
index 96732a212507e1f995b71dab2f5a8b2210c9f805..632dd97324557a04d69042d452be230d41a49c82 100644 (file)
@@ -115,11 +115,13 @@ struct xfs_unmount_log_format {
 #define XLOG_REG_TYPE_BUD_FORMAT       26
 #define XLOG_REG_TYPE_ATTRI_FORMAT     27
 #define XLOG_REG_TYPE_ATTRD_FORMAT     28
-#define XLOG_REG_TYPE_ATTR_NAME        29
+#define XLOG_REG_TYPE_ATTR_NAME                29
 #define XLOG_REG_TYPE_ATTR_VALUE       30
 #define XLOG_REG_TYPE_XMI_FORMAT       31
 #define XLOG_REG_TYPE_XMD_FORMAT       32
-#define XLOG_REG_TYPE_MAX              32
+#define XLOG_REG_TYPE_ATTR_NEWNAME     33
+#define XLOG_REG_TYPE_ATTR_NEWVALUE    34
+#define XLOG_REG_TYPE_MAX              34
 
 /*
  * Flags to log operation header
@@ -1028,6 +1030,7 @@ struct xfs_icreate_log {
 #define XFS_ATTRI_OP_FLAGS_REPLACE     3       /* Replace the attribute */
 #define XFS_ATTRI_OP_FLAGS_PPTR_SET    4       /* Set parent pointer */
 #define XFS_ATTRI_OP_FLAGS_PPTR_REMOVE 5       /* Remove parent pointer */
+#define XFS_ATTRI_OP_FLAGS_PPTR_REPLACE        6       /* Replace parent pointer */
 #define XFS_ATTRI_OP_FLAGS_TYPE_MASK   0xFF    /* Flags type mask */
 
 /*
@@ -1050,7 +1053,18 @@ struct xfs_attri_log_format {
        uint64_t        alfi_id;        /* attri identifier */
        uint64_t        alfi_ino;       /* the inode for this attr operation */
        uint32_t        alfi_op_flags;  /* marks the op as a set or remove */
-       uint32_t        alfi_name_len;  /* attr name length */
+       union {
+               uint32_t        alfi_name_len;  /* attr name length */
+               struct {
+                       /*
+                        * For PPTR_REPLACE, these are the lengths of the old
+                        * and new attr names.  The new and old values must
+                        * have the same length.
+                        */
+                       uint16_t        alfi_old_name_len;
+                       uint16_t        alfi_new_name_len;
+               };
+       };
        uint32_t        alfi_value_len; /* attr value length */
        uint32_t        alfi_attr_filter;/* attr filter flags */
 };