diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index f807f8f4f705..2645052042bf 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -426,6 +426,23 @@ xlog_state_shutdown_callbacks( struct xlog_in_core *iclog; LIST_HEAD(cb_list); + /* + * Shutdown waiters on ic_force_wait do not require callback completion. + * Once log shutdown has been established, they only need to wake, + * observe xlog_is_shutdown(), and abort with -EIO. + * + * Wake them before processing callbacks to avoid deadlock if callback + * processing blocks on a buffer lock and prevents the wakeup from being + * reached. + * + * Keep ic_write_wait wakeups ordered after callback processing so + * shutdown callback side effects still complete before teardown progresses. + */ + iclog = log->l_iclog; + do { + wake_up_all(&iclog->ic_force_wait); + } while ((iclog = iclog->ic_next) != log->l_iclog); + iclog = log->l_iclog; do { if (atomic_read(&iclog->ic_refcnt)) { @@ -439,7 +456,6 @@ xlog_state_shutdown_callbacks( spin_lock(&log->l_icloglock); wake_up_all(&iclog->ic_write_wait); - wake_up_all(&iclog->ic_force_wait); } while ((iclog = iclog->ic_next) != log->l_iclog); wake_up_all(&log->l_flush_wait);