mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
xfs: abort consistently on dquot flush failure
The dquot flush handler effectively aborts the dquot flush if the filesystem is already shut down, but doesn't actually shut down if the flush fails. Update xfs_qm_dqflush() to consistently abort the dquot flush and shutdown the fs if the flush fails with an unexpected error. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Allison Collins <allison.henderson@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
parent
629dcb38dc
commit
b707fffda6
1 changed files with 10 additions and 22 deletions
|
@ -1068,6 +1068,7 @@ xfs_qm_dqflush(
|
||||||
struct xfs_buf **bpp)
|
struct xfs_buf **bpp)
|
||||||
{
|
{
|
||||||
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_buf *bp;
|
struct xfs_buf *bp;
|
||||||
struct xfs_dqblk *dqb;
|
struct xfs_dqblk *dqb;
|
||||||
struct xfs_disk_dquot *ddqp;
|
struct xfs_disk_dquot *ddqp;
|
||||||
|
@ -1083,32 +1084,16 @@ xfs_qm_dqflush(
|
||||||
|
|
||||||
xfs_qm_dqunpin_wait(dqp);
|
xfs_qm_dqunpin_wait(dqp);
|
||||||
|
|
||||||
/*
|
|
||||||
* This may have been unpinned because the filesystem is shutting
|
|
||||||
* down forcibly. If that's the case we must not write this dquot
|
|
||||||
* to disk, because the log record didn't make it to disk.
|
|
||||||
*
|
|
||||||
* We also have to remove the log item from the AIL in this case,
|
|
||||||
* as we wait for an emptry AIL as part of the unmount process.
|
|
||||||
*/
|
|
||||||
if (XFS_FORCED_SHUTDOWN(mp)) {
|
|
||||||
struct xfs_log_item *lip = &dqp->q_logitem.qli_item;
|
|
||||||
dqp->dq_flags &= ~XFS_DQ_DIRTY;
|
|
||||||
|
|
||||||
xfs_trans_ail_remove(lip, SHUTDOWN_CORRUPT_INCORE);
|
|
||||||
|
|
||||||
error = -EIO;
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the buffer containing the on-disk dquot
|
* Get the buffer containing the on-disk dquot
|
||||||
*/
|
*/
|
||||||
error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
|
error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
|
||||||
mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK,
|
mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK,
|
||||||
&bp, &xfs_dquot_buf_ops);
|
&bp, &xfs_dquot_buf_ops);
|
||||||
if (error)
|
if (error == -EAGAIN)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
if (error)
|
||||||
|
goto out_abort;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the location of the dquot inside the buffer.
|
* Calculate the location of the dquot inside the buffer.
|
||||||
|
@ -1123,9 +1108,8 @@ xfs_qm_dqflush(
|
||||||
xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
|
xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
|
||||||
be32_to_cpu(dqp->q_core.d_id), fa);
|
be32_to_cpu(dqp->q_core.d_id), fa);
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
xfs_dqfunlock(dqp);
|
error = -EFSCORRUPTED;
|
||||||
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
|
goto out_abort;
|
||||||
return -EFSCORRUPTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the only portion of data that needs to persist */
|
/* This is the only portion of data that needs to persist */
|
||||||
|
@ -1174,6 +1158,10 @@ xfs_qm_dqflush(
|
||||||
*bpp = bp;
|
*bpp = bp;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_abort:
|
||||||
|
dqp->dq_flags &= ~XFS_DQ_DIRTY;
|
||||||
|
xfs_trans_ail_remove(lip, SHUTDOWN_CORRUPT_INCORE);
|
||||||
|
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
xfs_dqfunlock(dqp);
|
xfs_dqfunlock(dqp);
|
||||||
return error;
|
return error;
|
||||||
|
|
Loading…
Reference in a new issue