aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/elevator.c91
1 files changed, 37 insertions, 54 deletions
diff --git a/block/elevator.c b/block/elevator.c
index 6a343e8f8319..a16c2d1713e5 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -168,17 +168,13 @@ static struct elevator_type *elevator_get(const char *name)
168 return e; 168 return e;
169} 169}
170 170
171static void *elevator_init_queue(struct request_queue *q, 171static int elevator_init_queue(struct request_queue *q,
172 struct elevator_queue *eq) 172 struct elevator_queue *eq)
173{ 173{
174 return eq->ops->elevator_init_fn(q); 174 eq->elevator_data = eq->ops->elevator_init_fn(q);
175} 175 if (eq->elevator_data)
176 176 return 0;
177static void elevator_attach(struct request_queue *q, struct elevator_queue *eq, 177 return -ENOMEM;
178 void *data)
179{
180 q->elevator = eq;
181 eq->elevator_data = data;
182} 178}
183 179
184static char chosen_elevator[ELV_NAME_MAX]; 180static char chosen_elevator[ELV_NAME_MAX];
@@ -241,7 +237,7 @@ int elevator_init(struct request_queue *q, char *name)
241{ 237{
242 struct elevator_type *e = NULL; 238 struct elevator_type *e = NULL;
243 struct elevator_queue *eq; 239 struct elevator_queue *eq;
244 void *data; 240 int err;
245 241
246 if (unlikely(q->elevator)) 242 if (unlikely(q->elevator))
247 return 0; 243 return 0;
@@ -278,13 +274,13 @@ int elevator_init(struct request_queue *q, char *name)
278 if (!eq) 274 if (!eq)
279 return -ENOMEM; 275 return -ENOMEM;
280 276
281 data = elevator_init_queue(q, eq); 277 err = elevator_init_queue(q, eq);
282 if (!data) { 278 if (err) {
283 kobject_put(&eq->kobj); 279 kobject_put(&eq->kobj);
284 return -ENOMEM; 280 return err;
285 } 281 }
286 282
287 elevator_attach(q, eq, data); 283 q->elevator = eq;
288 return 0; 284 return 0;
289} 285}
290EXPORT_SYMBOL(elevator_init); 286EXPORT_SYMBOL(elevator_init);
@@ -856,9 +852,8 @@ static struct kobj_type elv_ktype = {
856 .release = elevator_release, 852 .release = elevator_release,
857}; 853};
858 854
859int elv_register_queue(struct request_queue *q) 855int __elv_register_queue(struct request_queue *q, struct elevator_queue *e)
860{ 856{
861 struct elevator_queue *e = q->elevator;
862 int error; 857 int error;
863 858
864 error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); 859 error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched");
@@ -876,19 +871,22 @@ int elv_register_queue(struct request_queue *q)
876 } 871 }
877 return error; 872 return error;
878} 873}
879EXPORT_SYMBOL(elv_register_queue);
880 874
881static void __elv_unregister_queue(struct elevator_queue *e) 875int elv_register_queue(struct request_queue *q)
882{ 876{
883 kobject_uevent(&e->kobj, KOBJ_REMOVE); 877 return __elv_register_queue(q, q->elevator);
884 kobject_del(&e->kobj);
885 e->registered = 0;
886} 878}
879EXPORT_SYMBOL(elv_register_queue);
887 880
888void elv_unregister_queue(struct request_queue *q) 881void elv_unregister_queue(struct request_queue *q)
889{ 882{
890 if (q) 883 if (q) {
891 __elv_unregister_queue(q->elevator); 884 struct elevator_queue *e = q->elevator;
885
886 kobject_uevent(&e->kobj, KOBJ_REMOVE);
887 kobject_del(&e->kobj);
888 e->registered = 0;
889 }
892} 890}
893EXPORT_SYMBOL(elv_unregister_queue); 891EXPORT_SYMBOL(elv_unregister_queue);
894 892
@@ -928,50 +926,36 @@ EXPORT_SYMBOL_GPL(elv_unregister);
928static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) 926static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
929{ 927{
930 struct elevator_queue *old_elevator, *e; 928 struct elevator_queue *old_elevator, *e;
931 void *data;
932 int err; 929 int err;
933 930
934 /* 931 /* allocate new elevator */
935 * Allocate new elevator
936 */
937 e = elevator_alloc(q, new_e); 932 e = elevator_alloc(q, new_e);
938 if (!e) 933 if (!e)
939 return -ENOMEM; 934 return -ENOMEM;
940 935
941 data = elevator_init_queue(q, e); 936 err = elevator_init_queue(q, e);
942 if (!data) { 937 if (err) {
943 kobject_put(&e->kobj); 938 kobject_put(&e->kobj);
944 return -ENOMEM; 939 return err;
945 } 940 }
946 941
947 /* 942 /* turn on BYPASS and drain all requests w/ elevator private data */
948 * Turn on BYPASS and drain all requests w/ elevator private data
949 */
950 elv_quiesce_start(q); 943 elv_quiesce_start(q);
951 944
952 /* 945 /* unregister old queue, register new one and kill old elevator */
953 * Remember old elevator. 946 if (q->elevator->registered) {
954 */ 947 elv_unregister_queue(q);
955 old_elevator = q->elevator; 948 err = __elv_register_queue(q, e);
956
957 /*
958 * attach and start new elevator
959 */
960 spin_lock_irq(q->queue_lock);
961 elevator_attach(q, e, data);
962 spin_unlock_irq(q->queue_lock);
963
964 if (old_elevator->registered) {
965 __elv_unregister_queue(old_elevator);
966
967 err = elv_register_queue(q);
968 if (err) 949 if (err)
969 goto fail_register; 950 goto fail_register;
970 } 951 }
971 952
972 /* 953 /* done, replace the old one with new one and turn off BYPASS */
973 * finally exit old elevator and turn off BYPASS. 954 spin_lock_irq(q->queue_lock);
974 */ 955 old_elevator = q->elevator;
956 q->elevator = e;
957 spin_unlock_irq(q->queue_lock);
958
975 elevator_exit(old_elevator); 959 elevator_exit(old_elevator);
976 elv_quiesce_end(q); 960 elv_quiesce_end(q);
977 961
@@ -985,7 +969,6 @@ fail_register:
985 * one again (along with re-adding the sysfs dir) 969 * one again (along with re-adding the sysfs dir)
986 */ 970 */
987 elevator_exit(e); 971 elevator_exit(e);
988 q->elevator = old_elevator;
989 elv_register_queue(q); 972 elv_register_queue(q);
990 elv_quiesce_end(q); 973 elv_quiesce_end(q);
991 974