Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23fac50f authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Niv Sardi
Browse files

[XFS] split up xlog_recover_process_iunlinks



Split out the body of the main loop into a separate helper to make the
code readable.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <david@fromorbit.com>
Signed-off-by: default avatarNiv Sardi <xaiki@sgi.com>
parent 51ce16d5
Loading
Loading
Loading
Loading
+66 −68
Original line number Diff line number Diff line
@@ -3147,6 +3147,70 @@ out_error:
	return;
}

STATIC xfs_agino_t
xlog_recover_process_one_iunlink(
	struct xfs_mount		*mp,
	xfs_agnumber_t			agno,
	xfs_agino_t			agino,
	int				bucket)
{
	struct xfs_buf			*ibp;
	struct xfs_dinode		*dip;
	struct xfs_inode		*ip;
	xfs_ino_t			ino;
	int				error;

	ino = XFS_AGINO_TO_INO(mp, agno, agino);
	error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
	if (error)
		goto fail;

	/*
	 * Get the on disk inode to find the next inode in the bucket.
	 */
	ASSERT(ip != NULL);
	error = xfs_itobp(mp, NULL, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
	if (error)
		goto fail;

	ASSERT(dip != NULL);
	ASSERT(ip->i_d.di_nlink == 0);

	/* setup for the next pass */
	agino = be32_to_cpu(dip->di_next_unlinked);
	xfs_buf_relse(ibp);

	/*
	 * Prevent any DMAPI event from being sent when the reference on
	 * the inode is dropped.
	 */
	ip->i_d.di_dmevmask = 0;

	/*
	 * If this is a new inode, handle it specially.  Otherwise, just
	 * drop our reference to the inode.  If there are no other
	 * references, this will send the inode to xfs_inactive() which
	 * will truncate the file and free the inode.
	 */
	if (ip->i_d.di_mode == 0)
		xfs_iput_new(ip, 0);
	else
		IRELE(ip);
	return agino;

 fail:
	/*
	 * We can't read in the inode this bucket points to, or this inode
	 * is messed up.  Just ditch this bucket of inodes.  We will lose
	 * some inodes and space, but at least we won't hang.
	 *
	 * Call xlog_recover_clear_agi_bucket() to perform a transaction to
	 * clear the inode pointer in the bucket.
	 */
	xlog_recover_clear_agi_bucket(mp, agno, bucket);
	return NULLAGINO;
}

/*
 * xlog_iunlink_recover
 *
@@ -3167,11 +3231,7 @@ xlog_recover_process_iunlinks(
	xfs_agnumber_t	agno;
	xfs_agi_t	*agi;
	xfs_buf_t	*agibp;
	xfs_buf_t	*ibp;
	xfs_dinode_t	*dip;
	xfs_inode_t	*ip;
	xfs_agino_t	agino;
	xfs_ino_t	ino;
	int		bucket;
	int		error;
	uint		mp_dmevmask;
@@ -3201,10 +3261,8 @@ xlog_recover_process_iunlinks(
		agi = XFS_BUF_TO_AGI(agibp);

		for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {

			agino = be32_to_cpu(agi->agi_unlinked[bucket]);
			while (agino != NULLAGINO) {

				/*
				 * Release the agi buffer so that it can
				 * be acquired in the normal course of the
@@ -3212,68 +3270,8 @@ xlog_recover_process_iunlinks(
				 */
				xfs_buf_relse(agibp);

				ino = XFS_AGINO_TO_INO(mp, agno, agino);
				error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
				ASSERT(error || (ip != NULL));

				if (!error) {
					/*
					 * Get the on disk inode to find the
					 * next inode in the bucket.
					 */
					error = xfs_itobp(mp, NULL, ip, &dip,
							&ibp, 0, 0,
							XFS_BUF_LOCK);
					ASSERT(error || (dip != NULL));
				}

				if (!error) {
					ASSERT(ip->i_d.di_nlink == 0);

					/* setup for the next pass */
					agino = be32_to_cpu(
							dip->di_next_unlinked);
					xfs_buf_relse(ibp);
					/*
					 * Prevent any DMAPI event from
					 * being sent when the
					 * reference on the inode is
					 * dropped.
					 */
					ip->i_d.di_dmevmask = 0;

					/*
					 * If this is a new inode, handle
					 * it specially.  Otherwise,
					 * just drop our reference to the
					 * inode.  If there are no
					 * other references, this will
					 * send the inode to
					 * xfs_inactive() which will
					 * truncate the file and free
					 * the inode.
					 */
					if (ip->i_d.di_mode == 0)
						xfs_iput_new(ip, 0);
					else
						IRELE(ip);
				} else {
					/*
					 * We can't read in the inode
					 * this bucket points to, or
					 * this inode is messed up.  Just
					 * ditch this bucket of inodes.  We
					 * will lose some inodes and space,
					 * but at least we won't hang.  Call
					 * xlog_recover_clear_agi_bucket()
					 * to perform a transaction to clear
					 * the inode pointer in the bucket.
					 */
					xlog_recover_clear_agi_bucket(mp, agno,
							bucket);

					agino = NULLAGINO;
				}
				agino = xlog_recover_process_one_iunlink(mp,
							agno, agino, bucket);

				/*
				 * Reacquire the agibuffer and continue around