Re: [PATCH 4/9] repair: parallelise phase 7

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

 



On Tue, Dec 22, 2015 at 08:37:04AM +1100, Dave Chinner wrote:
> From: Dave Chinner <dchinner@xxxxxxxxxx>
> 
> It operates on a single AG at a time, sequentially, doing inode updates. All the
> data structures accessed and modified are per AG, as are the modification to
> on-disk structures. Hence we can run this phase concurrently across multiple
> AGs.
> 
> This is important for large, broken filesystem repairs, where there can be
> millions of inodes that need link counts updated. Once such repair image takes
> more than 45 minutes to run phase 7 as a single threaded operation.
> 
> Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
> ---

Reviewed-by: Brian Foster <bfoster@xxxxxxxxxx>

>  repair/phase7.c     | 77 ++++++++++++++++++++++++++++++++++-------------------
>  repair/progress.c   |  4 +--
>  repair/protos.h     |  2 +-
>  repair/xfs_repair.c |  2 +-
>  4 files changed, 54 insertions(+), 31 deletions(-)
> 
> diff --git a/repair/phase7.c b/repair/phase7.c
> index b1e3a55..91dad02 100644
> --- a/repair/phase7.c
> +++ b/repair/phase7.c
> @@ -26,6 +26,7 @@
>  #include "dinode.h"
>  #include "versions.h"
>  #include "progress.h"
> +#include "threads.h"
>  
>  /* dinoc is a pointer to the IN-CORE dinode core */
>  static void
> @@ -108,45 +109,67 @@ update_inode_nlinks(
>  	IRELE(ip);
>  }
>  
> -void
> -phase7(xfs_mount_t *mp)
> +/*
> + * for each ag, look at each inode 1 at a time. If the number of
> + * links is bad, reset it, log the inode core, commit the transaction
> + */
> +static void
> +do_link_updates(
> +	struct work_queue	*wq,
> +	xfs_agnumber_t		agno,
> +	void			*arg)
>  {
>  	ino_tree_node_t		*irec;
> -	int			i;
>  	int			j;
>  	__uint32_t		nrefs;
>  
> +	irec = findfirst_inode_rec(agno);
> +
> +	while (irec != NULL)  {
> +		for (j = 0; j < XFS_INODES_PER_CHUNK; j++)  {
> +			ASSERT(is_inode_confirmed(irec, j));
> +
> +			if (is_inode_free(irec, j))
> +				continue;
> +
> +			ASSERT(no_modify || is_inode_reached(irec, j));
> +
> +			nrefs = num_inode_references(irec, j);
> +			ASSERT(no_modify || nrefs > 0);
> +
> +			if (get_inode_disk_nlinks(irec, j) != nrefs)
> +				update_inode_nlinks(wq->mp,
> +					XFS_AGINO_TO_INO(wq->mp, agno,
> +						irec->ino_startnum + j),
> +					nrefs);
> +		}
> +		irec = next_ino_rec(irec);
> +	}
> +
> +	PROG_RPT_INC(prog_rpt_done[agno], 1);
> +}
> +
> +void
> +phase7(
> +	struct xfs_mount	*mp,
> +	int			scan_threads)
> +{
> +	struct work_queue	wq;
> +	int			agno;
> +
>  	if (!no_modify)
>  		do_log(_("Phase 7 - verify and correct link counts...\n"));
>  	else
>  		do_log(_("Phase 7 - verify link counts...\n"));
>  
> -	/*
> -	 * for each ag, look at each inode 1 at a time. If the number of
> -	 * links is bad, reset it, log the inode core, commit the transaction
> -	 */
> -	for (i = 0; i < glob_agcount; i++)  {
> -		irec = findfirst_inode_rec(i);
> -
> -		while (irec != NULL)  {
> -			for (j = 0; j < XFS_INODES_PER_CHUNK; j++)  {
> -				ASSERT(is_inode_confirmed(irec, j));
> +	set_progress_msg(PROGRESS_FMT_CORR_LINK, (__uint64_t) glob_agcount);
>  
> -				if (is_inode_free(irec, j))
> -					continue;
> +	create_work_queue(&wq, mp, scan_threads);
>  
> -				ASSERT(no_modify || is_inode_reached(irec, j));
> +	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
> +		queue_work(&wq, do_link_updates, agno, NULL);
>  
> -				nrefs = num_inode_references(irec, j);
> -				ASSERT(no_modify || nrefs > 0);
> +	destroy_work_queue(&wq);
>  
> -				if (get_inode_disk_nlinks(irec, j) != nrefs)
> -					update_inode_nlinks(mp,
> -						XFS_AGINO_TO_INO(mp, i,
> -							irec->ino_startnum + j),
> -						nrefs);
> -			}
> -			irec = next_ino_rec(irec);
> -		}
> -	}
> +	print_final_rpt();
>  }
> diff --git a/repair/progress.c b/repair/progress.c
> index 418b803..2a09b23 100644
> --- a/repair/progress.c
> +++ b/repair/progress.c
> @@ -75,9 +75,9 @@ progress_rpt_t progress_rpt_reports[] = {
>  {FMT2, N_("moving disconnected inodes to lost+found"),		/* 12 */
>  	&rpt_fmts[FMT2], &rpt_types[TYPE_INODE]},
>  {FMT1, N_("verify and correct link counts"),			/* 13 */
> -	&rpt_fmts[FMT1], &rpt_types[TYPE_INODE]},
> +	&rpt_fmts[FMT1], &rpt_types[TYPE_AG]},
>  {FMT1, N_("verify link counts"),				/* 14 */
> -	&rpt_fmts[FMT1], &rpt_types[TYPE_INODE]}
> +	&rpt_fmts[FMT1], &rpt_types[TYPE_AG]}
>  };
>  
>  pthread_t	report_thread;
> diff --git a/repair/protos.h b/repair/protos.h
> index 9d5a2a6..b113aca 100644
> --- a/repair/protos.h
> +++ b/repair/protos.h
> @@ -50,7 +50,7 @@ void	phase3(struct xfs_mount *);
>  void	phase4(struct xfs_mount *);
>  void	phase5(struct xfs_mount *);
>  void	phase6(struct xfs_mount *);
> -void	phase7(struct xfs_mount *);
> +void	phase7(struct xfs_mount *, int);
>  
>  int	verify_set_agheader(struct xfs_mount *, struct xfs_buf *,
>  		struct xfs_sb *, struct xfs_agf *, struct xfs_agi *,
> diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
> index 3eaced4..fcdb212 100644
> --- a/repair/xfs_repair.c
> +++ b/repair/xfs_repair.c
> @@ -893,7 +893,7 @@ main(int argc, char **argv)
>  		phase6(mp);
>  		timestamp(PHASE_END, 6, NULL);
>  
> -		phase7(mp);
> +		phase7(mp, phase2_threads);
>  		timestamp(PHASE_END, 7, NULL);
>  	} else  {
>  		do_warn(
> -- 
> 2.5.0
> 
> _______________________________________________
> xfs mailing list
> xfs@xxxxxxxxxxx
> http://oss.sgi.com/mailman/listinfo/xfs

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



[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux