Commit 6c7e8cee6a9128eeb7f83c3ad1cb243f77f5cb16
1 parent
d508afb437
Exists in
master
and in
20 other branches
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>
Showing 2 changed files with 31 additions and 13 deletions Side-by-side Diff
block/blk.h
... | ... | @@ -70,6 +70,10 @@ |
70 | 70 | |
71 | 71 | int blk_dev_init(void); |
72 | 72 | |
73 | +void elv_quisce_start(struct request_queue *q); | |
74 | +void elv_quisce_end(struct request_queue *q); | |
75 | + | |
76 | + | |
73 | 77 | /* |
74 | 78 | * Return the threshold (number of used requests) at which the queue is |
75 | 79 | * considered to be congested. It include a little hysteresis to keep the |
block/elevator.c
... | ... | @@ -587,6 +587,31 @@ |
587 | 587 | } |
588 | 588 | } |
589 | 589 | |
590 | +/* | |
591 | + * Call with queue lock held, interrupts disabled | |
592 | + */ | |
593 | +void elv_quisce_start(struct request_queue *q) | |
594 | +{ | |
595 | + queue_flag_set(QUEUE_FLAG_ELVSWITCH, q); | |
596 | + | |
597 | + /* | |
598 | + * make sure we don't have any requests in flight | |
599 | + */ | |
600 | + elv_drain_elevator(q); | |
601 | + while (q->rq.elvpriv) { | |
602 | + blk_start_queueing(q); | |
603 | + spin_unlock_irq(q->queue_lock); | |
604 | + msleep(10); | |
605 | + spin_lock_irq(q->queue_lock); | |
606 | + elv_drain_elevator(q); | |
607 | + } | |
608 | +} | |
609 | + | |
610 | +void elv_quisce_end(struct request_queue *q) | |
611 | +{ | |
612 | + queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); | |
613 | +} | |
614 | + | |
590 | 615 | void elv_insert(struct request_queue *q, struct request *rq, int where) |
591 | 616 | { |
592 | 617 | struct list_head *pos; |
593 | 618 | |
... | ... | @@ -1101,19 +1126,8 @@ |
1101 | 1126 | * Turn on BYPASS and drain all requests w/ elevator private data |
1102 | 1127 | */ |
1103 | 1128 | spin_lock_irq(q->queue_lock); |
1129 | + elv_quisce_start(q); | |
1104 | 1130 | |
1105 | - queue_flag_set(QUEUE_FLAG_ELVSWITCH, q); | |
1106 | - | |
1107 | - elv_drain_elevator(q); | |
1108 | - | |
1109 | - while (q->rq.elvpriv) { | |
1110 | - blk_start_queueing(q); | |
1111 | - spin_unlock_irq(q->queue_lock); | |
1112 | - msleep(10); | |
1113 | - spin_lock_irq(q->queue_lock); | |
1114 | - elv_drain_elevator(q); | |
1115 | - } | |
1116 | - | |
1117 | 1131 | /* |
1118 | 1132 | * Remember old elevator. |
1119 | 1133 | */ |
... | ... | @@ -1136,7 +1150,7 @@ |
1136 | 1150 | */ |
1137 | 1151 | elevator_exit(old_elevator); |
1138 | 1152 | spin_lock_irq(q->queue_lock); |
1139 | - queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); | |
1153 | + elv_quisce_end(q); | |
1140 | 1154 | spin_unlock_irq(q->queue_lock); |
1141 | 1155 | |
1142 | 1156 | blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); |