]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: Set up infrastructure for log attribute replay
authorAllison Henderson <allison.henderson@oracle.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: fd920008784ead369e79c2be2f8d9cc736e306ca

Currently attributes are modified directly across one or more
transactions. But they are not logged or replayed in the event of an
error. The goal of log attr replay is to enable logging and replaying
of attribute operations using the existing delayed operations
infrastructure.  This will later enable the attributes to become part of
larger multi part operations that also must first be recorded to the
log.  This is mostly of interest in the scheme of parent pointers which
would need to maintain an attribute containing parent inode information
any time an inode is moved, created, or removed.  Parent pointers would
then be of interest to any feature that would need to quickly derive an
inode path from the mount point. Online scrub, nfs lookups and fs grow
or shrink operations are all features that could take advantage of this.

This patch adds two new log item types for setting or removing
attributes as deferred operations.  The xfs_attri_log_item will log an
intent to set or remove an attribute.  The corresponding
xfs_attrd_log_item holds a reference to the xfs_attri_log_item and is
freed once the transaction is done.  Both log items use a generic
xfs_attr_log_format structure that contains the attribute name, value,
flags, inode, and an op_flag that indicates if the operations is a set
or remove.

[dchinner: added extra little bits needed for intent whiteouts]

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Chandan Babu R <chandanrlinux@gmail.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>
libxfs/libxfs_priv.h
libxfs/xfs_attr.c
libxfs/xfs_attr.h
libxfs/xfs_defer.c
libxfs/xfs_defer.h
libxfs/xfs_log_format.h

index 9260e6829d7e51c64f6d20f01e471ea2c36af19e..4bad869c94a8eabeb3c752acf4bd9cc7f0c550db 100644 (file)
@@ -718,4 +718,12 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip,
 /* xfs_inode.h */
 #define xfs_iflags_set(ip, flags)      do { } while (0)
 
+/* xfs_attr_item.h */
+struct xfs_attri_log_item {
+/* intentionally empty to allow build and retain identical libxfs files */
+};
+struct xfs_attrd_log_item {
+/* intentionally empty to allow build and retain identical libxfs files */
+};
+
 #endif /* __LIBXFS_INTERNAL_XFS_H__ */
index 1450c221f8b6b0cc1bddc7dd34b5863bd3194745..b0608f725cde62452c482557441f600ab1977afc 100644 (file)
@@ -25,6 +25,9 @@
 #include "xfs_trans_space.h"
 #include "xfs_trace.h"
 
+struct kmem_cache              *xfs_attri_cache;
+struct kmem_cache              *xfs_attrd_cache;
+
 /*
  * xfs_attr.c
  *
@@ -61,8 +64,6 @@ STATIC int xfs_attr_node_hasname(xfs_da_args_t *args,
                                 struct xfs_da_state **state);
 STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
 STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
-STATIC int xfs_attr_set_iter(struct xfs_delattr_context *dac,
-                            struct xfs_buf **leaf_bp);
 STATIC int xfs_attr_node_removename(struct xfs_da_args *args,
                                    struct xfs_da_state *state);
 
@@ -166,7 +167,7 @@ xfs_attr_get(
 /*
  * Calculate how many blocks we need for the new attribute,
  */
-STATIC int
+int
 xfs_attr_calc_size(
        struct xfs_da_args      *args,
        int                     *local)
@@ -840,6 +841,40 @@ out_trans_cancel:
        goto out_unlock;
 }
 
+int __init
+xfs_attri_init_cache(void)
+{
+       xfs_attri_cache = kmem_cache_create("xfs_attri",
+                                           sizeof(struct xfs_attri_log_item),
+                                           0, 0, NULL);
+
+       return xfs_attri_cache != NULL ? 0 : -ENOMEM;
+}
+
+void
+xfs_attri_destroy_cache(void)
+{
+       kmem_cache_destroy(xfs_attri_cache);
+       xfs_attri_cache = NULL;
+}
+
+int __init
+xfs_attrd_init_cache(void)
+{
+       xfs_attrd_cache = kmem_cache_create("xfs_attrd",
+                                           sizeof(struct xfs_attrd_log_item),
+                                           0, 0, NULL);
+
+       return xfs_attrd_cache != NULL ? 0 : -ENOMEM;
+}
+
+void
+xfs_attrd_destroy_cache(void)
+{
+       kmem_cache_destroy(xfs_attrd_cache);
+       xfs_attrd_cache = NULL;
+}
+
 /*========================================================================
  * External routines when attribute list is inside the inode
  *========================================================================*/
index 5e71f719bdd52b883b335c0cb3db6fbddd767b0e..80b6f28b0d1ad043160c55fe1c8e879179adf31c 100644 (file)
@@ -28,6 +28,11 @@ struct xfs_attr_list_context;
  */
 #define        ATTR_MAX_VALUELEN       (64*1024)       /* max length of a value */
 
+static inline bool xfs_has_larp(struct xfs_mount *mp)
+{
+       return false;
+}
+
 /*
  * Kernel-internal version of the attrlist cursor.
  */
@@ -461,6 +466,11 @@ enum xfs_delattr_state {
 struct xfs_delattr_context {
        struct xfs_da_args      *da_args;
 
+       /*
+        * Used by xfs_attr_set to hold a leaf buffer across a transaction roll
+        */
+       struct xfs_buf          *leaf_bp;
+
        /* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */
        struct xfs_bmbt_irec    map;
        xfs_dablk_t             lblkno;
@@ -474,6 +484,23 @@ struct xfs_delattr_context {
        enum xfs_delattr_state  dela_state;
 };
 
+/*
+ * List of attrs to commit later.
+ */
+struct xfs_attr_item {
+       struct xfs_delattr_context      xattri_dac;
+
+       /*
+        * Indicates if the attr operation is a set or a remove
+        * XFS_ATTR_OP_FLAGS_{SET,REMOVE}
+        */
+       unsigned int                    xattri_op_flags;
+
+       /* used to log this item to an intent */
+       struct list_head                xattri_list;
+};
+
+
 /*========================================================================
  * Function prototypes for the kernel.
  *========================================================================*/
@@ -490,10 +517,21 @@ int xfs_attr_get_ilocked(struct xfs_da_args *args);
 int xfs_attr_get(struct xfs_da_args *args);
 int xfs_attr_set(struct xfs_da_args *args);
 int xfs_attr_set_args(struct xfs_da_args *args);
+int xfs_attr_set_iter(struct xfs_delattr_context *dac,
+                     struct xfs_buf **leaf_bp);
 int xfs_attr_remove_args(struct xfs_da_args *args);
 int xfs_attr_remove_iter(struct xfs_delattr_context *dac);
 bool xfs_attr_namecheck(const void *name, size_t length);
 void xfs_delattr_context_init(struct xfs_delattr_context *dac,
                              struct xfs_da_args *args);
+int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
+
+extern struct kmem_cache       *xfs_attri_cache;
+extern struct kmem_cache       *xfs_attrd_cache;
+
+int __init xfs_attri_init_cache(void);
+void xfs_attri_destroy_cache(void);
+int __init xfs_attrd_init_cache(void);
+void xfs_attrd_destroy_cache(void);
 
 #endif /* __XFS_ATTR_H__ */
index 8af4ae7b9b582e9619b97939c2beaae2b6642dad..4923b4225fbc8434e2f291010362fee8e9b3c81d 100644 (file)
@@ -18,6 +18,7 @@
 #include "xfs_refcount.h"
 #include "xfs_bmap.h"
 #include "xfs_alloc.h"
+#include "xfs_attr.h"
 
 static struct kmem_cache       *xfs_defer_pending_cache;
 
@@ -864,7 +865,12 @@ xfs_defer_init_item_caches(void)
        error = xfs_extfree_intent_init_cache();
        if (error)
                goto err;
-
+       error = xfs_attri_init_cache();
+       if (error)
+               goto err;
+       error = xfs_attrd_init_cache();
+       if (error)
+               goto err;
        return 0;
 err:
        xfs_defer_destroy_item_caches();
@@ -875,6 +881,8 @@ err:
 void
 xfs_defer_destroy_item_caches(void)
 {
+       xfs_attri_destroy_cache();
+       xfs_attrd_destroy_cache();
        xfs_extfree_intent_destroy_cache();
        xfs_bmap_intent_destroy_cache();
        xfs_refcount_intent_destroy_cache();
index 7bb8a31ad65bb453b14b95c5a5a59f814665c85d..fcd23e5cf1ee6494be28d6b46f4bfd7255c97c8d 100644 (file)
@@ -63,6 +63,8 @@ extern const struct xfs_defer_op_type xfs_refcount_update_defer_type;
 extern const struct xfs_defer_op_type xfs_rmap_update_defer_type;
 extern const struct xfs_defer_op_type xfs_extent_free_defer_type;
 extern const struct xfs_defer_op_type xfs_agfl_free_defer_type;
+extern const struct xfs_defer_op_type xfs_attr_defer_type;
+
 
 /*
  * Deferred operation item relogging limits.
index afce51633f03d6b7d5b8d226b7d787b02f3707fa..a27492e9967365e144deafdb4d98d61d7cd8d53d 100644 (file)
@@ -113,7 +113,12 @@ struct xfs_unmount_log_format {
 #define XLOG_REG_TYPE_CUD_FORMAT       24
 #define XLOG_REG_TYPE_BUI_FORMAT       25
 #define XLOG_REG_TYPE_BUD_FORMAT       26
-#define XLOG_REG_TYPE_MAX              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_VALUE       30
+#define XLOG_REG_TYPE_MAX              30
+
 
 /*
  * Flags to log operation header
@@ -236,6 +241,8 @@ typedef struct xfs_trans_header {
 #define        XFS_LI_CUD              0x1243
 #define        XFS_LI_BUI              0x1244  /* bmbt update intent */
 #define        XFS_LI_BUD              0x1245
+#define        XFS_LI_ATTRI            0x1246  /* attr set/remove intent*/
+#define        XFS_LI_ATTRD            0x1247  /* attr set/remove done */
 
 #define XFS_LI_TYPE_DESC \
        { XFS_LI_EFI,           "XFS_LI_EFI" }, \
@@ -251,7 +258,9 @@ typedef struct xfs_trans_header {
        { XFS_LI_CUI,           "XFS_LI_CUI" }, \
        { XFS_LI_CUD,           "XFS_LI_CUD" }, \
        { XFS_LI_BUI,           "XFS_LI_BUI" }, \
-       { XFS_LI_BUD,           "XFS_LI_BUD" }
+       { XFS_LI_BUD,           "XFS_LI_BUD" }, \
+       { XFS_LI_ATTRI,         "XFS_LI_ATTRI" }, \
+       { XFS_LI_ATTRD,         "XFS_LI_ATTRD" }
 
 /*
  * Inode Log Item Format definitions.
@@ -893,4 +902,35 @@ struct xfs_icreate_log {
        __be32          icl_gen;        /* inode generation number to use */
 };
 
+/*
+ * Flags for deferred attribute operations.
+ * Upper bits are flags, lower byte is type code
+ */
+#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_TYPE_MASK    0xFF    /* Flags type mask */
+
+/*
+ * This is the structure used to lay out an attr log item in the
+ * log.
+ */
+struct xfs_attri_log_format {
+       uint16_t        alfi_type;      /* attri log item type */
+       uint16_t        alfi_size;      /* size of this item */
+       uint32_t        __pad;          /* pad to 64 bit aligned */
+       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 */
+       uint32_t        alfi_value_len; /* attr value length */
+       uint32_t        alfi_attr_flags;/* attr flags */
+};
+
+struct xfs_attrd_log_format {
+       uint16_t        alfd_type;      /* attrd log item type */
+       uint16_t        alfd_size;      /* size of this item */
+       uint32_t        __pad;          /* pad to 64 bit aligned */
+       uint64_t        alfd_alf_id;    /* id of corresponding attri */
+};
+
 #endif /* __XFS_LOG_FORMAT_H__ */