summaryrefslogtreecommitdiffstats
path: root/block/blk-ioc.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2017-03-17 20:34:30 +0100
committerThomas Gleixner <tglx@linutronix.de>2017-03-17 20:34:30 +0100
commit79a21d572cf66968a2272fdf9711f835518256d9 (patch)
tree5fe3e4692fb8375faf8e1aeea1c2eae38c342250 /block/blk-ioc.c
parentefi/arm: Fix boot crash with CONFIG_CPUMASK_OFFSTACK=y (diff)
parentefi/esrt: Cleanup bad memory map log messages (diff)
downloadlinux-79a21d572cf66968a2272fdf9711f835518256d9.tar.xz
linux-79a21d572cf66968a2272fdf9711f835518256d9.zip
Merge tag 'efi-urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi into efi/urgent
Pull a single UEFI fix from Ard: - Reduce the severity of the notice that appears when the ESRT table points to memory that is not covered by the memory map. It is scaring our users and interfering with their nice splash screens. Note that the ESRT may still be perfectly usable, and is currently (to my knowledge) not widely used to begin with.
Diffstat (limited to 'block/blk-ioc.c')
-rw-r--r--block/blk-ioc.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index b12f9c87b4c3..63898d229cb9 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -7,6 +7,7 @@
#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/slab.h>
+#include <linux/sched/task.h>
#include "blk.h"
@@ -36,8 +37,8 @@ static void icq_free_icq_rcu(struct rcu_head *head)
}
/*
- * Exit an icq. Called with both ioc and q locked for sq, only ioc locked for
- * mq.
+ * Exit an icq. Called with ioc locked for blk-mq, and with both ioc
+ * and queue locked for legacy.
*/
static void ioc_exit_icq(struct io_cq *icq)
{
@@ -54,7 +55,10 @@ static void ioc_exit_icq(struct io_cq *icq)
icq->flags |= ICQ_EXITED;
}
-/* Release an icq. Called with both ioc and q locked. */
+/*
+ * Release an icq. Called with ioc locked for blk-mq, and with both ioc
+ * and queue locked for legacy.
+ */
static void ioc_destroy_icq(struct io_cq *icq)
{
struct io_context *ioc = icq->ioc;
@@ -62,7 +66,6 @@ static void ioc_destroy_icq(struct io_cq *icq)
struct elevator_type *et = q->elevator->type;
lockdep_assert_held(&ioc->lock);
- lockdep_assert_held(q->queue_lock);
radix_tree_delete(&ioc->icq_tree, icq->q->id);
hlist_del_init(&icq->ioc_node);
@@ -222,24 +225,40 @@ void exit_io_context(struct task_struct *task)
put_io_context_active(ioc);
}
+static void __ioc_clear_queue(struct list_head *icq_list)
+{
+ unsigned long flags;
+
+ while (!list_empty(icq_list)) {
+ struct io_cq *icq = list_entry(icq_list->next,
+ struct io_cq, q_node);
+ struct io_context *ioc = icq->ioc;
+
+ spin_lock_irqsave(&ioc->lock, flags);
+ ioc_destroy_icq(icq);
+ spin_unlock_irqrestore(&ioc->lock, flags);
+ }
+}
+
/**
* ioc_clear_queue - break any ioc association with the specified queue
* @q: request_queue being cleared
*
- * Walk @q->icq_list and exit all io_cq's. Must be called with @q locked.
+ * Walk @q->icq_list and exit all io_cq's.
*/
void ioc_clear_queue(struct request_queue *q)
{
- lockdep_assert_held(q->queue_lock);
+ LIST_HEAD(icq_list);
- while (!list_empty(&q->icq_list)) {
- struct io_cq *icq = list_entry(q->icq_list.next,
- struct io_cq, q_node);
- struct io_context *ioc = icq->ioc;
+ spin_lock_irq(q->queue_lock);
+ list_splice_init(&q->icq_list, &icq_list);
- spin_lock(&ioc->lock);
- ioc_destroy_icq(icq);
- spin_unlock(&ioc->lock);
+ if (q->mq_ops) {
+ spin_unlock_irq(q->queue_lock);
+ __ioc_clear_queue(&icq_list);
+ } else {
+ __ioc_clear_queue(&icq_list);
+ spin_unlock_irq(q->queue_lock);
}
}