Skip to content

Commit

Permalink
xfs: introduce attr remove initial states into xfs_attr_set_iter
Browse files Browse the repository at this point in the history
We need to merge the add and remove code paths to enable safe
recovery of replace operations. Hoist the initial remove states from
xfs_attr_remove_iter into xfs_attr_set_iter. We will make use of
them in the next patches.

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>
  • Loading branch information
Dave Chinner authored and Dave Chinner committed May 12, 2022
1 parent 4e3d96a commit e5d5596
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 62 deletions.
139 changes: 77 additions & 62 deletions fs/xfs/libxfs/xfs_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,68 @@ xfs_attr_rmtval_alloc(
return error;
}

/*
* Mark an attribute entry INCOMPLETE and save pointers to the relevant buffers
* for later deletion of the entry.
*/
static int
xfs_attr_leaf_mark_incomplete(
struct xfs_da_args *args,
struct xfs_da_state *state)
{
int error;

/*
* Fill in disk block numbers in the state structure
* so that we can get the buffers back after we commit
* several transactions in the following calls.
*/
error = xfs_attr_fillstate(state);
if (error)
return error;

/*
* Mark the attribute as INCOMPLETE
*/
return xfs_attr3_leaf_setflag(args);
}

/*
* Initial setup for xfs_attr_node_removename. Make sure the attr is there and
* the blocks are valid. Attr keys with remote blocks will be marked
* incomplete.
*/
static
int xfs_attr_node_removename_setup(
struct xfs_attr_item *attr)
{
struct xfs_da_args *args = attr->xattri_da_args;
struct xfs_da_state **state = &attr->xattri_da_state;
int error;

error = xfs_attr_node_hasname(args, state);
if (error != -EEXIST)
goto out;
error = 0;

ASSERT((*state)->path.blk[(*state)->path.active - 1].bp != NULL);
ASSERT((*state)->path.blk[(*state)->path.active - 1].magic ==
XFS_ATTR_LEAF_MAGIC);

if (args->rmtblkno > 0) {
error = xfs_attr_leaf_mark_incomplete(args, *state);
if (error)
goto out;

error = xfs_attr_rmtval_invalidate(args);
}
out:
if (error)
xfs_da_state_free(*state);

return error;
}

/*
* Remove the original attr we have just replaced. This is dependent on the
* original lookup and insert placing the old attr in args->blkno/args->index
Expand Down Expand Up @@ -549,6 +611,21 @@ xfs_attr_set_iter(
case XFS_DAS_NODE_ADD:
return xfs_attr_node_addname(attr);

case XFS_DAS_SF_REMOVE:
attr->xattri_dela_state = XFS_DAS_DONE;
return xfs_attr_sf_removename(args);
case XFS_DAS_LEAF_REMOVE:
attr->xattri_dela_state = XFS_DAS_DONE;
return xfs_attr_leaf_removename(args);
case XFS_DAS_NODE_REMOVE:
error = xfs_attr_node_removename_setup(attr);
if (error)
return error;
attr->xattri_dela_state = XFS_DAS_NODE_REMOVE_RMT;
if (args->rmtblkno == 0)
attr->xattri_dela_state++;
break;

case XFS_DAS_LEAF_SET_RMT:
case XFS_DAS_NODE_SET_RMT:
error = xfs_attr_rmtval_find_space(attr);
Expand Down Expand Up @@ -1348,68 +1425,6 @@ xfs_attr_node_remove_attr(
}


/*
* Mark an attribute entry INCOMPLETE and save pointers to the relevant buffers
* for later deletion of the entry.
*/
STATIC int
xfs_attr_leaf_mark_incomplete(
struct xfs_da_args *args,
struct xfs_da_state *state)
{
int error;

/*
* Fill in disk block numbers in the state structure
* so that we can get the buffers back after we commit
* several transactions in the following calls.
*/
error = xfs_attr_fillstate(state);
if (error)
return error;

/*
* Mark the attribute as INCOMPLETE
*/
return xfs_attr3_leaf_setflag(args);
}

/*
* Initial setup for xfs_attr_node_removename. Make sure the attr is there and
* the blocks are valid. Attr keys with remote blocks will be marked
* incomplete.
*/
STATIC
int xfs_attr_node_removename_setup(
struct xfs_attr_item *attr)
{
struct xfs_da_args *args = attr->xattri_da_args;
struct xfs_da_state **state = &attr->xattri_da_state;
int error;

error = xfs_attr_node_hasname(args, state);
if (error != -EEXIST)
goto out;
error = 0;

ASSERT((*state)->path.blk[(*state)->path.active - 1].bp != NULL);
ASSERT((*state)->path.blk[(*state)->path.active - 1].magic ==
XFS_ATTR_LEAF_MAGIC);

if (args->rmtblkno > 0) {
error = xfs_attr_leaf_mark_incomplete(args, *state);
if (error)
goto out;

error = xfs_attr_rmtval_invalidate(args);
}
out:
if (error)
xfs_da_state_free(*state);

return error;
}

STATIC int
xfs_attr_node_removename(
struct xfs_da_args *args,
Expand Down
4 changes: 4 additions & 0 deletions fs/xfs/libxfs/xfs_attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,10 @@ enum xfs_delattr_state {
XFS_DAS_RM_NAME, /* Remove attr name */
XFS_DAS_RM_SHRINK, /* We are shrinking the tree */

XFS_DAS_SF_REMOVE, /* Initial shortform set iter state */
XFS_DAS_LEAF_REMOVE, /* Initial leaf form set iter state */
XFS_DAS_NODE_REMOVE, /* Initial node form set iter state */

/* Leaf state set/replace sequence */
XFS_DAS_LEAF_SET_RMT, /* set a remote xattr from a leaf */
XFS_DAS_LEAF_ALLOC_RMT, /* We are allocating remote blocks */
Expand Down
3 changes: 3 additions & 0 deletions fs/xfs/xfs_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -4136,6 +4136,9 @@ TRACE_DEFINE_ENUM(XFS_DAS_NODE_ADD);
TRACE_DEFINE_ENUM(XFS_DAS_RMTBLK);
TRACE_DEFINE_ENUM(XFS_DAS_RM_NAME);
TRACE_DEFINE_ENUM(XFS_DAS_RM_SHRINK);
TRACE_DEFINE_ENUM(XFS_DAS_SF_REMOVE);
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_REMOVE);
TRACE_DEFINE_ENUM(XFS_DAS_NODE_REMOVE);
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_SET_RMT);
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_ALLOC_RMT);
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_REPLACE);
Expand Down

0 comments on commit e5d5596

Please sign in to comment.