Commit c196bf43 authored by Cong Zhang's avatar Cong Zhang Committed by Jens Axboe
Browse files

blk-mq: Abort suspend when wakeup events are pending



During system suspend, wakeup capable IRQs for block device can be
delayed, which can cause blk_mq_hctx_notify_offline() to hang
indefinitely while waiting for pending request to complete.
Skip the request waiting loop and abort suspend when wakeup events are
pending to prevent the deadlock.

Fixes: bf0beec0 ("blk-mq: drain I/O when all CPUs in a hctx are offline")
Signed-off-by: default avatarCong Zhang <cong.zhang@oss.qualcomm.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 71075d25
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/cache.h>
#include <linux/sched/topology.h>
#include <linux/sched/signal.h>
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/crash_dump.h>
#include <linux/prefetch.h>
@@ -3718,6 +3719,7 @@ static int blk_mq_hctx_notify_offline(unsigned int cpu, struct hlist_node *node)
{
	struct blk_mq_hw_ctx *hctx = hlist_entry_safe(node,
			struct blk_mq_hw_ctx, cpuhp_online);
	int ret = 0;

	if (blk_mq_hctx_has_online_cpu(hctx, cpu))
		return 0;
@@ -3738,12 +3740,24 @@ static int blk_mq_hctx_notify_offline(unsigned int cpu, struct hlist_node *node)
	 * frozen and there are no requests.
	 */
	if (percpu_ref_tryget(&hctx->queue->q_usage_counter)) {
		while (blk_mq_hctx_has_requests(hctx))
		while (blk_mq_hctx_has_requests(hctx)) {
			/*
			 * The wakeup capable IRQ handler of block device is
			 * not called during suspend. Skip the loop by checking
			 * pm_wakeup_pending to prevent the deadlock and improve
			 * suspend latency.
			 */
			if (pm_wakeup_pending()) {
				clear_bit(BLK_MQ_S_INACTIVE, &hctx->state);
				ret = -EBUSY;
				break;
			}
			msleep(5);
		}
		percpu_ref_put(&hctx->queue->q_usage_counter);
	}

	return 0;
	return ret;
}

/*