aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk.h4
-rw-r--r--block/elevator.c40
2 files changed, 31 insertions, 13 deletions
diff --git a/block/blk.h b/block/blk.h
index 3ee94358b43d..22043c2886c7 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -70,6 +70,10 @@ void blk_queue_congestion_threshold(struct request_queue *q);
70 70
71int blk_dev_init(void); 71int blk_dev_init(void);
72 72
73void elv_quisce_start(struct request_queue *q);
74void elv_quisce_end(struct request_queue *q);
75
76
73/* 77/*
74 * Return the threshold (number of used requests) at which the queue is 78 * Return the threshold (number of used requests) at which the queue is
75 * considered to be congested. It include a little hysteresis to keep the 79 * considered to be congested. It include a little hysteresis to keep the
diff --git a/block/elevator.c b/block/elevator.c
index ca6788a0195a..c6744913ff4a 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -587,6 +587,31 @@ static void elv_drain_elevator(struct request_queue *q)
587 } 587 }
588} 588}
589 589
590/*
591 * Call with queue lock held, interrupts disabled
592 */
593void 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
610void elv_quisce_end(struct request_queue *q)
611{
612 queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
613}
614
590void elv_insert(struct request_queue *q, struct request *rq, int where) 615void elv_insert(struct request_queue *q, struct request *rq, int where)
591{ 616{
592 struct list_head *pos; 617 struct list_head *pos;
@@ -1101,18 +1126,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
1101 * Turn on BYPASS and drain all requests w/ elevator private data 1126 * Turn on BYPASS and drain all requests w/ elevator private data
1102 */ 1127 */
1103 spin_lock_irq(q->queue_lock); 1128 spin_lock_irq(q->queue_lock);
1104 1129 elv_quisce_start(q);
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 1130
1117 /* 1131 /*
1118 * Remember old elevator. 1132 * Remember old elevator.
@@ -1136,7 +1150,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
1136 */ 1150 */
1137 elevator_exit(old_elevator); 1151 elevator_exit(old_elevator);
1138 spin_lock_irq(q->queue_lock); 1152 spin_lock_irq(q->queue_lock);
1139 queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); 1153 elv_quisce_end(q);
1140 spin_unlock_irq(q->queue_lock); 1154 spin_unlock_irq(q->queue_lock);
1141 1155
1142 blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); 1156 blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);