public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: Carlos Maiolino <cmaiolino@redhat.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH] Stop searching for free slots in an inode chunk when there are none
Date: Mon, 14 Aug 2017 15:48:17 -0700	[thread overview]
Message-ID: <20170814224817.GD4796@magnolia> (raw)
In-Reply-To: <20170814105349.12391-1-cmaiolino@redhat.com>

On Mon, Aug 14, 2017 at 12:53:49PM +0200, Carlos Maiolino wrote:
> In a filesystem without finobt, the Space manager selects an AG to alloc a new
> inode, where xfs_dialloc_ag_inobt() will search the AG for the free slot chunk.
> 
> When the new inode is in the samge AG as its parent, the btree will be searched
> starting on the parent's record, and then retried from the top if no slot is
> available beyond the parent's record.
> 
> To exit this loop though, xfs_dialloc_ag_inobt() relies on the fact that the
> btree must have a free slot available, once its callers relied on the
> agi->freecount when deciding how/where to allocate this new inode.
> 
> In the case when the agi->freecount is corrupted, showing available inodes in an
> AG, when in fact there is none, this becomes an infinite loop.
> 
> Add a way to stop the loop when a free slot is not found in the btree, making
> the function to fall into the whole AG scan which will then, be able to detect
> the corruption and shut the filesystem down.
> 
> As pointed by Brian, this might impact performance, giving the fact we
> don't reset the search distance anymore when we reach the end of the
> tree, giving it fewer tries before falling back to the whole AG search, but
> it will only affect searches that start within 10 records to the end of the tree.
> 
> Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>

Looks ok, will test... hey, what's the xfstest number?

Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

> ---
> Changelog:
> 
> 	V3: - Move searchdistance state saving out of the while loop
> 	    - Remove newino goto label
> 
> 	V2: - Use searchdistance variable to stop the infinite loop
> 	      instead of adding a new mechanism
> 
>  fs/xfs/libxfs/xfs_ialloc.c | 55 +++++++++++++++++++++++-----------------------
>  1 file changed, 27 insertions(+), 28 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
> index d41ade5d293e..0e1cc51f05a1 100644
> --- a/fs/xfs/libxfs/xfs_ialloc.c
> +++ b/fs/xfs/libxfs/xfs_ialloc.c
> @@ -1123,6 +1123,7 @@ xfs_dialloc_ag_inobt(
>  	int			error;
>  	int			offset;
>  	int			i, j;
> +	int			searchdistance = 10;
>  
>  	pag = xfs_perag_get(mp, agno);
>  
> @@ -1149,7 +1150,6 @@ xfs_dialloc_ag_inobt(
>  	if (pagno == agno) {
>  		int		doneleft;	/* done, to the left */
>  		int		doneright;	/* done, to the right */
> -		int		searchdistance = 10;
>  
>  		error = xfs_inobt_lookup(cur, pagino, XFS_LOOKUP_LE, &i);
>  		if (error)
> @@ -1210,21 +1210,9 @@ xfs_dialloc_ag_inobt(
>  		/*
>  		 * Loop until we find an inode chunk with a free inode.
>  		 */
> -		while (!doneleft || !doneright) {
> +		while (--searchdistance > 0 && (!doneleft || !doneright)) {
>  			int	useleft;  /* using left inode chunk this time */
>  
> -			if (!--searchdistance) {
> -				/*
> -				 * Not in range - save last search
> -				 * location and allocate a new inode
> -				 */
> -				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
> -				pag->pagl_leftrec = trec.ir_startino;
> -				pag->pagl_rightrec = rec.ir_startino;
> -				pag->pagl_pagino = pagino;
> -				goto newino;
> -			}
> -
>  			/* figure out the closer block if both are valid. */
>  			if (!doneleft && !doneright) {
>  				useleft = pagino -
> @@ -1268,26 +1256,37 @@ xfs_dialloc_ag_inobt(
>  				goto error1;
>  		}
>  
> -		/*
> -		 * We've reached the end of the btree. because
> -		 * we are only searching a small chunk of the
> -		 * btree each search, there is obviously free
> -		 * inodes closer to the parent inode than we
> -		 * are now. restart the search again.
> -		 */
> -		pag->pagl_pagino = NULLAGINO;
> -		pag->pagl_leftrec = NULLAGINO;
> -		pag->pagl_rightrec = NULLAGINO;
> -		xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
> -		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
> -		goto restart_pagno;
> +		if (searchdistance <= 0) {
> +			/*
> +			 * Not in range - save last search
> +			 * location and allocate a new inode
> +			 */
> +			xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
> +			pag->pagl_leftrec = trec.ir_startino;
> +			pag->pagl_rightrec = rec.ir_startino;
> +			pag->pagl_pagino = pagino;
> +
> +		} else {
> +			/*
> +			 * We've reached the end of the btree. because
> +			 * we are only searching a small chunk of the
> +			 * btree each search, there is obviously free
> +			 * inodes closer to the parent inode than we
> +			 * are now. restart the search again.
> +			 */
> +			pag->pagl_pagino = NULLAGINO;
> +			pag->pagl_leftrec = NULLAGINO;
> +			pag->pagl_rightrec = NULLAGINO;
> +			xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
> +			xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
> +			goto restart_pagno;
> +		}
>  	}
>  
>  	/*
>  	 * In a different AG from the parent.
>  	 * See if the most recently allocated block has any free.
>  	 */
> -newino:
>  	if (agi->agi_newino != cpu_to_be32(NULLAGINO)) {
>  		error = xfs_inobt_lookup(cur, be32_to_cpu(agi->agi_newino),
>  					 XFS_LOOKUP_EQ, &i);
> -- 
> 2.13.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2017-08-14 22:48 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-14 10:53 [PATCH] Stop searching for free slots in an inode chunk when there are none Carlos Maiolino
2017-08-14 11:36 ` Carlos Maiolino
2017-08-14 22:48 ` Darrick J. Wong [this message]
  -- strict thread matches above, loose matches on Subject: below --
2017-08-03 15:19 Carlos Maiolino
2017-08-03 22:35 ` Dave Chinner
2017-08-04  8:55   ` Carlos Eduardo Maiolino
2017-08-04  9:36     ` Carlos Eduardo Maiolino
2017-08-04 23:17       ` 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=20170814224817.GD4796@magnolia \
    --to=darrick.wong@oracle.com \
    --cc=cmaiolino@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox