diff options
-rw-r--r-- | block/elevator.c | 90 |
1 files changed, 45 insertions, 45 deletions
diff --git a/block/elevator.c b/block/elevator.c index f016855a46b0..f8c08e1bff2b 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -121,11 +121,10 @@ static struct elevator_type *elevator_get(const char *name) | |||
121 | return e; | 121 | return e; |
122 | } | 122 | } |
123 | 123 | ||
124 | static int elevator_init_queue(struct request_queue *q, | 124 | static int elevator_init_queue(struct request_queue *q) |
125 | struct elevator_queue *eq) | ||
126 | { | 125 | { |
127 | eq->elevator_data = eq->type->ops.elevator_init_fn(q); | 126 | q->elevator->elevator_data = q->elevator->type->ops.elevator_init_fn(q); |
128 | if (eq->elevator_data) | 127 | if (q->elevator->elevator_data) |
129 | return 0; | 128 | return 0; |
130 | return -ENOMEM; | 129 | return -ENOMEM; |
131 | } | 130 | } |
@@ -188,7 +187,6 @@ static void elevator_release(struct kobject *kobj) | |||
188 | int elevator_init(struct request_queue *q, char *name) | 187 | int elevator_init(struct request_queue *q, char *name) |
189 | { | 188 | { |
190 | struct elevator_type *e = NULL; | 189 | struct elevator_type *e = NULL; |
191 | struct elevator_queue *eq; | ||
192 | int err; | 190 | int err; |
193 | 191 | ||
194 | if (unlikely(q->elevator)) | 192 | if (unlikely(q->elevator)) |
@@ -222,17 +220,16 @@ int elevator_init(struct request_queue *q, char *name) | |||
222 | } | 220 | } |
223 | } | 221 | } |
224 | 222 | ||
225 | eq = elevator_alloc(q, e); | 223 | q->elevator = elevator_alloc(q, e); |
226 | if (!eq) | 224 | if (!q->elevator) |
227 | return -ENOMEM; | 225 | return -ENOMEM; |
228 | 226 | ||
229 | err = elevator_init_queue(q, eq); | 227 | err = elevator_init_queue(q); |
230 | if (err) { | 228 | if (err) { |
231 | kobject_put(&eq->kobj); | 229 | kobject_put(&q->elevator->kobj); |
232 | return err; | 230 | return err; |
233 | } | 231 | } |
234 | 232 | ||
235 | q->elevator = eq; | ||
236 | return 0; | 233 | return 0; |
237 | } | 234 | } |
238 | EXPORT_SYMBOL(elevator_init); | 235 | EXPORT_SYMBOL(elevator_init); |
@@ -801,8 +798,9 @@ static struct kobj_type elv_ktype = { | |||
801 | .release = elevator_release, | 798 | .release = elevator_release, |
802 | }; | 799 | }; |
803 | 800 | ||
804 | int __elv_register_queue(struct request_queue *q, struct elevator_queue *e) | 801 | int elv_register_queue(struct request_queue *q) |
805 | { | 802 | { |
803 | struct elevator_queue *e = q->elevator; | ||
806 | int error; | 804 | int error; |
807 | 805 | ||
808 | error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); | 806 | error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); |
@@ -820,11 +818,6 @@ int __elv_register_queue(struct request_queue *q, struct elevator_queue *e) | |||
820 | } | 818 | } |
821 | return error; | 819 | return error; |
822 | } | 820 | } |
823 | |||
824 | int elv_register_queue(struct request_queue *q) | ||
825 | { | ||
826 | return __elv_register_queue(q, q->elevator); | ||
827 | } | ||
828 | EXPORT_SYMBOL(elv_register_queue); | 821 | EXPORT_SYMBOL(elv_register_queue); |
829 | 822 | ||
830 | void elv_unregister_queue(struct request_queue *q) | 823 | void elv_unregister_queue(struct request_queue *q) |
@@ -907,51 +900,58 @@ EXPORT_SYMBOL_GPL(elv_unregister); | |||
907 | */ | 900 | */ |
908 | static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) | 901 | static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) |
909 | { | 902 | { |
910 | struct elevator_queue *old_elevator, *e; | 903 | struct elevator_queue *old = q->elevator; |
904 | bool registered = old->registered; | ||
911 | int err; | 905 | int err; |
912 | 906 | ||
913 | /* allocate new elevator */ | 907 | /* |
914 | e = elevator_alloc(q, new_e); | 908 | * Turn on BYPASS and drain all requests w/ elevator private data. |
915 | if (!e) | 909 | * Block layer doesn't call into a quiesced elevator - all requests |
916 | return -ENOMEM; | 910 | * are directly put on the dispatch list without elevator data |
917 | 911 | * using INSERT_BACK. All requests have SOFTBARRIER set and no | |
918 | err = elevator_init_queue(q, e); | 912 | * merge happens either. |
919 | if (err) { | 913 | */ |
920 | kobject_put(&e->kobj); | ||
921 | return err; | ||
922 | } | ||
923 | |||
924 | /* turn on BYPASS and drain all requests w/ elevator private data */ | ||
925 | elv_quiesce_start(q); | 914 | elv_quiesce_start(q); |
926 | 915 | ||
927 | /* unregister old queue, register new one and kill old elevator */ | 916 | /* unregister and clear all auxiliary data of the old elevator */ |
928 | if (q->elevator->registered) { | 917 | if (registered) |
929 | elv_unregister_queue(q); | 918 | elv_unregister_queue(q); |
930 | err = __elv_register_queue(q, e); | ||
931 | if (err) | ||
932 | goto fail_register; | ||
933 | } | ||
934 | 919 | ||
935 | /* done, clear io_cq's, switch elevators and turn off BYPASS */ | ||
936 | spin_lock_irq(q->queue_lock); | 920 | spin_lock_irq(q->queue_lock); |
937 | ioc_clear_queue(q); | 921 | ioc_clear_queue(q); |
938 | old_elevator = q->elevator; | ||
939 | q->elevator = e; | ||
940 | spin_unlock_irq(q->queue_lock); | 922 | spin_unlock_irq(q->queue_lock); |
941 | 923 | ||
942 | elevator_exit(old_elevator); | 924 | /* allocate, init and register new elevator */ |
925 | err = -ENOMEM; | ||
926 | q->elevator = elevator_alloc(q, new_e); | ||
927 | if (!q->elevator) | ||
928 | goto fail_init; | ||
929 | |||
930 | err = elevator_init_queue(q); | ||
931 | if (err) { | ||
932 | kobject_put(&q->elevator->kobj); | ||
933 | goto fail_init; | ||
934 | } | ||
935 | |||
936 | if (registered) { | ||
937 | err = elv_register_queue(q); | ||
938 | if (err) | ||
939 | goto fail_register; | ||
940 | } | ||
941 | |||
942 | /* done, kill the old one and finish */ | ||
943 | elevator_exit(old); | ||
943 | elv_quiesce_end(q); | 944 | elv_quiesce_end(q); |
944 | 945 | ||
945 | blk_add_trace_msg(q, "elv switch: %s", e->type->elevator_name); | 946 | blk_add_trace_msg(q, "elv switch: %s", new_e->elevator_name); |
946 | 947 | ||
947 | return 0; | 948 | return 0; |
948 | 949 | ||
949 | fail_register: | 950 | fail_register: |
950 | /* | 951 | elevator_exit(q->elevator); |
951 | * switch failed, exit the new io scheduler and reattach the old | 952 | fail_init: |
952 | * one again (along with re-adding the sysfs dir) | 953 | /* switch failed, restore and re-register old elevator */ |
953 | */ | 954 | q->elevator = old; |
954 | elevator_exit(e); | ||
955 | elv_register_queue(q); | 955 | elv_register_queue(q); |
956 | elv_quiesce_end(q); | 956 | elv_quiesce_end(q); |
957 | 957 | ||