diff options
-rw-r--r-- | block/blk.h | 4 | ||||
-rw-r--r-- | block/elevator.c | 40 |
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 | ||
71 | int blk_dev_init(void); | 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 | * 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 | */ | ||
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 | void elv_insert(struct request_queue *q, struct request *rq, int where) | 615 | void 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); |