Skip to content

Commit

Permalink
block: elevator quiescing helpers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jens Axboe committed Apr 7, 2009
1 parent d508afb commit 6c7e8ce
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 13 deletions.
4 changes: 4 additions & 0 deletions block/blk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 27 additions & 13 deletions block/elevator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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);
Expand Down

0 comments on commit 6c7e8ce

Please sign in to comment.