mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-04 04:06:26 +00:00
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: Jerome Marchand <jmarchan@redhat.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
This commit is contained in:
parent
d508afb437
commit
6c7e8cee6a
@ -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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
|||||||
* 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)
|
|||||||
*/
|
*/
|
||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user