Commit a40fe308 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: separate dquot buffer reads from xfs_dqflush



The first step towards holding the dquot buffer in the li_buf instead of
reading it in the AIL is to separate the part that reads the buffer from
the actual flush code.  There should be no functional changes.

Signed-off-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 07137e92
Loading
Loading
Loading
Loading
+37 −20
Original line number Diff line number Diff line
@@ -1238,6 +1238,42 @@ xfs_qm_dqflush_check(
	return NULL;
}

/*
 * Get the buffer containing the on-disk dquot.
 *
 * Requires dquot flush lock, will clear the dirty flag, delete the quota log
 * item from the AIL, and shut down the system if something goes wrong.
 */
int
xfs_dquot_read_buf(
	struct xfs_trans	*tp,
	struct xfs_dquot	*dqp,
	struct xfs_buf		**bpp)
{
	struct xfs_mount	*mp = dqp->q_mount;
	struct xfs_buf		*bp = NULL;
	int			error;

	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, dqp->q_blkno,
				   mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK,
				   &bp, &xfs_dquot_buf_ops);
	if (error == -EAGAIN)
		return error;
	if (xfs_metadata_is_sick(error))
		xfs_dquot_mark_sick(dqp);
	if (error)
		goto out_abort;

	*bpp = bp;
	return 0;

out_abort:
	dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
	xfs_trans_ail_delete(&dqp->q_logitem.qli_item, 0);
	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
	return error;
}

/*
 * Write a modified dquot to disk.
 * The dquot must be locked and the flush lock too taken by caller.
@@ -1249,11 +1285,10 @@ xfs_qm_dqflush_check(
int
xfs_qm_dqflush(
	struct xfs_dquot	*dqp,
	struct xfs_buf		**bpp)
	struct xfs_buf		*bp)
{
	struct xfs_mount	*mp = dqp->q_mount;
	struct xfs_log_item	*lip = &dqp->q_logitem.qli_item;
	struct xfs_buf		*bp;
	struct xfs_dqblk	*dqblk;
	xfs_failaddr_t		fa;
	int			error;
@@ -1263,28 +1298,12 @@ xfs_qm_dqflush(

	trace_xfs_dqflush(dqp);

	*bpp = NULL;

	xfs_qm_dqunpin_wait(dqp);

	/*
	 * Get the buffer containing the on-disk dquot
	 */
	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
				   mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK,
				   &bp, &xfs_dquot_buf_ops);
	if (error == -EAGAIN)
		goto out_unlock;
	if (xfs_metadata_is_sick(error))
		xfs_dquot_mark_sick(dqp);
	if (error)
		goto out_abort;

	fa = xfs_qm_dqflush_check(dqp);
	if (fa) {
		xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
				dqp->q_id, fa);
		xfs_buf_relse(bp);
		xfs_dquot_mark_sick(dqp);
		error = -EFSCORRUPTED;
		goto out_abort;
@@ -1334,14 +1353,12 @@ xfs_qm_dqflush(
	}

	trace_xfs_dqflush_done(dqp);
	*bpp = bp;
	return 0;

out_abort:
	dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
	xfs_trans_ail_delete(lip, 0);
	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
out_unlock:
	xfs_dqfunlock(dqp);
	return error;
}
+3 −1
Original line number Diff line number Diff line
@@ -214,7 +214,9 @@ void xfs_dquot_to_disk(struct xfs_disk_dquot *ddqp, struct xfs_dquot *dqp);
#define XFS_DQ_IS_DIRTY(dqp)	((dqp)->q_flags & XFS_DQFLAG_DIRTY)

void		xfs_qm_dqdestroy(struct xfs_dquot *dqp);
int		xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf **bpp);
int		xfs_dquot_read_buf(struct xfs_trans *tp, struct xfs_dquot *dqp,
				struct xfs_buf **bpp);
int		xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf *bp);
void		xfs_qm_dqunpin_wait(struct xfs_dquot *dqp);
void		xfs_qm_adjust_dqtimers(struct xfs_dquot *d);
void		xfs_qm_adjust_dqlimits(struct xfs_dquot *d);
+16 −4
Original line number Diff line number Diff line
@@ -155,14 +155,26 @@ xfs_qm_dquot_logitem_push(

	spin_unlock(&lip->li_ailp->ail_lock);

	error = xfs_qm_dqflush(dqp, &bp);
	error = xfs_dquot_read_buf(NULL, dqp, &bp);
	if (error) {
		if (error == -EAGAIN)
			rval = XFS_ITEM_LOCKED;
		xfs_dqfunlock(dqp);
		goto out_relock_ail;
	}

	/*
	 * dqflush completes dqflock on error, and the delwri ioend does it on
	 * success.
	 */
	error = xfs_qm_dqflush(dqp, bp);
	if (!error) {
		if (!xfs_buf_delwri_queue(bp, buffer_list))
			rval = XFS_ITEM_FLUSHING;
	}
	xfs_buf_relse(bp);
	} else if (error == -EAGAIN)
		rval = XFS_ITEM_LOCKED;

out_relock_ail:
	spin_lock(&lip->li_ailp->ail_lock);
out_unlock:
	xfs_dqunlock(dqp);
+30 −7
Original line number Diff line number Diff line
@@ -148,17 +148,28 @@ xfs_qm_dqpurge(
		 * We don't care about getting disk errors here. We need
		 * to purge this dquot anyway, so we go ahead regardless.
		 */
		error = xfs_qm_dqflush(dqp, &bp);
		error = xfs_dquot_read_buf(NULL, dqp, &bp);
		if (error == -EAGAIN) {
			xfs_dqfunlock(dqp);
			dqp->q_flags &= ~XFS_DQFLAG_FREEING;
			goto out_unlock;
		}
		if (error)
			goto out_funlock;

		/*
		 * dqflush completes dqflock on error, and the bwrite ioend
		 * does it on success.
		 */
		error = xfs_qm_dqflush(dqp, bp);
		if (!error) {
			error = xfs_bwrite(bp);
			xfs_buf_relse(bp);
		} else if (error == -EAGAIN) {
			dqp->q_flags &= ~XFS_DQFLAG_FREEING;
			goto out_unlock;
		}
		xfs_dqflock(dqp);
	}

out_funlock:
	ASSERT(atomic_read(&dqp->q_pincount) == 0);
	ASSERT(xlog_is_shutdown(dqp->q_logitem.qli_item.li_log) ||
		!test_bit(XFS_LI_IN_AIL, &dqp->q_logitem.qli_item.li_flags));
@@ -494,7 +505,17 @@ xfs_qm_dquot_isolate(
		/* we have to drop the LRU lock to flush the dquot */
		spin_unlock(&lru->lock);

		error = xfs_qm_dqflush(dqp, &bp);
		error = xfs_dquot_read_buf(NULL, dqp, &bp);
		if (error) {
			xfs_dqfunlock(dqp);
			goto out_unlock_dirty;
		}

		/*
		 * dqflush completes dqflock on error, and the delwri ioend
		 * does it on success.
		 */
		error = xfs_qm_dqflush(dqp, bp);
		if (error)
			goto out_unlock_dirty;

@@ -1489,10 +1510,12 @@ xfs_qm_flush_one(
		goto out_unlock;
	}

	error = xfs_qm_dqflush(dqp, &bp);
	error = xfs_dquot_read_buf(NULL, dqp, &bp);
	if (error)
		goto out_unlock;

	error = xfs_qm_dqflush(dqp, bp);
	if (!error)
		xfs_buf_delwri_queue(bp, buffer_list);
	xfs_buf_relse(bp);
out_unlock: