]> git.hungrycats.org Git - linux/commitdiff
[PATCH] fix blk_start_queue()
authorJens Axboe <axboe@suse.de>
Mon, 8 Mar 2004 04:29:23 +0000 (20:29 -0800)
committerJens Axboe <axboe@suse.de>
Mon, 8 Mar 2004 04:29:23 +0000 (20:29 -0800)
Here's the second attempt at fixing blk_start_queue().  The only change
since last version is using proper atomic bitops.  If we moved the
read/write full to a different variable, we could rely on the queue lock
for plugging and stop/start of queue (by far the most used bit
operations there) and skip the atomic bitops.

drivers/block/ll_rw_blk.c

index b5f085c28ec976c3783e26b0e4f3fded8cd628fa..9e8b6e35b213b7c608871a2b480d6f5730d20c24 100644 (file)
@@ -1188,13 +1188,23 @@ static void blk_unplug_timeout(unsigned long data)
  * Description:
  *   blk_start_queue() will clear the stop flag on the queue, and call
  *   the request_fn for the queue if it was in a stopped state when
- *   entered. Also see blk_stop_queue(). Must not be called from driver
- *   request function due to recursion issues. Queue lock must be held.
+ *   entered. Also see blk_stop_queue(). Queue lock must be held.
  **/
 void blk_start_queue(request_queue_t *q)
 {
        clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
-       schedule_work(&q->unplug_work);
+
+       /*
+        * one level of recursion is ok and is much faster than kicking
+        * the unplug handling
+        */
+       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);
+               schedule_work(&q->unplug_work);
+       }
 }
 
 EXPORT_SYMBOL(blk_start_queue);