Re: [PATCH 16/18 v2] xfs: use XFS_DA_OP flags in deferred attr ops

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 11, 2022 at 08:20:15AM +1000, Dave Chinner wrote:
> From: Dave Chinner <dchinner@xxxxxxxxxx>
> 
> We currently store the high level attr operation in
> args->attr_flags. This falgs are what the VFS is telling us to do,

"This flag contains what the VFS is telling us to do..."

> but don't necessarily match what we are doing in the low level
> modification state machine. e.g. XATTR_REPLACE implies both
> XFS_DA_OP_ADDNAME and XFS_DA_OP_RENAME because it is doing both a
> remove and adding a new attr.
> 
> However, deep in the individual state machine operations, we check
> errors against this high level VFS op flags, not the low level
> XFS_DA_OP flags. Indeed, we don't even have a low level flag for
> a REMOVE operation, so the only way we know we are doing a remove
> is the complete absence of XATTR_REPLACE, XATTR_CREATE,
> XFS_DA_OP_ADDNAME and XFS_DA_OP_RENAME. And because there are other
> flags in these fields, this is a pain to check if we need to.
> 
> As the XFS_DA_OP flags are only needed once the deferred operations
> are set up, set these flags appropriately when we set the initial
> operation state. We also introduce a XFS_DA_OP_REMOVE flag to make
> it easy to know that we are doing a remove operation.

Oh goody!

> With these, we can remove the use of XATTR_REPLACE and XATTR_CREATE
> in low level lookup operations, and manipulate the low level flags
> according to the low level context that is operating. e.g. log
> recovery does not have a VFS xattr operation state to copy into
> args->attr_flags, and the low level state machine ops we do for
> recovery do not match the high level VFS operations that were in
> progress when the system failed...
> 
> Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
> ---
> Version 2 (now that vger has finally got this to me after 2 days):
> - fixed bug by that removed clearing remote block values after save
>   for node format blocks. Clearing is now done by
>   xfs_attr_save_rmt_blk() for both callers.
> 

With the minor sentence nit above fixed,
Reviewed-by: Darrick J. Wong <djwong@xxxxxxxxxx>

--D

>  fs/xfs/libxfs/xfs_attr.c      | 136 +++++++++++++++++++++++-------------------
>  fs/xfs/libxfs/xfs_attr.h      |   3 +
>  fs/xfs/libxfs/xfs_attr_leaf.c |   2 +-
>  fs/xfs/libxfs/xfs_da_btree.h  |   8 ++-
>  4 files changed, 83 insertions(+), 66 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index 8be76f8d11c5..a36364b27aa1 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -467,7 +467,7 @@ xfs_attr_leaf_addname(
>  	 */
>  	if (args->rmtblkno)
>  		attr->xattri_dela_state = XFS_DAS_LEAF_SET_RMT;
> -	else if (args->op_flags & XFS_DA_OP_RENAME)
> +	else if (args->op_flags & XFS_DA_OP_REPLACE)
>  		xfs_attr_dela_state_set_replace(attr, XFS_DAS_LEAF_REPLACE);
>  	else
>  		attr->xattri_dela_state = XFS_DAS_DONE;
> @@ -512,7 +512,7 @@ xfs_attr_node_addname(
>  
>  	if (args->rmtblkno)
>  		attr->xattri_dela_state = XFS_DAS_NODE_SET_RMT;
> -	else if (args->op_flags & XFS_DA_OP_RENAME)
> +	else if (args->op_flags & XFS_DA_OP_REPLACE)
>  		xfs_attr_dela_state_set_replace(attr, XFS_DAS_NODE_REPLACE);
>  	else
>  		attr->xattri_dela_state = XFS_DAS_DONE;
> @@ -548,7 +548,7 @@ xfs_attr_rmtval_alloc(
>  		return error;
>  
>  	/* If this is not a rename, clear the incomplete flag and we're done. */
> -	if (!(args->op_flags & XFS_DA_OP_RENAME)) {
> +	if (!(args->op_flags & XFS_DA_OP_REPLACE)) {
>  		error = xfs_attr3_leaf_clearflag(args);
>  		attr->xattri_dela_state = XFS_DAS_DONE;
>  	} else {
> @@ -967,8 +967,6 @@ xfs_attr_set(
>  
>  	if (args->value) {
>  		XFS_STATS_INC(mp, xs_attr_set);
> -
> -		args->op_flags |= XFS_DA_OP_ADDNAME;
>  		args->total = xfs_attr_calc_size(args, &local);
>  
>  		/*
> @@ -1126,28 +1124,41 @@ static inline int xfs_attr_sf_totsize(struct xfs_inode *dp)
>   * Add a name to the shortform attribute list structure
>   * This is the external routine.
>   */
> -STATIC int
> -xfs_attr_shortform_addname(xfs_da_args_t *args)
> +static int
> +xfs_attr_shortform_addname(
> +	struct xfs_da_args	*args)
>  {
> -	int newsize, forkoff, retval;
> +	int			newsize, forkoff;
> +	int			error;
>  
>  	trace_xfs_attr_sf_addname(args);
>  
> -	retval = xfs_attr_shortform_lookup(args);
> -	if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
> -		return retval;
> -	if (retval == -EEXIST) {
> -		if (args->attr_flags & XATTR_CREATE)
> -			return retval;
> -		retval = xfs_attr_sf_removename(args);
> -		if (retval)
> -			return retval;
> +	error = xfs_attr_shortform_lookup(args);
> +	switch (error) {
> +	case -ENOATTR:
> +		if (args->op_flags & XFS_DA_OP_REPLACE)
> +			return error;
> +		break;
> +	case -EEXIST:
> +		if (!(args->op_flags & XFS_DA_OP_REPLACE))
> +			return error;
> +
> +		error = xfs_attr_sf_removename(args);
> +		if (error)
> +			return error;
> +
>  		/*
> -		 * Since we have removed the old attr, clear ATTR_REPLACE so
> -		 * that the leaf format add routine won't trip over the attr
> -		 * not being around.
> +		 * Since we have removed the old attr, clear XFS_DA_OP_REPLACE
> +		 * so that the new attr doesn't fit in shortform format, the
> +		 * leaf format add routine won't trip over the attr not being
> +		 * around.
>  		 */
> -		args->attr_flags &= ~XATTR_REPLACE;
> +		args->op_flags &= ~XFS_DA_OP_REPLACE;
> +		break;
> +	case 0:
> +		break;
> +	default:
> +		return error;
>  	}
>  
>  	if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
> @@ -1170,8 +1181,8 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
>   * External routines when attribute list is one block
>   *========================================================================*/
>  
> -/* Store info about a remote block */
> -STATIC void
> +/* Save the current remote block info and clear the current pointers. */
> +static void
>  xfs_attr_save_rmt_blk(
>  	struct xfs_da_args	*args)
>  {
> @@ -1180,10 +1191,13 @@ xfs_attr_save_rmt_blk(
>  	args->rmtblkno2 = args->rmtblkno;
>  	args->rmtblkcnt2 = args->rmtblkcnt;
>  	args->rmtvaluelen2 = args->rmtvaluelen;
> +	args->rmtblkno = 0;
> +	args->rmtblkcnt = 0;
> +	args->rmtvaluelen = 0;
>  }
>  
>  /* Set stored info about a remote block */
> -STATIC void
> +static void
>  xfs_attr_restore_rmt_blk(
>  	struct xfs_da_args	*args)
>  {
> @@ -1229,28 +1243,27 @@ xfs_attr_leaf_try_add(
>  	 * Look up the xattr name to set the insertion point for the new xattr.
>  	 */
>  	error = xfs_attr3_leaf_lookup_int(bp, args);
> -	if (error != -ENOATTR && error != -EEXIST)
> -		goto out_brelse;
> -	if (error == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
> -		goto out_brelse;
> -	if (error == -EEXIST) {
> -		if (args->attr_flags & XATTR_CREATE)
> +	switch (error) {
> +	case -ENOATTR:
> +		if (args->op_flags & XFS_DA_OP_REPLACE)
> +			goto out_brelse;
> +		break;
> +	case -EEXIST:
> +		if (!(args->op_flags & XFS_DA_OP_REPLACE))
>  			goto out_brelse;
>  
>  		trace_xfs_attr_leaf_replace(args);
> -
> -		/* save the attribute state for later removal*/
> -		args->op_flags |= XFS_DA_OP_RENAME;	/* an atomic rename */
> -		xfs_attr_save_rmt_blk(args);
> -
>  		/*
> -		 * clear the remote attr state now that it is saved so that the
> -		 * values reflect the state of the attribute we are about to
> +		 * Save the existing remote attr state so that the current
> +		 * values reflect the state of the new attribute we are about to
>  		 * add, not the attribute we just found and will remove later.
>  		 */
> -		args->rmtblkno = 0;
> -		args->rmtblkcnt = 0;
> -		args->rmtvaluelen = 0;
> +		xfs_attr_save_rmt_blk(args);
> +		break;
> +	case 0:
> +		break;
> +	default:
> +		goto out_brelse;
>  	}
>  
>  	return xfs_attr3_leaf_add(bp, args);
> @@ -1389,46 +1402,45 @@ xfs_attr_node_hasname(
>  
>  STATIC int
>  xfs_attr_node_addname_find_attr(
> -	 struct xfs_attr_item		*attr)
> +	 struct xfs_attr_item	*attr)
>  {
> -	struct xfs_da_args		*args = attr->xattri_da_args;
> -	int				retval;
> +	struct xfs_da_args	*args = attr->xattri_da_args;
> +	int			error;
>  
>  	/*
>  	 * Search to see if name already exists, and get back a pointer
>  	 * to where it should go.
>  	 */
> -	retval = xfs_attr_node_hasname(args, &attr->xattri_da_state);
> -	if (retval != -ENOATTR && retval != -EEXIST)
> -		goto error;
> -
> -	if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
> -		goto error;
> -	if (retval == -EEXIST) {
> -		if (args->attr_flags & XATTR_CREATE)
> +	error = xfs_attr_node_hasname(args, &attr->xattri_da_state);
> +	switch (error) {
> +	case -ENOATTR:
> +		if (args->op_flags & XFS_DA_OP_REPLACE)
> +			goto error;
> +		break;
> +	case -EEXIST:
> +		if (!(args->op_flags & XFS_DA_OP_REPLACE))
>  			goto error;
>  
> -		trace_xfs_attr_node_replace(args);
> -
> -		/* save the attribute state for later removal*/
> -		args->op_flags |= XFS_DA_OP_RENAME;	/* atomic rename op */
> -		xfs_attr_save_rmt_blk(args);
>  
> +		trace_xfs_attr_node_replace(args);
>  		/*
> -		 * clear the remote attr state now that it is saved so that the
> -		 * values reflect the state of the attribute we are about to
> +		 * Save the existing remote attr state so that the current
> +		 * values reflect the state of the new attribute we are about to
>  		 * add, not the attribute we just found and will remove later.
>  		 */
> -		args->rmtblkno = 0;
> -		args->rmtblkcnt = 0;
> -		args->rmtvaluelen = 0;
> +		xfs_attr_save_rmt_blk(args);
> +		break;
> +	case 0:
> +		break;
> +	default:
> +		goto error;
>  	}
>  
>  	return 0;
>  error:
>  	if (attr->xattri_da_state)
>  		xfs_da_state_free(attr->xattri_da_state);
> -	return retval;
> +	return error;
>  }
>  
>  /*
> diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
> index 6bef522533a4..e93efc8b11cd 100644
> --- a/fs/xfs/libxfs/xfs_attr.h
> +++ b/fs/xfs/libxfs/xfs_attr.h
> @@ -584,6 +584,7 @@ xfs_attr_is_shortform(
>  static inline enum xfs_delattr_state
>  xfs_attr_init_add_state(struct xfs_da_args *args)
>  {
> +	args->op_flags |= XFS_DA_OP_ADDNAME;
>  	if (!args->dp->i_afp)
>  		return XFS_DAS_DONE;
>  	if (xfs_attr_is_shortform(args->dp))
> @@ -596,6 +597,7 @@ xfs_attr_init_add_state(struct xfs_da_args *args)
>  static inline enum xfs_delattr_state
>  xfs_attr_init_remove_state(struct xfs_da_args *args)
>  {
> +	args->op_flags |= XFS_DA_OP_REMOVE;
>  	if (xfs_attr_is_shortform(args->dp))
>  		return XFS_DAS_SF_REMOVE;
>  	if (xfs_attr_is_leaf(args->dp))
> @@ -606,6 +608,7 @@ xfs_attr_init_remove_state(struct xfs_da_args *args)
>  static inline enum xfs_delattr_state
>  xfs_attr_init_replace_state(struct xfs_da_args *args)
>  {
> +	args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE;
>  	return xfs_attr_init_add_state(args);
>  }
>  
> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
> index e90bfd9d7551..53d02ce9ed78 100644
> --- a/fs/xfs/libxfs/xfs_attr_leaf.c
> +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
> @@ -1492,7 +1492,7 @@ xfs_attr3_leaf_add_work(
>  	entry->flags = args->attr_filter;
>  	if (tmp)
>  		entry->flags |= XFS_ATTR_LOCAL;
> -	if (args->op_flags & XFS_DA_OP_RENAME) {
> +	if (args->op_flags & XFS_DA_OP_REPLACE) {
>  		if (!xfs_has_larp(mp))
>  			entry->flags |= XFS_ATTR_INCOMPLETE;
>  		if ((args->blkno2 == args->blkno) &&
> diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h
> index deb368d041e3..468ca70cd35d 100644
> --- a/fs/xfs/libxfs/xfs_da_btree.h
> +++ b/fs/xfs/libxfs/xfs_da_btree.h
> @@ -85,19 +85,21 @@ typedef struct xfs_da_args {
>   * Operation flags:
>   */
>  #define XFS_DA_OP_JUSTCHECK	(1u << 0) /* check for ok with no space */
> -#define XFS_DA_OP_RENAME	(1u << 1) /* this is an atomic rename op */
> +#define XFS_DA_OP_REPLACE	(1u << 1) /* this is an atomic replace op */
>  #define XFS_DA_OP_ADDNAME	(1u << 2) /* this is an add operation */
>  #define XFS_DA_OP_OKNOENT	(1u << 3) /* lookup op, ENOENT ok, else die */
>  #define XFS_DA_OP_CILOOKUP	(1u << 4) /* lookup returns CI name if found */
>  #define XFS_DA_OP_NOTIME	(1u << 5) /* don't update inode timestamps */
> +#define XFS_DA_OP_REMOVE	(1u << 6) /* this is a remove operation */
>  
>  #define XFS_DA_OP_FLAGS \
>  	{ XFS_DA_OP_JUSTCHECK,	"JUSTCHECK" }, \
> -	{ XFS_DA_OP_RENAME,	"RENAME" }, \
> +	{ XFS_DA_OP_REPLACE,	"REPLACE" }, \
>  	{ XFS_DA_OP_ADDNAME,	"ADDNAME" }, \
>  	{ XFS_DA_OP_OKNOENT,	"OKNOENT" }, \
>  	{ XFS_DA_OP_CILOOKUP,	"CILOOKUP" }, \
> -	{ XFS_DA_OP_NOTIME,	"NOTIME" }
> +	{ XFS_DA_OP_NOTIME,	"NOTIME" }, \
> +	{ XFS_DA_OP_REMOVE,	"REMOVE" }
>  
>  /*
>   * Storage for holding state during Btree searches and split/join ops.
> Dave Chinner
> david@xxxxxxxxxxxxx



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux