aboutsummaryrefslogtreecommitdiffstats
path: root/block/elevator.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-10-19 08:32:38 -0400
committerJens Axboe <axboe@kernel.dk>2011-10-19 08:32:38 -0400
commite3c78ca524d230bc145e902625e88c392a58ddf3 (patch)
tree833eb544dd4180fd626f60da17788aae7830f4dc /block/elevator.c
parent315fceee81155ef2aeed9316ca72aeea9347db5c (diff)
block: reorganize queue draining
Reorganize queue draining related code in preparation of queue exit changes. * Factor out actual draining from elv_quiesce_start() to blk_drain_queue(). * Make elv_quiesce_start/end() responsible for their own locking. * Replace open-coded ELVSWITCH clearing in elevator_switch() with elv_quiesce_end(). This patch doesn't cause any visible functional difference. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/elevator.c')
-rw-r--r--block/elevator.c37
1 files changed, 11 insertions, 26 deletions
diff --git a/block/elevator.c b/block/elevator.c
index cb332cb7ac6b..74a277ffed39 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -31,7 +31,6 @@
31#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/init.h> 32#include <linux/init.h>
33#include <linux/compiler.h> 33#include <linux/compiler.h>
34#include <linux/delay.h>
35#include <linux/blktrace_api.h> 34#include <linux/blktrace_api.h>
36#include <linux/hash.h> 35#include <linux/hash.h>
37#include <linux/uaccess.h> 36#include <linux/uaccess.h>
@@ -606,43 +605,35 @@ void elv_requeue_request(struct request_queue *q, struct request *rq)
606void elv_drain_elevator(struct request_queue *q) 605void elv_drain_elevator(struct request_queue *q)
607{ 606{
608 static int printed; 607 static int printed;
608
609 lockdep_assert_held(q->queue_lock);
610
609 while (q->elevator->ops->elevator_dispatch_fn(q, 1)) 611 while (q->elevator->ops->elevator_dispatch_fn(q, 1))
610 ; 612 ;
611 if (q->nr_sorted == 0) 613 if (q->nr_sorted && printed++ < 10) {
612 return;
613 if (printed++ < 10) {
614 printk(KERN_ERR "%s: forced dispatching is broken " 614 printk(KERN_ERR "%s: forced dispatching is broken "
615 "(nr_sorted=%u), please report this\n", 615 "(nr_sorted=%u), please report this\n",
616 q->elevator->elevator_type->elevator_name, q->nr_sorted); 616 q->elevator->elevator_type->elevator_name, q->nr_sorted);
617 } 617 }
618} 618}
619 619
620/*
621 * Call with queue lock held, interrupts disabled
622 */
623void elv_quiesce_start(struct request_queue *q) 620void elv_quiesce_start(struct request_queue *q)
624{ 621{
625 if (!q->elevator) 622 if (!q->elevator)
626 return; 623 return;
627 624
625 spin_lock_irq(q->queue_lock);
628 queue_flag_set(QUEUE_FLAG_ELVSWITCH, q); 626 queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
627 spin_unlock_irq(q->queue_lock);
629 628
630 /* 629 blk_drain_queue(q);
631 * make sure we don't have any requests in flight
632 */
633 elv_drain_elevator(q);
634 while (q->rq.elvpriv) {
635 __blk_run_queue(q);
636 spin_unlock_irq(q->queue_lock);
637 msleep(10);
638 spin_lock_irq(q->queue_lock);
639 elv_drain_elevator(q);
640 }
641} 630}
642 631
643void elv_quiesce_end(struct request_queue *q) 632void elv_quiesce_end(struct request_queue *q)
644{ 633{
634 spin_lock_irq(q->queue_lock);
645 queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); 635 queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
636 spin_unlock_irq(q->queue_lock);
646} 637}
647 638
648void __elv_add_request(struct request_queue *q, struct request *rq, int where) 639void __elv_add_request(struct request_queue *q, struct request *rq, int where)
@@ -972,7 +963,6 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
972 /* 963 /*
973 * Turn on BYPASS and drain all requests w/ elevator private data 964 * Turn on BYPASS and drain all requests w/ elevator private data
974 */ 965 */
975 spin_lock_irq(q->queue_lock);
976 elv_quiesce_start(q); 966 elv_quiesce_start(q);
977 967
978 /* 968 /*
@@ -983,8 +973,8 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
983 /* 973 /*
984 * attach and start new elevator 974 * attach and start new elevator
985 */ 975 */
976 spin_lock_irq(q->queue_lock);
986 elevator_attach(q, e, data); 977 elevator_attach(q, e, data);
987
988 spin_unlock_irq(q->queue_lock); 978 spin_unlock_irq(q->queue_lock);
989 979
990 if (old_elevator->registered) { 980 if (old_elevator->registered) {
@@ -999,9 +989,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
999 * finally exit old elevator and turn off BYPASS. 989 * finally exit old elevator and turn off BYPASS.
1000 */ 990 */
1001 elevator_exit(old_elevator); 991 elevator_exit(old_elevator);
1002 spin_lock_irq(q->queue_lock);
1003 elv_quiesce_end(q); 992 elv_quiesce_end(q);
1004 spin_unlock_irq(q->queue_lock);
1005 993
1006 blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); 994 blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
1007 995
@@ -1015,10 +1003,7 @@ fail_register:
1015 elevator_exit(e); 1003 elevator_exit(e);
1016 q->elevator = old_elevator; 1004 q->elevator = old_elevator;
1017 elv_register_queue(q); 1005 elv_register_queue(q);
1018 1006 elv_quiesce_end(q);
1019 spin_lock_irq(q->queue_lock);
1020 queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
1021 spin_unlock_irq(q->queue_lock);
1022 1007
1023 return err; 1008 return err;
1024} 1009}