diff options
Diffstat (limited to 'drivers/block/elevator.c')
-rw-r--r-- | drivers/block/elevator.c | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c index 55621d5c5774..36f1057084b0 100644 --- a/drivers/block/elevator.c +++ b/drivers/block/elevator.c | |||
@@ -147,24 +147,17 @@ static void elevator_setup_default(void) | |||
147 | struct elevator_type *e; | 147 | struct elevator_type *e; |
148 | 148 | ||
149 | /* | 149 | /* |
150 | * check if default is set and exists | 150 | * If default has not been set, use the compiled-in selection. |
151 | */ | 151 | */ |
152 | if (chosen_elevator[0] && (e = elevator_get(chosen_elevator))) { | 152 | if (!chosen_elevator[0]) |
153 | elevator_put(e); | 153 | strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); |
154 | return; | ||
155 | } | ||
156 | 154 | ||
157 | #if defined(CONFIG_IOSCHED_AS) | 155 | /* |
158 | strcpy(chosen_elevator, "anticipatory"); | 156 | * If the given scheduler is not available, fall back to no-op. |
159 | #elif defined(CONFIG_IOSCHED_DEADLINE) | 157 | */ |
160 | strcpy(chosen_elevator, "deadline"); | 158 | if (!(e = elevator_find(chosen_elevator))) |
161 | #elif defined(CONFIG_IOSCHED_CFQ) | 159 | strcpy(chosen_elevator, "noop"); |
162 | strcpy(chosen_elevator, "cfq"); | 160 | elevator_put(e); |
163 | #elif defined(CONFIG_IOSCHED_NOOP) | ||
164 | strcpy(chosen_elevator, "noop"); | ||
165 | #else | ||
166 | #error "You must build at least 1 IO scheduler into the kernel" | ||
167 | #endif | ||
168 | } | 161 | } |
169 | 162 | ||
170 | static int __init elevator_setup(char *str) | 163 | static int __init elevator_setup(char *str) |
@@ -642,6 +635,27 @@ EXPORT_SYMBOL_GPL(elv_register); | |||
642 | 635 | ||
643 | void elv_unregister(struct elevator_type *e) | 636 | void elv_unregister(struct elevator_type *e) |
644 | { | 637 | { |
638 | struct task_struct *g, *p; | ||
639 | |||
640 | /* | ||
641 | * Iterate every thread in the process to remove the io contexts. | ||
642 | */ | ||
643 | read_lock(&tasklist_lock); | ||
644 | do_each_thread(g, p) { | ||
645 | struct io_context *ioc = p->io_context; | ||
646 | if (ioc && ioc->cic) { | ||
647 | ioc->cic->exit(ioc->cic); | ||
648 | ioc->cic->dtor(ioc->cic); | ||
649 | ioc->cic = NULL; | ||
650 | } | ||
651 | if (ioc && ioc->aic) { | ||
652 | ioc->aic->exit(ioc->aic); | ||
653 | ioc->aic->dtor(ioc->aic); | ||
654 | ioc->aic = NULL; | ||
655 | } | ||
656 | } while_each_thread(g, p); | ||
657 | read_unlock(&tasklist_lock); | ||
658 | |||
645 | spin_lock_irq(&elv_list_lock); | 659 | spin_lock_irq(&elv_list_lock); |
646 | list_del_init(&e->list); | 660 | list_del_init(&e->list); |
647 | spin_unlock_irq(&elv_list_lock); | 661 | spin_unlock_irq(&elv_list_lock); |
@@ -739,8 +753,10 @@ ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) | |||
739 | return -EINVAL; | 753 | return -EINVAL; |
740 | } | 754 | } |
741 | 755 | ||
742 | if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) | 756 | if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { |
757 | elevator_put(e); | ||
743 | return count; | 758 | return count; |
759 | } | ||
744 | 760 | ||
745 | elevator_switch(q, e); | 761 | elevator_switch(q, e); |
746 | return count; | 762 | return count; |