Commit fd920008 authored by Allison Henderson's avatar Allison Henderson Committed by Dave Chinner

xfs: Set up infrastructure for log attribute replay

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: default avatarAllison Henderson <allison.henderson@oracle.com>
Reviewed-by: default avatarChandan Babu R <chandanrlinux@gmail.com>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 9a39cdab
......@@ -102,6 +102,7 @@ xfs-y += xfs_log.o \
xfs_buf_item_recover.o \
xfs_dquot_item_recover.o \
xfs_extfree_item.o \
xfs_attr_item.o \
xfs_icreate_item.o \
xfs_inode_item.o \
xfs_inode_item_recover.o \
......
......@@ -24,6 +24,10 @@
#include "xfs_quota.h"
#include "xfs_trans_space.h"
#include "xfs_trace.h"
#include "xfs_attr_item.h"
struct kmem_cache *xfs_attri_cache;
struct kmem_cache *xfs_attrd_cache;
/*
* xfs_attr.c
......@@ -61,8 +65,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 +168,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 +842,40 @@ xfs_attr_set(
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
*========================================================================*/
......
......@@ -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__ */
......@@ -23,6 +23,7 @@
#include "xfs_bmap.h"
#include "xfs_alloc.h"
#include "xfs_buf.h"
#include "xfs_attr.h"
static struct kmem_cache *xfs_defer_pending_cache;
......@@ -869,7 +870,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();
......@@ -880,6 +886,8 @@ xfs_defer_init_item_caches(void)
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();
......
......@@ -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.
......
......@@ -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__ */
......@@ -72,6 +72,8 @@ extern const struct xlog_recover_item_ops xlog_rui_item_ops;
extern const struct xlog_recover_item_ops xlog_rud_item_ops;
extern const struct xlog_recover_item_ops xlog_cui_item_ops;
extern const struct xlog_recover_item_ops xlog_cud_item_ops;
extern const struct xlog_recover_item_ops xlog_attri_item_ops;
extern const struct xlog_recover_item_ops xlog_attrd_item_ops;
/*
* Macros, structures, prototypes for internal log manager use.
......
......@@ -23,6 +23,8 @@
#include "xfs_rmap_btree.h"
#include "xfs_log.h"
#include "xfs_trans_priv.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_attr.h"
#include "xfs_reflink.h"
#include "xfs_ag.h"
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-or-later
*
* Copyright (C) 2022 Oracle. All Rights Reserved.
* Author: Allison Henderson <allison.henderson@oracle.com>
*/
#ifndef __XFS_ATTR_ITEM_H__
#define __XFS_ATTR_ITEM_H__
/* kernel only ATTRI/ATTRD definitions */
struct xfs_mount;
struct kmem_zone;
/*
* This is the "attr intention" log item. It is used to log the fact that some
* extended attribute operations need to be processed. An operation is
* currently either a set or remove. Set or remove operations are described by
* the xfs_attr_item which may be logged to this intent.
*
* During a normal attr operation, name and value point to the name and value
* fields of the caller's xfs_da_args structure. During a recovery, the name
* and value buffers are copied from the log, and stored in a trailing buffer
* attached to the xfs_attr_item until they are committed. They are freed when
* the xfs_attr_item itself is freed when the work is done.
*/
struct xfs_attri_log_item {
struct xfs_log_item attri_item;
atomic_t attri_refcount;
int attri_name_len;
int attri_value_len;
void *attri_name;
void *attri_value;
struct xfs_attri_log_format attri_format;
};
/*
* This is the "attr done" log item. It is used to log the fact that some attrs
* earlier mentioned in an attri item have been freed.
*/
struct xfs_attrd_log_item {
struct xfs_log_item attrd_item;
struct xfs_attri_log_item *attrd_attrip;
struct xfs_attrd_log_format attrd_format;
};
#endif /* __XFS_ATTR_ITEM_H__ */
......@@ -15,6 +15,7 @@
#include "xfs_inode.h"
#include "xfs_trans.h"
#include "xfs_bmap.h"
#include "xfs_da_btree.h"
#include "xfs_attr.h"
#include "xfs_attr_sf.h"
#include "xfs_attr_leaf.h"
......
......@@ -17,6 +17,8 @@
#include "xfs_itable.h"
#include "xfs_fsops.h"
#include "xfs_rtalloc.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_attr.h"
#include "xfs_ioctl.h"
#include "xfs_ioctl32.h"
......
......@@ -13,6 +13,8 @@
#include "xfs_inode.h"
#include "xfs_acl.h"
#include "xfs_quota.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_attr.h"
#include "xfs_trans.h"
#include "xfs_trace.h"
......
......@@ -1800,6 +1800,8 @@ static const struct xlog_recover_item_ops *xlog_recover_item_ops[] = {
&xlog_cud_item_ops,
&xlog_bui_item_ops,
&xlog_bud_item_ops,
&xlog_attri_item_ops,
&xlog_attrd_item_ops,
};
static const struct xlog_recover_item_ops *
......
......@@ -132,6 +132,8 @@ xfs_check_ondisk_structs(void)
XFS_CHECK_STRUCT_SIZE(struct xfs_inode_log_format, 56);
XFS_CHECK_STRUCT_SIZE(struct xfs_qoff_logformat, 20);
XFS_CHECK_STRUCT_SIZE(struct xfs_trans_header, 16);
XFS_CHECK_STRUCT_SIZE(struct xfs_attri_log_format, 40);
XFS_CHECK_STRUCT_SIZE(struct xfs_attrd_log_format, 16);
/*
* The v5 superblock format extended several v4 header structures with
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment