aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-ioc.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index fe186a9eade9..b12f9c87b4c3 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -35,7 +35,10 @@ static void icq_free_icq_rcu(struct rcu_head *head)
35 kmem_cache_free(icq->__rcu_icq_cache, icq); 35 kmem_cache_free(icq->__rcu_icq_cache, icq);
36} 36}
37 37
38/* Exit an icq. Called with both ioc and q locked. */ 38/*
39 * Exit an icq. Called with both ioc and q locked for sq, only ioc locked for
40 * mq.
41 */
39static void ioc_exit_icq(struct io_cq *icq) 42static void ioc_exit_icq(struct io_cq *icq)
40{ 43{
41 struct elevator_type *et = icq->q->elevator->type; 44 struct elevator_type *et = icq->q->elevator->type;
@@ -166,6 +169,7 @@ EXPORT_SYMBOL(put_io_context);
166 */ 169 */
167void put_io_context_active(struct io_context *ioc) 170void put_io_context_active(struct io_context *ioc)
168{ 171{
172 struct elevator_type *et;
169 unsigned long flags; 173 unsigned long flags;
170 struct io_cq *icq; 174 struct io_cq *icq;
171 175
@@ -184,13 +188,19 @@ retry:
184 hlist_for_each_entry(icq, &ioc->icq_list, ioc_node) { 188 hlist_for_each_entry(icq, &ioc->icq_list, ioc_node) {
185 if (icq->flags & ICQ_EXITED) 189 if (icq->flags & ICQ_EXITED)
186 continue; 190 continue;
187 if (spin_trylock(icq->q->queue_lock)) { 191
192 et = icq->q->elevator->type;
193 if (et->uses_mq) {
188 ioc_exit_icq(icq); 194 ioc_exit_icq(icq);
189 spin_unlock(icq->q->queue_lock);
190 } else { 195 } else {
191 spin_unlock_irqrestore(&ioc->lock, flags); 196 if (spin_trylock(icq->q->queue_lock)) {
192 cpu_relax(); 197 ioc_exit_icq(icq);
193 goto retry; 198 spin_unlock(icq->q->queue_lock);
199 } else {
200 spin_unlock_irqrestore(&ioc->lock, flags);
201 cpu_relax();
202 goto retry;
203 }
194 } 204 }
195 } 205 }
196 spin_unlock_irqrestore(&ioc->lock, flags); 206 spin_unlock_irqrestore(&ioc->lock, flags);