]> err.no Git - linux-2.6/blobdiff - block/ll_rw_blk.c
Merge branch 'master' into upstream
[linux-2.6] / block / ll_rw_blk.c
index e5041a02e21f5c7ee4e93597ef95967643380462..eac48bec14791533a594af0e2909b7ed5347c091 100644 (file)
@@ -1732,8 +1732,21 @@ void blk_run_queue(struct request_queue *q)
 
        spin_lock_irqsave(q->queue_lock, flags);
        blk_remove_plug(q);
-       if (!elv_queue_empty(q))
-               q->request_fn(q);
+
+       /*
+        * Only recurse once to avoid overrunning the stack, let the unplug
+        * handling reinvoke the handler shortly if we already got there.
+        */
+       if (!elv_queue_empty(q)) {
+               if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
+                       q->request_fn(q);
+                       clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags);
+               } else {
+                       blk_plug_device(q);
+                       kblockd_schedule_work(&q->unplug_work);
+               }
+       }
+
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_run_queue);