From: Christoph Hellwig We're trying to get rid of as much as possible tasklist walks, or at least moving them to core code. This patch falls into the second category. Instead of walking the tasklist in cfq-iosched move that into elv_unregister. The added benefit is that with this change the as ioscheduler might be might unloadable more easily aswell. The new code uses read_lock instead of read_lock_irq because the tasklist_lock only needs irq disabling for writers. Signed-off-by: Christoph Hellwig Acked-by: Jens Axboe Signed-off-by: Andrew Morton --- drivers/block/as-iosched.c | 2 +- drivers/block/cfq-iosched.c | 22 +--------------------- drivers/block/elevator.c | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+), 22 deletions(-) diff -puN drivers/block/as-iosched.c~move-tasklist-walk-from-cfq-iosched-to-elevatorc drivers/block/as-iosched.c --- 25/drivers/block/as-iosched.c~move-tasklist-walk-from-cfq-iosched-to-elevatorc Tue Sep 20 15:50:01 2005 +++ 25-akpm/drivers/block/as-iosched.c Tue Sep 20 15:50:01 2005 @@ -2119,8 +2119,8 @@ static int __init as_init(void) static void __exit as_exit(void) { - kmem_cache_destroy(arq_pool); elv_unregister(&iosched_as); + kmem_cache_destroy(arq_pool); } module_init(as_init); diff -puN drivers/block/cfq-iosched.c~move-tasklist-walk-from-cfq-iosched-to-elevatorc drivers/block/cfq-iosched.c --- 25/drivers/block/cfq-iosched.c~move-tasklist-walk-from-cfq-iosched-to-elevatorc Tue Sep 20 15:50:01 2005 +++ 25-akpm/drivers/block/cfq-iosched.c Tue Sep 20 15:50:01 2005 @@ -2620,28 +2620,8 @@ static int __init cfq_init(void) static void __exit cfq_exit(void) { - struct task_struct *g, *p; - unsigned long flags; - - read_lock_irqsave(&tasklist_lock, flags); - - /* - * iterate each process in the system, removing our io_context - */ - do_each_thread(g, p) { - struct io_context *ioc = p->io_context; - - if (ioc && ioc->cic) { - ioc->cic->exit(ioc->cic); - cfq_free_io_context(ioc->cic); - ioc->cic = NULL; - } - } while_each_thread(g, p); - - read_unlock_irqrestore(&tasklist_lock, flags); - - cfq_slab_kill(); elv_unregister(&iosched_cfq); + cfq_slab_kill(); } module_init(cfq_init); diff -puN drivers/block/elevator.c~move-tasklist-walk-from-cfq-iosched-to-elevatorc drivers/block/elevator.c --- 25/drivers/block/elevator.c~move-tasklist-walk-from-cfq-iosched-to-elevatorc Tue Sep 20 15:50:01 2005 +++ 25-akpm/drivers/block/elevator.c Tue Sep 20 15:50:01 2005 @@ -572,6 +572,27 @@ EXPORT_SYMBOL_GPL(elv_register); void elv_unregister(struct elevator_type *e) { + struct task_struct *g, *p; + + /* + * Iterate every thread in the process to remove the io contexts. + */ + read_lock(&tasklist_lock); + do_each_thread(g, p) { + struct io_context *ioc = p->io_context; + if (ioc && ioc->cic) { + ioc->cic->exit(ioc->cic); + ioc->cic->dtor(ioc->cic); + ioc->cic = NULL; + } + if (ioc && ioc->aic) { + ioc->aic->exit(ioc->aic); + ioc->aic->dtor(ioc->aic); + ioc->aic = NULL; + } + } while_each_thread(g, p); + read_unlock(&tasklist_lock); + spin_lock_irq(&elv_list_lock); list_del_init(&e->list); spin_unlock_irq(&elv_list_lock); _