public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Dave Chinner <david@fromorbit.com>
To: Brian Foster <bfoster@redhat.com>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH 03/20] xfs: sanitise error handling in xfs_alloc_fix_freelist
Date: Tue, 16 Jun 2015 07:51:19 +1000	[thread overview]
Message-ID: <20150615215119.GC10224@dastard> (raw)
In-Reply-To: <20150615145814.GC36091@bfoster.bfoster>

On Mon, Jun 15, 2015 at 10:58:14AM -0400, Brian Foster wrote:
> On Wed, Jun 03, 2015 at 04:04:40PM +1000, Dave Chinner wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> > 
> > The error handling is currently an inconsistent mess as every error
> > condition handles return values and releasing buffers individually.
> > Clean this up by using gotos and a sane error label stack.
> > 
> > Signed-off-by: Dave Chinner <dchinner@redhat.com>
> > ---
> >  fs/xfs/libxfs/xfs_alloc.c | 103 +++++++++++++++++++++-------------------------
> >  1 file changed, 47 insertions(+), 56 deletions(-)
> > 
> > diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
> > index 2471cb5..352db46 100644
> > --- a/fs/xfs/libxfs/xfs_alloc.c
> > +++ b/fs/xfs/libxfs/xfs_alloc.c
> > @@ -1909,80 +1909,65 @@ xfs_alloc_space_available(
> >   */
> >  STATIC int			/* error */
> >  xfs_alloc_fix_freelist(
> > -	xfs_alloc_arg_t	*args,	/* allocation argument structure */
> > -	int		flags)	/* XFS_ALLOC_FLAG_... */
> > +	struct xfs_alloc_arg	*args,	/* allocation argument structure */
> > +	int			flags)	/* XFS_ALLOC_FLAG_... */
> >  {
> > -	xfs_buf_t	*agbp;	/* agf buffer pointer */
> > -	xfs_buf_t	*agflbp;/* agfl buffer pointer */
> > -	xfs_agblock_t	bno;	/* freelist block */
> > -	int		error;	/* error result code */
> > -	xfs_mount_t	*mp;	/* file system mount point structure */
> > -	xfs_extlen_t	need;	/* total blocks needed in freelist */
> > -	xfs_perag_t	*pag;	/* per-ag information structure */
> > -	xfs_alloc_arg_t	targs;	/* local allocation arguments */
> > -	xfs_trans_t	*tp;	/* transaction pointer */
> > -
> > -	mp = args->mp;
> > +	struct xfs_mount	*mp = args->mp;
> > +	struct xfs_perag	*pag = args->pag;
> > +	struct xfs_trans	*tp = args->tp;
> > +	struct xfs_buf		*agbp = NULL;
> > +	struct xfs_buf		*agflbp = NULL;
> > +	struct xfs_alloc_arg	targs;	/* local allocation arguments */
> > +	xfs_agblock_t		bno;	/* freelist block */
> > +	xfs_extlen_t		need;	/* total blocks needed in freelist */
> > +	int			error;
> >  
> > -	pag = args->pag;
> > -	tp = args->tp;
> >  	if (!pag->pagf_init) {
> > -		if ((error = xfs_alloc_read_agf(mp, tp, args->agno, flags,
> > -				&agbp)))
> > -			return error;
> > +		error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp);
> > +		if (error)
> > +			goto out_no_agbp;
> >  		if (!pag->pagf_init) {
> >  			ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
> >  			ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
> > -			args->agbp = NULL;
> > -			return 0;
> > +			goto out_agbp_relse;
> >  		}
> > -	} else
> > -		agbp = NULL;
> > +	}
> >  
> >  	/*
> > -	 * If this is a metadata preferred pag and we are user data
> > -	 * then try somewhere else if we are not being asked to
> > -	 * try harder at this point
> > +	 * If this is a metadata preferred pag and we are user data then try
> > +	 * somewhere else if we are not being asked to try harder at this
> > +	 * point
> >  	 */
> >  	if (pag->pagf_metadata && args->userdata &&
> >  	    (flags & XFS_ALLOC_FLAG_TRYLOCK)) {
> >  		ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
> > -		args->agbp = NULL;
> > -		return 0;
> > +		goto out_agbp_relse;
> >  	}
> >  
> >  	need = XFS_MIN_FREELIST_PAG(pag, mp);
> > -	if (!xfs_alloc_space_available(args, need, flags)) {
> > -		if (agbp)
> > -			xfs_trans_brelse(tp, agbp);
> > -		args->agbp = NULL;
> > -		return 0;
> > -	}
> > +	if (!xfs_alloc_space_available(args, need, flags))
> > +		goto out_agbp_relse;
> >  
> >  	/*
> >  	 * Get the a.g. freespace buffer.
> >  	 * Can fail if we're not blocking on locks, and it's held.
> >  	 */
> > -	if (agbp == NULL) {
> > -		if ((error = xfs_alloc_read_agf(mp, tp, args->agno, flags,
> > -				&agbp)))
> > -			return error;
> > -		if (agbp == NULL) {
> > +	if (!agbp) {
> > +		error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp);
> > +		if (error)
> > +			goto out_no_agbp;
> > +		if (!agbp) {
> >  			ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
> >  			ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
> > -			args->agbp = NULL;
> > -			return 0;
> > +			goto out_no_agbp;
> >  		}
> >  	}
> >  
> >  
> >  	/* If there isn't enough total space or single-extent, reject it. */
> >  	need = XFS_MIN_FREELIST_PAG(pag, mp);
> > -	if (!xfs_alloc_space_available(args, need, flags)) {
> > -		xfs_trans_brelse(tp, agbp);
> > -		args->agbp = NULL;
> > -		return 0;
> > -	}
> > +	if (!xfs_alloc_space_available(args, need, flags))
> > +		goto out_agbp_relse;
> >  
> >  	/*
> >  	 * Make the freelist shorter if it's too long.
> > @@ -1997,10 +1982,10 @@ xfs_alloc_fix_freelist(
> >  
> >  		error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
> >  		if (error)
> > -			return error;
> > +			goto out_agbp_relse;
> 
> So at this point it looks like the buffer could be logged (i.e., dirty
> in the transaction). Perhaps this is the reason for the lack of agbp
> releases from this point forward in the current error handling. That
> said, we do the agflbp release unconditionally at the end of the
> function even when it might be logged. xfs_trans_brelse() appears to
> handle this case as it just skips removing the item from the tp.
> 
> This is a bit confusing and at the very least seems like an unexpected
> use of xfs_trans_brelse(). Is this intentional?

Yes, very much so. If the agf is clean, then releasing it
immediately on error in the function that grabbed the buffer is the
right thing to do. This can happen if the first call to
xfs_alloc_get_freelist() fails (which only occurs if we fail to read
the AGFL buffer).

And, as you noticed, if it is dirty it will remain held by the
transaction until it is cancelled, as happens everywhere else in the
code. So this is effectively making the current code consistent with
the usual error handling patterns...

FWIW, in looking at this, I noticed that the freelist modificaiton
loops are kind of inefficient - extending it re-reads the agfl
buffer for every call, and then we re-read the agfl buffer again
before making the free list longer if needed. I think this can be
cleaned up further and better optimised. IOWs, it can only fail on
the first read of the AGFL buffer, because if it succeeds then it
will be found in the transaction item list on subsequent reads...

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

  reply	other threads:[~2015-06-15 21:52 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-03  6:04 [RFC PATCH 00/20] xfs: reverse mapping btree support Dave Chinner
2015-06-03  6:04 ` [PATCH 01/20] xfs: xfs_alloc_fix_freelist() can use incore perag structures Dave Chinner
2015-06-15 14:57   ` Brian Foster
2015-06-03  6:04 ` [PATCH 02/20] xfs: factor out free space extent length check Dave Chinner
2015-06-15 14:58   ` Brian Foster
2015-06-03  6:04 ` [PATCH 03/20] xfs: sanitise error handling in xfs_alloc_fix_freelist Dave Chinner
2015-06-15 14:58   ` Brian Foster
2015-06-15 21:51     ` Dave Chinner [this message]
2015-06-16 11:27       ` Brian Foster
2015-06-22  0:10         ` Dave Chinner
2015-06-03  6:04 ` [PATCH 04/20] xfs: clean up XFS_MIN_FREELIST macros Dave Chinner
2015-06-15 14:58   ` Brian Foster
2015-06-03  6:04 ` [PATCH 05/20] xfs: introduce rmap btree definitions Dave Chinner
2015-06-03  6:30   ` Darrick J. Wong
2015-06-03  6:34     ` Darrick J. Wong
2015-06-03  6:04 ` [PATCH 06/20] xfs: add rmap btree stats infrastructure Dave Chinner
2015-06-03  6:04 ` [PATCH 07/20] xfs: rmap btree add more reserved blocks Dave Chinner
2015-06-03  6:04 ` [PATCH 08/20] xfs: add owner field to extent allocation and freeing Dave Chinner
2015-06-24 19:09   ` Brian Foster
2015-06-24 21:13     ` Dave Chinner
2015-06-25 13:03       ` Brian Foster
2015-06-03  6:04 ` [PATCH 09/20] xfs: introduce rmap extent operation stubs Dave Chinner
2015-06-03  6:04 ` [PATCH 10/20] xfs: define the on-disk rmap btree format Dave Chinner
2015-06-03  6:04 ` [PATCH 11/20] xfs: add rmap btree growfs support Dave Chinner
2015-06-03  6:04 ` [PATCH 12/20] xfs: rmap btree transaction reservations Dave Chinner
2015-06-03  6:04 ` [PATCH 13/20] xfs: rmap btree requires more reserved free space Dave Chinner
2015-06-25 16:41   ` Brian Foster
2015-07-10  0:37     ` Dave Chinner
2015-06-03  6:04 ` [PATCH 14/20] xfs: add rmap btree operations Dave Chinner
2015-06-03  6:04 ` [PATCH 15/20] xfs: add an extent to the rmap btree Dave Chinner
2015-06-25 16:41   ` Brian Foster
2015-07-10  0:39     ` Dave Chinner
2015-06-03  6:04 ` [PATCH 16/20] xfs: remove an extent from " Dave Chinner
2015-06-03  6:04 ` [PATCH 17/20] xfs: add rmap btree geometry feature flag Dave Chinner
2015-06-03  6:04 ` [PATCH 18/20] xfs: add rmap btree block detection to log recovery Dave Chinner
2015-06-03  6:04 ` [PATCH 19/20] xfs: disable XFS_IOC_SWAPEXT when rmap btree is enabled Dave Chinner
2015-06-03  6:04 ` [PATCH 20/20] xfs: enable the rmap btree functionality Dave Chinner

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=20150615215119.GC10224@dastard \
    --to=david@fromorbit.com \
    --cc=bfoster@redhat.com \
    --cc=xfs@oss.sgi.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox