xfs: force the log before shutting down

When we have marked the filesystem for shutdown, we want to prevent
any further buffer IO from being submitted. However, we currently
force the log after marking the filesystem as shut down, hence
allowing IO to the log *after* we have marked both the filesystem
and the log as in an error state.

Clean this up by forcing the log before we mark the filesytem with
an error. This replaces the pure CIL flush that we currently have
which works around this same issue (i.e the CIL can't be flushed
once the shutdown flags are set) and hence enables us to clean up
the logic substantially.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
Dave Chinner 2014-10-02 09:02:28 +10:00 committed by Dave Chinner
parent 52addcf9d6
commit a870fe6dfa

View File

@ -3867,18 +3867,17 @@ xlog_state_ioerror(
* This is called from xfs_force_shutdown, when we're forcibly * This is called from xfs_force_shutdown, when we're forcibly
* shutting down the filesystem, typically because of an IO error. * shutting down the filesystem, typically because of an IO error.
* Our main objectives here are to make sure that: * Our main objectives here are to make sure that:
* a. the filesystem gets marked 'SHUTDOWN' for all interested * a. if !logerror, flush the logs to disk. Anything modified
* after this is ignored.
* b. the filesystem gets marked 'SHUTDOWN' for all interested
* parties to find out, 'atomically'. * parties to find out, 'atomically'.
* b. those who're sleeping on log reservations, pinned objects and * c. those who're sleeping on log reservations, pinned objects and
* other resources get woken up, and be told the bad news. * other resources get woken up, and be told the bad news.
* c. nothing new gets queued up after (a) and (b) are done. * d. nothing new gets queued up after (b) and (c) are done.
* d. if !logerror, flush the iclogs to disk, then seal them off
* for business.
* *
* Note: for delayed logging the !logerror case needs to flush the regions * Note: for the !logerror case we need to flush the regions held in memory out
* held in memory out to the iclogs before flushing them to disk. This needs * to disk first. This needs to be done before the log is marked as shutdown,
* to be done before the log is marked as shutdown, otherwise the flush to the * otherwise the iclog writes will fail.
* iclogs will fail.
*/ */
int int
xfs_log_force_umount( xfs_log_force_umount(
@ -3910,16 +3909,16 @@ xfs_log_force_umount(
ASSERT(XLOG_FORCED_SHUTDOWN(log)); ASSERT(XLOG_FORCED_SHUTDOWN(log));
return 1; return 1;
} }
retval = 0;
/* /*
* Flush the in memory commit item list before marking the log as * Flush all the completed transactions to disk before marking the log
* being shut down. We need to do it in this order to ensure all the * being shut down. We need to do it in this order to ensure that
* completed transactions are flushed to disk with the xfs_log_force() * completed operations are safely on disk before we shut down, and that
* call below. * we don't have to issue any buffer IO after the shutdown flags are set
* to guarantee this.
*/ */
if (!logerror) if (!logerror)
xlog_cil_force(log); _xfs_log_force(mp, XFS_LOG_SYNC, NULL);
/* /*
* mark the filesystem and the as in a shutdown state and wake * mark the filesystem and the as in a shutdown state and wake
@ -3931,17 +3930,10 @@ xfs_log_force_umount(
XFS_BUF_DONE(mp->m_sb_bp); XFS_BUF_DONE(mp->m_sb_bp);
/* /*
* This flag is sort of redundant because of the mount flag, but * Mark the log and the iclogs with IO error flags to prevent any
* it's good to maintain the separation between the log and the rest * further log IO from being issued or completed.
* of XFS.
*/ */
log->l_flags |= XLOG_IO_ERROR; log->l_flags |= XLOG_IO_ERROR;
/*
* If we hit a log error, we want to mark all the iclogs IOERROR
* while we're still holding the loglock.
*/
if (logerror)
retval = xlog_state_ioerror(log); retval = xlog_state_ioerror(log);
spin_unlock(&log->l_icloglock); spin_unlock(&log->l_icloglock);
@ -3955,19 +3947,6 @@ xfs_log_force_umount(
xlog_grant_head_wake_all(&log->l_reserve_head); xlog_grant_head_wake_all(&log->l_reserve_head);
xlog_grant_head_wake_all(&log->l_write_head); xlog_grant_head_wake_all(&log->l_write_head);
if (!(log->l_iclog->ic_state & XLOG_STATE_IOERROR)) {
ASSERT(!logerror);
/*
* Force the incore logs to disk before shutting the
* log down completely.
*/
_xfs_log_force(mp, XFS_LOG_SYNC, NULL);
spin_lock(&log->l_icloglock);
retval = xlog_state_ioerror(log);
spin_unlock(&log->l_icloglock);
}
/* /*
* Wake up everybody waiting on xfs_log_force. Wake the CIL push first * Wake up everybody waiting on xfs_log_force. Wake the CIL push first
* as if the log writes were completed. The abort handling in the log * as if the log writes were completed. The abort handling in the log