Commit b707fffd authored by Brian Foster's avatar Brian Foster Committed by Darrick J. Wong

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: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarAllison Collins <allison.henderson@oracle.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 629dcb38
...@@ -1068,6 +1068,7 @@ xfs_qm_dqflush( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment