Commit db1a28cc authored by Allison Collins's avatar Allison Collins Committed by Darrick J. Wong
Browse files

xfs: Add helpers xfs_attr_is_shortform and xfs_attr_set_shortform



In this patch, we hoist code from xfs_attr_set_args into two new helpers
xfs_attr_is_shortform and xfs_attr_set_shortform.  These two will help
to simplify xfs_attr_set_args when we get into delayed attrs later.

Signed-off-by: default avatarAllison Collins <allison.henderson@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarChandan Rajendra <chandanrlinux@gmail.com>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Acked-by: default avatarDave Chinner <dchinner@redhat.com>
parent a237f2dd
Loading
Loading
Loading
Loading
+72 −35
Original line number Diff line number Diff line
@@ -204,23 +204,30 @@ xfs_attr_try_sf_addname(
}

/*
 * Set the attribute specified in @args.
 * Check to see if the attr should be upgraded from non-existent or shortform to
 * single-leaf-block attribute list.
 */
int
xfs_attr_set_args(
	struct xfs_da_args	*args)
static inline bool
xfs_attr_is_shortform(
	struct xfs_inode    *ip)
{
	struct xfs_inode	*dp = args->dp;
	struct xfs_buf          *leaf_bp = NULL;
	int			error, error2 = 0;
	return ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL ||
	       (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
		ip->i_afp->if_nextents == 0);
}

/*
	 * If the attribute list is non-existent or a shortform list,
	 * upgrade it to a single-leaf-block attribute list.
 * Attempts to set an attr in shortform, or converts short form to leaf form if
 * there is not enough room.  If the attr is set, the transaction is committed
 * and set to NULL.
 */
	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL ||
	    (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
	     dp->i_afp->if_nextents == 0)) {
STATIC int
xfs_attr_set_shortform(
	struct xfs_da_args	*args,
	struct xfs_buf		**leaf_bp)
{
	struct xfs_inode	*dp = args->dp;
	int			error, error2 = 0;

	/*
	 * Try to add the attr to the attribute list in the inode.
@@ -231,29 +238,59 @@ xfs_attr_set_args(
		args->trans = NULL;
		return error ? error : error2;
	}

	/*
		 * It won't fit in the shortform, transform to a leaf block.
		 * GROT: another possible req'mt for a double-split btree op.
	 * It won't fit in the shortform, transform to a leaf block.  GROT:
	 * another possible req'mt for a double-split btree op.
	 */
		error = xfs_attr_shortform_to_leaf(args, &leaf_bp);
	error = xfs_attr_shortform_to_leaf(args, leaf_bp);
	if (error)
		return error;

	/*
		 * Prevent the leaf buffer from being unlocked so that a
		 * concurrent AIL push cannot grab the half-baked leaf
		 * buffer and run into problems with the write verifier.
		 * Once we're done rolling the transaction we can release
		 * the hold and add the attr to the leaf.
	 * Prevent the leaf buffer from being unlocked so that a concurrent AIL
	 * push cannot grab the half-baked leaf buffer and run into problems
	 * with the write verifier. Once we're done rolling the transaction we
	 * can release the hold and add the attr to the leaf.
	 */
		xfs_trans_bhold(args->trans, leaf_bp);
	xfs_trans_bhold(args->trans, *leaf_bp);
	error = xfs_defer_finish(&args->trans);
		xfs_trans_bhold_release(args->trans, leaf_bp);
	xfs_trans_bhold_release(args->trans, *leaf_bp);
	if (error) {
			xfs_trans_brelse(args->trans, leaf_bp);
		xfs_trans_brelse(args->trans, *leaf_bp);
		return error;
	}

	return 0;
}

/*
 * Set the attribute specified in @args.
 */
int
xfs_attr_set_args(
	struct xfs_da_args	*args)
{
	struct xfs_inode	*dp = args->dp;
	struct xfs_buf          *leaf_bp = NULL;
	int			error = 0;

	/*
	 * If the attribute list is already in leaf format, jump straight to
	 * leaf handling.  Otherwise, try to add the attribute to the shortform
	 * list; if there's no room then convert the list to leaf format and try
	 * again.
	 */
	if (xfs_attr_is_shortform(dp)) {

		/*
		 * If the attr was successfully set in shortform, the
		 * transaction is committed and set to NULL.  Otherwise, is it
		 * converted from shortform to leaf, and the transaction is
		 * retained.
		 */
		error = xfs_attr_set_shortform(args, &leaf_bp);
		if (error || !args->trans)
			return error;
	}

	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {