lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 18 Feb 2019 14:43:30 +0100
From:   Greg Kroah-Hartman <>
Cc:     Greg Kroah-Hartman <>,, Zachary Hays <>,
        Ulf Hansson <>
Subject: [PATCH 4.19 64/85] mmc: block: handle complete_work on separate workqueue

4.19-stable review patch.  If anyone has any objections, please let me know.


From: Zachary Hays <>

commit dcf6e2e38a1c7ccbc535de5e1d9b14998847499d upstream.

The kblockd workqueue is created with the WQ_MEM_RECLAIM flag set.
This generates a rescuer thread for that queue that will trigger when
the CPU is under heavy load and collect the uncompleted work.

In the case of mmc, this creates the possibility of a deadlock when
there are multiple partitions on the device as other blk-mq work is
also run on the same queue. For example:

- worker 0 claims the mmc host to work on partition 1
- worker 1 attempts to claim the host for partition 2 but has to wait
  for worker 0 to finish
- worker 0 schedules complete_work to release the host
- rescuer thread is triggered after time-out and collects the dangling
- rescuer thread attempts to complete the work in order starting with
  claim host
- the task to release host is now blocked by a task to claim it and
  will never be called

The above results in multiple hung tasks that lead to failures to
mount partitions.

Handling complete_work on a separate workqueue avoids this by keeping
the work completion tasks separate from the other blk-mq work. This
allows the host to be released without getting blocked by other tasks
attempting to claim the host.

Signed-off-by: Zachary Hays <>
Fixes: 81196976ed94 ("mmc: block: Add blk-mq support")
Cc: <>
Signed-off-by: Ulf Hansson <>
Signed-off-by: Greg Kroah-Hartman <>

 drivers/mmc/core/block.c |   10 +++++++++-
 include/linux/mmc/card.h |    1 +
 2 files changed, 10 insertions(+), 1 deletion(-)

--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -2114,7 +2114,7 @@ static void mmc_blk_mq_req_done(struct m
 		if (waiting)
-			kblockd_schedule_work(&mq->complete_work);
+			queue_work(mq->card->complete_wq, &mq->complete_work);
@@ -2928,6 +2928,13 @@ static int mmc_blk_probe(struct mmc_card
 	mmc_fixup_device(card, mmc_blk_fixups);
+	card->complete_wq = alloc_workqueue("mmc_complete",
+	if (unlikely(!card->complete_wq)) {
+		pr_err("Failed to create mmc completion workqueue");
+		return -ENOMEM;
+	}
 	md = mmc_blk_alloc(card);
 	if (IS_ERR(md))
 		return PTR_ERR(md);
@@ -2991,6 +2998,7 @@ static void mmc_blk_remove(struct mmc_ca
 	dev_set_drvdata(&card->dev, NULL);
+	destroy_workqueue(card->complete_wq);
 static int _mmc_blk_suspend(struct mmc_card *card)
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -308,6 +308,7 @@ struct mmc_card {
 	unsigned int    nr_parts;
 	unsigned int		bouncesz;	/* Bounce buffer size */
+	struct workqueue_struct *complete_wq;	/* Private workqueue */
 static inline bool mmc_large_sector(struct mmc_card *card)

Powered by blists - more mailing lists