diff options
author | Dave Chinner <dchinner@redhat.com> | 2022-05-12 08:12:55 +0300 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2022-05-12 08:12:55 +0300 |
commit | 2e7ef218e489f5b3f5156a305b55a08c41839c1b (patch) | |
tree | 3409fa2320fa1bcfee3bb6f03b4c64732f0b8aca /fs/xfs/libxfs | |
parent | 411b434a63248ecff58aaf498b09eaf3b3f52f90 (diff) | |
download | linux-2e7ef218e489f5b3f5156a305b55a08c41839c1b.tar.xz |
xfs: remote xattr removal in xfs_attr_set_iter() is conditional
We may not have a remote value for the old xattr we have to remove,
so skip over the remote value removal states and go straight to
the xattr name removal in the leaf/node block.
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>
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_attr.c | 59 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_attr.h | 8 |
2 files changed, 34 insertions, 33 deletions
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 9b5ef38b09b2..c0e72e9c4f53 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -494,15 +494,14 @@ next_state: /* * We must "flip" the incomplete flags on the "new" and "old" * attribute/value pairs so that one disappears and one appears - * atomically. Then we must remove the "old" attribute/value - * pair. + * atomically. */ error = xfs_attr3_leaf_flipflags(args); if (error) return error; /* - * Commit the flag value change and start the next trans - * in series at REMOVE_OLD. + * We must commit the flag value change now to make it atomic + * and then we can start the next trans in series at REMOVE_OLD. */ error = -EAGAIN; attr->xattri_dela_state++; @@ -511,41 +510,43 @@ next_state: case XFS_DAS_LEAF_REMOVE_OLD: case XFS_DAS_NODE_REMOVE_OLD: /* - * Dismantle the "old" attribute/value pair by removing a - * "remote" value (if it exists). + * If we have a remote attr, start the process of removing it + * by invalidating any cached buffers. + * + * If we don't have a remote attr, we skip the remote block + * removal state altogether with a second state increment. */ xfs_attr_restore_rmt_blk(args); - error = xfs_attr_rmtval_invalidate(args); - if (error) - return error; - - attr->xattri_dela_state++; - fallthrough; - case XFS_DAS_RM_LBLK: - case XFS_DAS_RM_NBLK: if (args->rmtblkno) { - error = xfs_attr_rmtval_remove(attr); - if (error == -EAGAIN) - trace_xfs_attr_set_iter_return( - attr->xattri_dela_state, args->dp); + error = xfs_attr_rmtval_invalidate(args); if (error) return error; - - attr->xattri_dela_state = XFS_DAS_RD_LEAF; - trace_xfs_attr_set_iter_return(attr->xattri_dela_state, - args->dp); - return -EAGAIN; + } else { + attr->xattri_dela_state++; } + attr->xattri_dela_state++; + goto next_state; + + case XFS_DAS_LEAF_REMOVE_RMT: + case XFS_DAS_NODE_REMOVE_RMT: + error = xfs_attr_rmtval_remove(attr); + if (error == -EAGAIN) + break; + if (error) + return error; + /* - * This is the end of the shared leaf/node sequence. We need - * to continue at the next state in the sequence, but we can't - * easily just fall through. So we increment to the next state - * and then jump back to switch statement to evaluate the next - * state correctly. + * We've finished removing the remote attr blocks, so commit the + * transaction and move on to removing the attr name from the + * leaf/node block. Removing the attr might require a full + * transaction reservation for btree block freeing, so we + * can't do that in the same transaction where we removed the + * remote attr blocks. */ + error = -EAGAIN; attr->xattri_dela_state++; - goto next_state; + break; case XFS_DAS_RD_LEAF: /* diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h index 01a50613726f..1e038c23029a 100644 --- a/fs/xfs/libxfs/xfs_attr.h +++ b/fs/xfs/libxfs/xfs_attr.h @@ -456,7 +456,7 @@ enum xfs_delattr_state { XFS_DAS_LEAF_ALLOC_RMT, /* We are allocating remote blocks */ XFS_DAS_LEAF_REPLACE, /* Perform replace ops on a leaf */ XFS_DAS_LEAF_REMOVE_OLD, /* Start removing old attr from leaf */ - XFS_DAS_RM_LBLK, /* A rename is removing leaf blocks */ + XFS_DAS_LEAF_REMOVE_RMT, /* A rename is removing remote blocks */ XFS_DAS_RD_LEAF, /* Read in the new leaf */ /* Node state set sequence, must match leaf state above */ @@ -464,7 +464,7 @@ enum xfs_delattr_state { XFS_DAS_NODE_ALLOC_RMT, /* We are allocating remote blocks */ XFS_DAS_NODE_REPLACE, /* Perform replace ops on a node */ XFS_DAS_NODE_REMOVE_OLD, /* Start removing old attr from node */ - XFS_DAS_RM_NBLK, /* A rename is removing node blocks */ + XFS_DAS_NODE_REMOVE_RMT, /* A rename is removing remote blocks */ XFS_DAS_CLR_FLAG, /* Clear incomplete flag */ XFS_DAS_DONE, /* finished operation */ @@ -482,13 +482,13 @@ enum xfs_delattr_state { { XFS_DAS_LEAF_ALLOC_RMT, "XFS_DAS_LEAF_ALLOC_RMT" }, \ { XFS_DAS_LEAF_REPLACE, "XFS_DAS_LEAF_REPLACE" }, \ { XFS_DAS_LEAF_REMOVE_OLD, "XFS_DAS_LEAF_REMOVE_OLD" }, \ - { XFS_DAS_RM_LBLK, "XFS_DAS_RM_LBLK" }, \ + { XFS_DAS_LEAF_REMOVE_RMT, "XFS_DAS_LEAF_REMOVE_RMT" }, \ { XFS_DAS_RD_LEAF, "XFS_DAS_RD_LEAF" }, \ { XFS_DAS_NODE_SET_RMT, "XFS_DAS_NODE_SET_RMT" }, \ { XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" }, \ { XFS_DAS_NODE_REPLACE, "XFS_DAS_NODE_REPLACE" }, \ { XFS_DAS_NODE_REMOVE_OLD, "XFS_DAS_NODE_REMOVE_OLD" }, \ - { XFS_DAS_RM_NBLK, "XFS_DAS_RM_NBLK" }, \ + { XFS_DAS_NODE_REMOVE_RMT, "XFS_DAS_NODE_REMOVE_RMT" }, \ { XFS_DAS_CLR_FLAG, "XFS_DAS_CLR_FLAG" }, \ { XFS_DAS_DONE, "XFS_DAS_DONE" } |