block: elevator quiescing helpers
authorJens Axboe <jens.axboe@oracle.com>
Fri, 27 Mar 2009 09:30:47 +0000 (10:30 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 7 Apr 2009 06:12:37 +0000 (08:12 +0200)
Simple helper functions to quiesce the request queue. These are
currently only used for switching IO schedulers on-the-fly, but
we can use them to properly switch IO accounting on and off as well.

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
block/blk.h
block/elevator.c

index 3ee94358b43d0ba8d1194daaac7d34534e87bfa5..22043c2886c70acbd14ef6121cf0047b33557360 100644 (file)
@@ -70,6 +70,10 @@ void blk_queue_congestion_threshold(struct request_queue *q);
 
 int blk_dev_init(void);
 
+void elv_quisce_start(struct request_queue *q);
+void elv_quisce_end(struct request_queue *q);
+
+
 /*
  * Return the threshold (number of used requests) at which the queue is
  * considered to be congested.  It include a little hysteresis to keep the
index ca6788a0195ac6d3e117009dcaecb7dd952c593c..c6744913ff4aa35a56c1edc7367411a66a8c5d4c 100644 (file)
@@ -587,6 +587,31 @@ static void elv_drain_elevator(struct request_queue *q)
        }
 }
 
+/*
+ * Call with queue lock held, interrupts disabled
+ */
+void elv_quisce_start(struct request_queue *q)
+{
+       queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
+
+       /*
+        * make sure we don't have any requests in flight
+        */
+       elv_drain_elevator(q);
+       while (q->rq.elvpriv) {
+               blk_start_queueing(q);
+               spin_unlock_irq(q->queue_lock);
+               msleep(10);
+               spin_lock_irq(q->queue_lock);
+               elv_drain_elevator(q);
+       }
+}
+
+void elv_quisce_end(struct request_queue *q)
+{
+       queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
+}
+
 void elv_insert(struct request_queue *q, struct request *rq, int where)
 {
        struct list_head *pos;
@@ -1101,18 +1126,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
         * Turn on BYPASS and drain all requests w/ elevator private data
         */
        spin_lock_irq(q->queue_lock);
-
-       queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
-
-       elv_drain_elevator(q);
-
-       while (q->rq.elvpriv) {
-               blk_start_queueing(q);
-               spin_unlock_irq(q->queue_lock);
-               msleep(10);
-               spin_lock_irq(q->queue_lock);
-               elv_drain_elevator(q);
-       }
+       elv_quisce_start(q);
 
        /*
         * Remember old elevator.
@@ -1136,7 +1150,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
         */
        elevator_exit(old_elevator);
        spin_lock_irq(q->queue_lock);
-       queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
+       elv_quisce_end(q);
        spin_unlock_irq(q->queue_lock);
 
        blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);