Commit 6c7e8cee authored by Jens Axboe's avatar Jens Axboe

block: elevator quiescing helpers

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: default avatarJerome Marchand <jmarchan@redhat.com>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent d508afb4
...@@ -70,6 +70,10 @@ void blk_queue_congestion_threshold(struct request_queue *q); ...@@ -70,6 +70,10 @@ void blk_queue_congestion_threshold(struct request_queue *q);
int blk_dev_init(void); 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 * Return the threshold (number of used requests) at which the queue is
* considered to be congested. It include a little hysteresis to keep the * considered to be congested. It include a little hysteresis to keep the
......
...@@ -587,6 +587,31 @@ static void elv_drain_elevator(struct request_queue *q) ...@@ -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) void elv_insert(struct request_queue *q, struct request *rq, int where)
{ {
struct list_head *pos; struct list_head *pos;
...@@ -1101,18 +1126,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) ...@@ -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 * Turn on BYPASS and drain all requests w/ elevator private data
*/ */
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
elv_quisce_start(q);
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);
}
/* /*
* Remember old elevator. * Remember old elevator.
...@@ -1136,7 +1150,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) ...@@ -1136,7 +1150,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
*/ */
elevator_exit(old_elevator); elevator_exit(old_elevator);
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); elv_quisce_end(q);
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment