|
@@ -1000,27 +1000,34 @@ xfs_log_space_wake(
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Determine if we have a transaction that has gone to disk
|
|
|
- * that needs to be covered. To begin the transition to the idle state
|
|
|
- * firstly the log needs to be idle (no AIL and nothing in the iclogs).
|
|
|
- * If we are then in a state where covering is needed, the caller is informed
|
|
|
- * that dummy transactions are required to move the log into the idle state.
|
|
|
+ * Determine if we have a transaction that has gone to disk that needs to be
|
|
|
+ * covered. To begin the transition to the idle state firstly the log needs to
|
|
|
+ * be idle. That means the CIL, the AIL and the iclogs needs to be empty before
|
|
|
+ * we start attempting to cover the log.
|
|
|
*
|
|
|
- * Because this is called as part of the sync process, we should also indicate
|
|
|
- * that dummy transactions should be issued in anything but the covered or
|
|
|
- * idle states. This ensures that the log tail is accurately reflected in
|
|
|
- * the log at the end of the sync, hence if a crash occurrs avoids replay
|
|
|
- * of transactions where the metadata is already on disk.
|
|
|
+ * Only if we are then in a state where covering is needed, the caller is
|
|
|
+ * informed that dummy transactions are required to move the log into the idle
|
|
|
+ * state.
|
|
|
+ *
|
|
|
+ * If there are any items in the AIl or CIL, then we do not want to attempt to
|
|
|
+ * cover the log as we may be in a situation where there isn't log space
|
|
|
+ * available to run a dummy transaction and this can lead to deadlocks when the
|
|
|
+ * tail of the log is pinned by an item that is modified in the CIL. Hence
|
|
|
+ * there's no point in running a dummy transaction at this point because we
|
|
|
+ * can't start trying to idle the log until both the CIL and AIL are empty.
|
|
|
*/
|
|
|
int
|
|
|
xfs_log_need_covered(xfs_mount_t *mp)
|
|
|
{
|
|
|
- int needed = 0;
|
|
|
struct xlog *log = mp->m_log;
|
|
|
+ int needed = 0;
|
|
|
|
|
|
if (!xfs_fs_writable(mp))
|
|
|
return 0;
|
|
|
|
|
|
+ if (!xlog_cil_empty(log))
|
|
|
+ return 0;
|
|
|
+
|
|
|
spin_lock(&log->l_icloglock);
|
|
|
switch (log->l_covered_state) {
|
|
|
case XLOG_STATE_COVER_DONE:
|
|
@@ -1029,14 +1036,17 @@ xfs_log_need_covered(xfs_mount_t *mp)
|
|
|
break;
|
|
|
case XLOG_STATE_COVER_NEED:
|
|
|
case XLOG_STATE_COVER_NEED2:
|
|
|
- if (!xfs_ail_min_lsn(log->l_ailp) &&
|
|
|
- xlog_iclogs_empty(log)) {
|
|
|
- if (log->l_covered_state == XLOG_STATE_COVER_NEED)
|
|
|
- log->l_covered_state = XLOG_STATE_COVER_DONE;
|
|
|
- else
|
|
|
- log->l_covered_state = XLOG_STATE_COVER_DONE2;
|
|
|
- }
|
|
|
- /* FALLTHRU */
|
|
|
+ if (xfs_ail_min_lsn(log->l_ailp))
|
|
|
+ break;
|
|
|
+ if (!xlog_iclogs_empty(log))
|
|
|
+ break;
|
|
|
+
|
|
|
+ needed = 1;
|
|
|
+ if (log->l_covered_state == XLOG_STATE_COVER_NEED)
|
|
|
+ log->l_covered_state = XLOG_STATE_COVER_DONE;
|
|
|
+ else
|
|
|
+ log->l_covered_state = XLOG_STATE_COVER_DONE2;
|
|
|
+ break;
|
|
|
default:
|
|
|
needed = 1;
|
|
|
break;
|