All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Chinner <david@fromorbit.com>
To: Allison Henderson <allison.henderson@oracle.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH v1 11/17] xfs: add parent attributes to link
Date: Fri, 17 Jun 2022 08:39:23 +1000	[thread overview]
Message-ID: <20220616223923.GG227878@dread.disaster.area> (raw)
In-Reply-To: <20220611094200.129502-12-allison.henderson@oracle.com>

On Sat, Jun 11, 2022 at 02:41:54AM -0700, Allison Henderson wrote:
> This patch modifies xfs_link to add a parent pointer to the inode.
> 
> [bfoster: rebase, use VFS inode fields, fix xfs_bmap_finish() usage]
> [achender: rebased, changed __unint32_t to xfs_dir2_dataptr_t,
>            fixed null pointer bugs]
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
> ---
>  fs/xfs/xfs_inode.c | 78 ++++++++++++++++++++++++++++++++++++----------
>  fs/xfs/xfs_trans.c |  7 +++--
>  fs/xfs/xfs_trans.h |  2 +-
>  3 files changed, 67 insertions(+), 20 deletions(-)
> 
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 6b1e4cb11b5c..41c58df8e568 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -1254,14 +1254,28 @@ xfs_create_tmpfile(
>  
>  int
>  xfs_link(
> -	xfs_inode_t		*tdp,
> -	xfs_inode_t		*sip,
> -	struct xfs_name		*target_name)
> -{
> -	xfs_mount_t		*mp = tdp->i_mount;
> -	xfs_trans_t		*tp;
> -	int			error, nospace_error = 0;
> -	int			resblks;
> +	xfs_inode_t			*tdp,
> +	xfs_inode_t			*sip,
> +	struct xfs_name			*target_name)
> +{
> +	xfs_mount_t			*mp = tdp->i_mount;
> +	xfs_trans_t			*tp;
> +	int				error, nospace_error = 0;
> +	int				resblks;
> +	struct xfs_parent_name_rec	rec;
> +	xfs_dir2_dataptr_t		diroffset;
> +
> +	struct xfs_da_args		args = {
> +		.dp		= sip,
> +		.geo		= mp->m_attr_geo,
> +		.whichfork	= XFS_ATTR_FORK,
> +		.attr_filter	= XFS_ATTR_PARENT,
> +		.op_flags	= XFS_DA_OP_OKNOENT,
> +		.name		= (const uint8_t *)&rec,
> +		.namelen	= sizeof(rec),
> +		.value		= (void *)target_name->name,
> +		.valuelen	= target_name->len,
> +	};

Now that I've had a bit of a think about this, this pattern of
placing the rec on the stack and then using it as a buffer that is
then accessed in xfs_tran_commit() processing feels like a landmine.

That is, we pass transaction contexts around functions as they are
largely independent constructs, but adding this stack variable to
the defer ops attached to the transaction means that the transaction
cannot be passed back to a caller for it to be committed - that will
corrupt the stack buffer and hence silently corrupt the parent attr
that is going to be logged when the transaction is finally committed.

Hence I think this needs to be wrapped up as a dynamically allocated
structure that is freed when the defer ops are done with it. e.g.

struct xfs_parent_defer {
	struct xfs_parent_name_rec	rec;
	xfs_dir2_dataptr_t		diroffset;
	struct xfs_da_args		args;
};

and then here:

>  
>  	trace_xfs_link(tdp, target_name);
>  
> @@ -1278,11 +1292,17 @@ xfs_link(
>  	if (error)
>  		goto std_return;
>  
> +	if (xfs_has_larp(mp)) {
> +		error = xfs_attr_grab_log_assist(mp);
> +		if (error)
> +			goto std_return;
> +	}

	struct xfs_parent_defer		*parent = NULL;
.....

	error = xfs_parent_init(mp, target_name, &parent);
	if (error)
		goto std_return;

and xfs_parent_init() looks something like this:

int
xfs_parent_init(
	.....
	struct xfs_parent_defer		**parentp)
{
	struct xfs_parent_defer		*parent;

	if (!xfs_has_parent_pointers(mp))
		return 0;

	error = xfs_attr_grab_log_assist(mp);
	if (error)
		return error;

	parent = kzalloc(sizeof(*parent), GFP_KERNEL);
	if (!parent)
		return -ENOMEM;

	/* init parent da_args */

	*parentp = parent;
	return 0;
}

With that in place, we then can wrap all this up:

>  
> +	/*
> +	 * If we have parent pointers, we now need to add the parent record to
> +	 * the attribute fork of the inode. If this is the initial parent
> +	 * attribute, we need to create it correctly, otherwise we can just add
> +	 * the parent to the inode.
> +	 */
> +	if (xfs_sb_version_hasparent(&mp->m_sb)) {
> +		args.trans = tp;
> +		xfs_init_parent_name_rec(&rec, tdp, diroffset);
> +		args.hashval = xfs_da_hashname(args.name,
> +					       args.namelen);
> +		error = xfs_attr_defer_add(&args);
> +		if (error)
> +			goto out_defer_cancel;
> +	}

with:

	if (parent) {
		error = xfs_parent_defer_add(tp, tdp, parent, diroffset);
		if (error)
			goto out_defer_cancel;
	}

and implement it something like:

int
xfs_parent_defer_add(
	struct xfs_trans	*tp,
	struct xfs_inode	*ip,
	struct xfs_parent_defer	*parent,
	xfs_dir2_dataptr_t	diroffset)
{
	struct xfs_da_args	*args = &parent->args;

	xfs_init_parent_name_rec(&parent->rec, ip, diroffset)
	args->trans = tp;
	args->hashval = xfs_da_hashname(args->name, args->namelen);
	return xfs_attr_defer_add(args);
}


> +
>  	/*
>  	 * If this is a synchronous mount, make sure that the
>  	 * link transaction goes to disk before returning to
> @@ -1331,11 +1367,21 @@ xfs_link(
>  	if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
>  		xfs_trans_set_sync(tp);
>  
> -	return xfs_trans_commit(tp);
> +	error = xfs_trans_commit(tp);
> +	xfs_iunlock(tdp, XFS_ILOCK_EXCL);
> +	xfs_iunlock(sip, XFS_ILOCK_EXCL);

with a xfs_parent_free(parent) added here now that we are done with
the parent update.

> +	return error;
>  
> - error_return:
> +out_defer_cancel:
> +	xfs_defer_cancel(tp);
> +error_return:
>  	xfs_trans_cancel(tp);
> - std_return:
> +	xfs_iunlock(tdp, XFS_ILOCK_EXCL);
> +	xfs_iunlock(sip, XFS_ILOCK_EXCL);
> +drop_incompat:
> +	if (xfs_has_larp(mp))
> +		xlog_drop_incompat_feat(mp->m_log);

And this can be replace with  xfs_parent_cancel(mp, parent); that
drops the log incompat featuer and frees the parent if it is not
null.

> +std_return:
>  	if (error == -ENOSPC && nospace_error)
>  		error = nospace_error;
>  	return error;
> @@ -2819,7 +2865,7 @@ xfs_remove(
>  	 */
>  	resblks = XFS_REMOVE_SPACE_RES(mp);
>  	error = xfs_trans_alloc_dir(dp, &M_RES(mp)->tr_remove, ip, &resblks,
> -			&tp, &dontcare);
> +			&tp, &dontcare, XFS_ILOCK_EXCL);

So you add this flag here so that link and remove can do different
things in xfs_trans_alloc_dir(), but in the very next patch
this gets changed to zero, so both callers only pass 0 to the
function.

Ideally there should be a patch prior to this one that converts
the locking and joining of both link and remove to use external
inode locking in a single patch, similar to the change in the second
patch that changed the inode locking around xfs_init_new_inode() to
require manual unlock. Then all the locking mods in this and the
next patch go away, leaving just the parent pointer mods in this
patch....

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

  reply	other threads:[~2022-06-16 22:39 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-11  9:41 [PATCH v1 00/17] Return of the Parent Pointers Allison Henderson
2022-06-11  9:41 ` [PATCH v1 01/17] xfs: Add larp state XFS_DAS_CREATE_FORK Allison Henderson
2022-06-15  1:09   ` Dave Chinner
2022-06-15 23:40     ` Alli
2022-06-16  2:08       ` Dave Chinner
2022-06-16  5:32         ` Dave Chinner
2022-06-29  6:33           ` Alli
2022-06-30  0:40             ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 02/17] xfs: Hold inode locks in xfs_ialloc Allison Henderson
2022-06-29 18:28   ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 03/17] xfs: get directory offset when adding directory name Allison Henderson
2022-06-29 18:29   ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 04/17] xfs: get directory offset when removing " Allison Henderson
2022-06-29 18:30   ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 05/17] xfs: get directory offset when replacing a " Allison Henderson
2022-06-29 18:30   ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 06/17] xfs: add parent pointer support to attribute code Allison Henderson
2022-06-29 18:33   ` Darrick J. Wong
2022-06-29 18:58     ` Alli
2022-06-11  9:41 ` [PATCH v1 07/17] xfs: define parent pointer xattr format Allison Henderson
2022-06-29 18:34   ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 08/17] xfs: Add xfs_verify_pptr Allison Henderson
2022-06-29 18:35   ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 09/17] xfs: extent transaction reservations for parent attributes Allison Henderson
2022-06-16  5:38   ` Dave Chinner
2022-06-18  0:31     ` Alli
2022-06-29 18:37   ` Darrick J. Wong
2022-06-29 19:23     ` Alli
2022-06-11  9:41 ` [PATCH v1 10/17] xfs: parent pointer attribute creation Allison Henderson
2022-06-11 15:10   ` kernel test robot
2022-06-16  5:49   ` Dave Chinner
2022-06-18  0:32     ` Alli
2022-06-29 18:41   ` Darrick J. Wong
2022-06-30  1:29     ` Alli
2022-06-11  9:41 ` [PATCH v1 11/17] xfs: add parent attributes to link Allison Henderson
2022-06-16 22:39   ` Dave Chinner [this message]
2022-06-18  0:32     ` Alli
2022-06-29 18:09       ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 12/17] xfs: remove parent pointers in unlink Allison Henderson
2022-06-29 17:35   ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 13/17] xfs: Add parent pointers to rename Allison Henderson
2022-06-29 18:02   ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 14/17] xfs: Add the parent pointer support to the superblock version 5 Allison Henderson
2022-06-16  6:03   ` Dave Chinner
2022-06-18  0:32     ` Alli
2022-06-20  0:21       ` Dave Chinner
2022-06-29 18:16         ` Darrick J. Wong
2022-06-11  9:41 ` [PATCH v1 15/17] xfs: Add helper function xfs_attr_list_context_init Allison Henderson
2022-06-29 18:42   ` Darrick J. Wong
2022-06-30  1:30     ` Alli
2022-06-11  9:41 ` [PATCH v1 16/17] xfs: Increase XFS_DEFER_OPS_NR_INODES to 4 Allison Henderson
2022-06-16 21:54   ` Dave Chinner
2022-06-18  0:32     ` Alli
2022-06-29 18:43       ` Darrick J. Wong
2022-06-30  1:30         ` Alli
2022-06-11  9:42 ` [PATCH v1 17/17] xfs: Add parent pointer ioctl Allison Henderson
2022-06-29 18:52   ` Darrick J. Wong
2022-06-30  1:30     ` Alli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220616223923.GG227878@dread.disaster.area \
    --to=david@fromorbit.com \
    --cc=allison.henderson@oracle.com \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.