mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-04 04:04:19 +00:00
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: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
07137e925f
commit
a40fe30868
@ -1238,6 +1238,42 @@ xfs_qm_dqflush_check(
|
|||||||
return NULL;
|
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.
|
* Write a modified dquot to disk.
|
||||||
* The dquot must be locked and the flush lock too taken by caller.
|
* The dquot must be locked and the flush lock too taken by caller.
|
||||||
@ -1249,11 +1285,10 @@ xfs_qm_dqflush_check(
|
|||||||
int
|
int
|
||||||
xfs_qm_dqflush(
|
xfs_qm_dqflush(
|
||||||
struct xfs_dquot *dqp,
|
struct xfs_dquot *dqp,
|
||||||
struct xfs_buf **bpp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
struct xfs_mount *mp = dqp->q_mount;
|
struct xfs_mount *mp = dqp->q_mount;
|
||||||
struct xfs_log_item *lip = &dqp->q_logitem.qli_item;
|
struct xfs_log_item *lip = &dqp->q_logitem.qli_item;
|
||||||
struct xfs_buf *bp;
|
|
||||||
struct xfs_dqblk *dqblk;
|
struct xfs_dqblk *dqblk;
|
||||||
xfs_failaddr_t fa;
|
xfs_failaddr_t fa;
|
||||||
int error;
|
int error;
|
||||||
@ -1263,28 +1298,12 @@ xfs_qm_dqflush(
|
|||||||
|
|
||||||
trace_xfs_dqflush(dqp);
|
trace_xfs_dqflush(dqp);
|
||||||
|
|
||||||
*bpp = NULL;
|
|
||||||
|
|
||||||
xfs_qm_dqunpin_wait(dqp);
|
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);
|
fa = xfs_qm_dqflush_check(dqp);
|
||||||
if (fa) {
|
if (fa) {
|
||||||
xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
|
xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
|
||||||
dqp->q_id, fa);
|
dqp->q_id, fa);
|
||||||
xfs_buf_relse(bp);
|
|
||||||
xfs_dquot_mark_sick(dqp);
|
xfs_dquot_mark_sick(dqp);
|
||||||
error = -EFSCORRUPTED;
|
error = -EFSCORRUPTED;
|
||||||
goto out_abort;
|
goto out_abort;
|
||||||
@ -1334,14 +1353,12 @@ xfs_qm_dqflush(
|
|||||||
}
|
}
|
||||||
|
|
||||||
trace_xfs_dqflush_done(dqp);
|
trace_xfs_dqflush_done(dqp);
|
||||||
*bpp = bp;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_abort:
|
out_abort:
|
||||||
dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
|
dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
|
||||||
xfs_trans_ail_delete(lip, 0);
|
xfs_trans_ail_delete(lip, 0);
|
||||||
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
|
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
|
||||||
out_unlock:
|
|
||||||
xfs_dqfunlock(dqp);
|
xfs_dqfunlock(dqp);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->q_flags & XFS_DQFLAG_DIRTY)
|
||||||
|
|
||||||
void xfs_qm_dqdestroy(struct xfs_dquot *dqp);
|
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_dqunpin_wait(struct xfs_dquot *dqp);
|
||||||
void xfs_qm_adjust_dqtimers(struct xfs_dquot *d);
|
void xfs_qm_adjust_dqtimers(struct xfs_dquot *d);
|
||||||
void xfs_qm_adjust_dqlimits(struct xfs_dquot *d);
|
void xfs_qm_adjust_dqlimits(struct xfs_dquot *d);
|
||||||
|
@ -155,14 +155,26 @@ xfs_qm_dquot_logitem_push(
|
|||||||
|
|
||||||
spin_unlock(&lip->li_ailp->ail_lock);
|
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 (!error) {
|
||||||
if (!xfs_buf_delwri_queue(bp, buffer_list))
|
if (!xfs_buf_delwri_queue(bp, buffer_list))
|
||||||
rval = XFS_ITEM_FLUSHING;
|
rval = XFS_ITEM_FLUSHING;
|
||||||
xfs_buf_relse(bp);
|
}
|
||||||
} else if (error == -EAGAIN)
|
xfs_buf_relse(bp);
|
||||||
rval = XFS_ITEM_LOCKED;
|
|
||||||
|
|
||||||
|
out_relock_ail:
|
||||||
spin_lock(&lip->li_ailp->ail_lock);
|
spin_lock(&lip->li_ailp->ail_lock);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
|
@ -148,17 +148,28 @@ xfs_qm_dqpurge(
|
|||||||
* We don't care about getting disk errors here. We need
|
* We don't care about getting disk errors here. We need
|
||||||
* to purge this dquot anyway, so we go ahead regardless.
|
* 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) {
|
if (!error) {
|
||||||
error = xfs_bwrite(bp);
|
error = xfs_bwrite(bp);
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
} else if (error == -EAGAIN) {
|
|
||||||
dqp->q_flags &= ~XFS_DQFLAG_FREEING;
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
}
|
||||||
xfs_dqflock(dqp);
|
xfs_dqflock(dqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_funlock:
|
||||||
ASSERT(atomic_read(&dqp->q_pincount) == 0);
|
ASSERT(atomic_read(&dqp->q_pincount) == 0);
|
||||||
ASSERT(xlog_is_shutdown(dqp->q_logitem.qli_item.li_log) ||
|
ASSERT(xlog_is_shutdown(dqp->q_logitem.qli_item.li_log) ||
|
||||||
!test_bit(XFS_LI_IN_AIL, &dqp->q_logitem.qli_item.li_flags));
|
!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 */
|
/* we have to drop the LRU lock to flush the dquot */
|
||||||
spin_unlock(&lru->lock);
|
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)
|
if (error)
|
||||||
goto out_unlock_dirty;
|
goto out_unlock_dirty;
|
||||||
|
|
||||||
@ -1489,11 +1510,13 @@ xfs_qm_flush_one(
|
|||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = xfs_qm_dqflush(dqp, &bp);
|
error = xfs_dquot_read_buf(NULL, dqp, &bp);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
xfs_buf_delwri_queue(bp, buffer_list);
|
error = xfs_qm_dqflush(dqp, bp);
|
||||||
|
if (!error)
|
||||||
|
xfs_buf_delwri_queue(bp, buffer_list);
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
|
Loading…
Reference in New Issue
Block a user