aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/elevator.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-10-28 11:56:34 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-28 11:56:34 -0400
commit5dd962494f76fb3ef1196cd420b5d6260d7a3766 (patch)
treef6eda4fcea880e420420a2886b84ad35a6b00f28 /drivers/block/elevator.c
parent28d721e24c88496ff8e9c4a0959bdc1415c0658e (diff)
parent772eca7825358f52cf208afd7ab8ce22722ce41a (diff)
Merge branch 'elevator-switch' of git://brick.kernel.dk/data/git/linux-2.6-block
Manual fixup for trivial "gfp_t" changes.
Diffstat (limited to 'drivers/block/elevator.c')
-rw-r--r--drivers/block/elevator.c77
1 files changed, 34 insertions, 43 deletions
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 3b8099ccedff..55621d5c5774 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -34,6 +34,7 @@
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/init.h> 35#include <linux/init.h>
36#include <linux/compiler.h> 36#include <linux/compiler.h>
37#include <linux/delay.h>
37 38
38#include <asm/uaccess.h> 39#include <asm/uaccess.h>
39 40
@@ -131,11 +132,7 @@ static int elevator_attach(request_queue_t *q, struct elevator_type *e,
131 eq->ops = &e->ops; 132 eq->ops = &e->ops;
132 eq->elevator_type = e; 133 eq->elevator_type = e;
133 134
134 INIT_LIST_HEAD(&q->queue_head);
135 q->last_merge = NULL;
136 q->elevator = eq; 135 q->elevator = eq;
137 q->end_sector = 0;
138 q->boundary_rq = NULL;
139 136
140 if (eq->ops->elevator_init_fn) 137 if (eq->ops->elevator_init_fn)
141 ret = eq->ops->elevator_init_fn(q, eq); 138 ret = eq->ops->elevator_init_fn(q, eq);
@@ -184,6 +181,11 @@ int elevator_init(request_queue_t *q, char *name)
184 struct elevator_queue *eq; 181 struct elevator_queue *eq;
185 int ret = 0; 182 int ret = 0;
186 183
184 INIT_LIST_HEAD(&q->queue_head);
185 q->last_merge = NULL;
186 q->end_sector = 0;
187 q->boundary_rq = NULL;
188
187 elevator_setup_default(); 189 elevator_setup_default();
188 190
189 if (!name) 191 if (!name)
@@ -336,23 +338,14 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
336 q->end_sector = rq_end_sector(rq); 338 q->end_sector = rq_end_sector(rq);
337 q->boundary_rq = rq; 339 q->boundary_rq = rq;
338 } 340 }
339 } 341 } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
342 where = ELEVATOR_INSERT_BACK;
340 343
341 if (plug) 344 if (plug)
342 blk_plug_device(q); 345 blk_plug_device(q);
343 346
344 rq->q = q; 347 rq->q = q;
345 348
346 if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) {
347 /*
348 * if drain is set, store the request "locally". when the drain
349 * is finished, the requests will be handed ordered to the io
350 * scheduler
351 */
352 list_add_tail(&rq->queuelist, &q->drain_list);
353 return;
354 }
355
356 switch (where) { 349 switch (where) {
357 case ELEVATOR_INSERT_FRONT: 350 case ELEVATOR_INSERT_FRONT:
358 rq->flags |= REQ_SOFTBARRIER; 351 rq->flags |= REQ_SOFTBARRIER;
@@ -659,25 +652,36 @@ EXPORT_SYMBOL_GPL(elv_unregister);
659 * switch to new_e io scheduler. be careful not to introduce deadlocks - 652 * switch to new_e io scheduler. be careful not to introduce deadlocks -
660 * we don't free the old io scheduler, before we have allocated what we 653 * we don't free the old io scheduler, before we have allocated what we
661 * need for the new one. this way we have a chance of going back to the old 654 * need for the new one. this way we have a chance of going back to the old
662 * one, if the new one fails init for some reason. we also do an intermediate 655 * one, if the new one fails init for some reason.
663 * switch to noop to ensure safety with stack-allocated requests, since they
664 * don't originate from the block layer allocator. noop is safe here, because
665 * it never needs to touch the elevator itself for completion events. DRAIN
666 * flags will make sure we don't touch it for additions either.
667 */ 656 */
668static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) 657static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
669{ 658{
670 elevator_t *e = kmalloc(sizeof(elevator_t), GFP_KERNEL); 659 elevator_t *old_elevator, *e;
671 struct elevator_type *noop_elevator = NULL;
672 elevator_t *old_elevator;
673 660
661 /*
662 * Allocate new elevator
663 */
664 e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
674 if (!e) 665 if (!e)
675 goto error; 666 goto error;
676 667
677 /* 668 /*
678 * first step, drain requests from the block freelist 669 * Turn on BYPASS and drain all requests w/ elevator private data
679 */ 670 */
680 blk_wait_queue_drained(q, 0); 671 spin_lock_irq(q->queue_lock);
672
673 set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
674
675 while (q->elevator->ops->elevator_dispatch_fn(q, 1))
676 ;
677
678 while (q->rq.elvpriv) {
679 spin_unlock_irq(q->queue_lock);
680 msleep(10);
681 spin_lock_irq(q->queue_lock);
682 }
683
684 spin_unlock_irq(q->queue_lock);
681 685
682 /* 686 /*
683 * unregister old elevator data 687 * unregister old elevator data
@@ -686,18 +690,6 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
686 old_elevator = q->elevator; 690 old_elevator = q->elevator;
687 691
688 /* 692 /*
689 * next step, switch to noop since it uses no private rq structures
690 * and doesn't allocate any memory for anything. then wait for any
691 * non-fs requests in-flight
692 */
693 noop_elevator = elevator_get("noop");
694 spin_lock_irq(q->queue_lock);
695 elevator_attach(q, noop_elevator, e);
696 spin_unlock_irq(q->queue_lock);
697
698 blk_wait_queue_drained(q, 1);
699
700 /*
701 * attach and start new elevator 693 * attach and start new elevator
702 */ 694 */
703 if (elevator_attach(q, new_e, e)) 695 if (elevator_attach(q, new_e, e))
@@ -707,11 +699,10 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
707 goto fail_register; 699 goto fail_register;
708 700
709 /* 701 /*
710 * finally exit old elevator and start queue again 702 * finally exit old elevator and turn off BYPASS.
711 */ 703 */
712 elevator_exit(old_elevator); 704 elevator_exit(old_elevator);
713 blk_finish_queue_drain(q); 705 clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
714 elevator_put(noop_elevator);
715 return; 706 return;
716 707
717fail_register: 708fail_register:
@@ -720,13 +711,13 @@ fail_register:
720 * one again (along with re-adding the sysfs dir) 711 * one again (along with re-adding the sysfs dir)
721 */ 712 */
722 elevator_exit(e); 713 elevator_exit(e);
714 e = NULL;
723fail: 715fail:
724 q->elevator = old_elevator; 716 q->elevator = old_elevator;
725 elv_register_queue(q); 717 elv_register_queue(q);
726 blk_finish_queue_drain(q); 718 clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
719 kfree(e);
727error: 720error:
728 if (noop_elevator)
729 elevator_put(noop_elevator);
730 elevator_put(new_e); 721 elevator_put(new_e);
731 printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name); 722 printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name);
732} 723}