aboutsummaryrefslogtreecommitdiffstats
path: root/block/elevator.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/elevator.c')
-rw-r--r--block/elevator.c65
1 files changed, 41 insertions, 24 deletions
diff --git a/block/elevator.c b/block/elevator.c
index 0d6be03d929e..a0afdd317cef 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -121,16 +121,16 @@ static struct elevator_type *elevator_get(const char *name)
121 return e; 121 return e;
122} 122}
123 123
124static int elevator_attach(request_queue_t *q, struct elevator_queue *eq) 124static void *elevator_init_queue(request_queue_t *q, struct elevator_queue *eq)
125{ 125{
126 int ret = 0; 126 return eq->ops->elevator_init_fn(q, eq);
127}
127 128
129static void elevator_attach(request_queue_t *q, struct elevator_queue *eq,
130 void *data)
131{
128 q->elevator = eq; 132 q->elevator = eq;
129 133 eq->elevator_data = data;
130 if (eq->ops->elevator_init_fn)
131 ret = eq->ops->elevator_init_fn(q, eq);
132
133 return ret;
134} 134}
135 135
136static char chosen_elevator[16]; 136static char chosen_elevator[16];
@@ -181,6 +181,7 @@ int elevator_init(request_queue_t *q, char *name)
181 struct elevator_type *e = NULL; 181 struct elevator_type *e = NULL;
182 struct elevator_queue *eq; 182 struct elevator_queue *eq;
183 int ret = 0; 183 int ret = 0;
184 void *data;
184 185
185 INIT_LIST_HEAD(&q->queue_head); 186 INIT_LIST_HEAD(&q->queue_head);
186 q->last_merge = NULL; 187 q->last_merge = NULL;
@@ -202,10 +203,13 @@ int elevator_init(request_queue_t *q, char *name)
202 if (!eq) 203 if (!eq)
203 return -ENOMEM; 204 return -ENOMEM;
204 205
205 ret = elevator_attach(q, eq); 206 data = elevator_init_queue(q, eq);
206 if (ret) 207 if (!data) {
207 kobject_put(&eq->kobj); 208 kobject_put(&eq->kobj);
209 return -ENOMEM;
210 }
208 211
212 elevator_attach(q, eq, data);
209 return ret; 213 return ret;
210} 214}
211 215
@@ -333,6 +337,7 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
333{ 337{
334 struct list_head *pos; 338 struct list_head *pos;
335 unsigned ordseq; 339 unsigned ordseq;
340 int unplug_it = 1;
336 341
337 blk_add_trace_rq(q, rq, BLK_TA_INSERT); 342 blk_add_trace_rq(q, rq, BLK_TA_INSERT);
338 343
@@ -399,6 +404,11 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
399 } 404 }
400 405
401 list_add_tail(&rq->queuelist, pos); 406 list_add_tail(&rq->queuelist, pos);
407 /*
408 * most requeues happen because of a busy condition, don't
409 * force unplug of the queue for that case.
410 */
411 unplug_it = 0;
402 break; 412 break;
403 413
404 default: 414 default:
@@ -407,7 +417,7 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
407 BUG(); 417 BUG();
408 } 418 }
409 419
410 if (blk_queue_plugged(q)) { 420 if (unplug_it && blk_queue_plugged(q)) {
411 int nrq = q->rq.count[READ] + q->rq.count[WRITE] 421 int nrq = q->rq.count[READ] + q->rq.count[WRITE]
412 - q->in_flight; 422 - q->in_flight;
413 423
@@ -716,13 +726,16 @@ int elv_register_queue(struct request_queue *q)
716 return error; 726 return error;
717} 727}
718 728
729static void __elv_unregister_queue(elevator_t *e)
730{
731 kobject_uevent(&e->kobj, KOBJ_REMOVE);
732 kobject_del(&e->kobj);
733}
734
719void elv_unregister_queue(struct request_queue *q) 735void elv_unregister_queue(struct request_queue *q)
720{ 736{
721 if (q) { 737 if (q)
722 elevator_t *e = q->elevator; 738 __elv_unregister_queue(q->elevator);
723 kobject_uevent(&e->kobj, KOBJ_REMOVE);
724 kobject_del(&e->kobj);
725 }
726} 739}
727 740
728int elv_register(struct elevator_type *e) 741int elv_register(struct elevator_type *e)
@@ -774,6 +787,7 @@ EXPORT_SYMBOL_GPL(elv_unregister);
774static int elevator_switch(request_queue_t *q, struct elevator_type *new_e) 787static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
775{ 788{
776 elevator_t *old_elevator, *e; 789 elevator_t *old_elevator, *e;
790 void *data;
777 791
778 /* 792 /*
779 * Allocate new elevator 793 * Allocate new elevator
@@ -782,6 +796,12 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
782 if (!e) 796 if (!e)
783 return 0; 797 return 0;
784 798
799 data = elevator_init_queue(q, e);
800 if (!data) {
801 kobject_put(&e->kobj);
802 return 0;
803 }
804
785 /* 805 /*
786 * Turn on BYPASS and drain all requests w/ elevator private data 806 * Turn on BYPASS and drain all requests w/ elevator private data
787 */ 807 */
@@ -800,19 +820,19 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
800 elv_drain_elevator(q); 820 elv_drain_elevator(q);
801 } 821 }
802 822
803 spin_unlock_irq(q->queue_lock);
804
805 /* 823 /*
806 * unregister old elevator data 824 * Remember old elevator.
807 */ 825 */
808 elv_unregister_queue(q);
809 old_elevator = q->elevator; 826 old_elevator = q->elevator;
810 827
811 /* 828 /*
812 * attach and start new elevator 829 * attach and start new elevator
813 */ 830 */
814 if (elevator_attach(q, e)) 831 elevator_attach(q, e, data);
815 goto fail; 832
833 spin_unlock_irq(q->queue_lock);
834
835 __elv_unregister_queue(old_elevator);
816 836
817 if (elv_register_queue(q)) 837 if (elv_register_queue(q))
818 goto fail_register; 838 goto fail_register;
@@ -831,7 +851,6 @@ fail_register:
831 */ 851 */
832 elevator_exit(e); 852 elevator_exit(e);
833 e = NULL; 853 e = NULL;
834fail:
835 q->elevator = old_elevator; 854 q->elevator = old_elevator;
836 elv_register_queue(q); 855 elv_register_queue(q);
837 clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); 856 clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
@@ -895,10 +914,8 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
895EXPORT_SYMBOL(elv_dispatch_sort); 914EXPORT_SYMBOL(elv_dispatch_sort);
896EXPORT_SYMBOL(elv_add_request); 915EXPORT_SYMBOL(elv_add_request);
897EXPORT_SYMBOL(__elv_add_request); 916EXPORT_SYMBOL(__elv_add_request);
898EXPORT_SYMBOL(elv_requeue_request);
899EXPORT_SYMBOL(elv_next_request); 917EXPORT_SYMBOL(elv_next_request);
900EXPORT_SYMBOL(elv_dequeue_request); 918EXPORT_SYMBOL(elv_dequeue_request);
901EXPORT_SYMBOL(elv_queue_empty); 919EXPORT_SYMBOL(elv_queue_empty);
902EXPORT_SYMBOL(elv_completed_request);
903EXPORT_SYMBOL(elevator_exit); 920EXPORT_SYMBOL(elevator_exit);
904EXPORT_SYMBOL(elevator_init); 921EXPORT_SYMBOL(elevator_init);