diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 13:21:20 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 18:34:12 -0500 |
| commit | e17a9489b4a686bb5e9615e1d375c67619cb99c5 (patch) | |
| tree | e6574d24ad8f16fefe7663c91cf19109e48f8c6c | |
| parent | 25975f863b0fd42c58109e253e7a4c65d9fdaf48 (diff) | |
[PATCH] stop elv_unregister() from rogering other iosched's data, fix locking
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | block/as-iosched.c | 7 | ||||
| -rw-r--r-- | block/cfq-iosched.c | 8 | ||||
| -rw-r--r-- | block/elevator.c | 24 | ||||
| -rw-r--r-- | include/linux/elevator.h | 1 |
4 files changed, 25 insertions, 15 deletions
diff --git a/block/as-iosched.c b/block/as-iosched.c index 8da3cf66894c..d2ee2af44b58 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c | |||
| @@ -195,6 +195,12 @@ static void free_as_io_context(struct as_io_context *aic) | |||
| 195 | kfree(aic); | 195 | kfree(aic); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | static void as_trim(struct io_context *ioc) | ||
| 199 | { | ||
| 200 | kfree(ioc->aic); | ||
| 201 | ioc->aic = NULL; | ||
| 202 | } | ||
| 203 | |||
| 198 | /* Called when the task exits */ | 204 | /* Called when the task exits */ |
| 199 | static void exit_as_io_context(struct as_io_context *aic) | 205 | static void exit_as_io_context(struct as_io_context *aic) |
| 200 | { | 206 | { |
| @@ -1860,6 +1866,7 @@ static struct elevator_type iosched_as = { | |||
| 1860 | .elevator_may_queue_fn = as_may_queue, | 1866 | .elevator_may_queue_fn = as_may_queue, |
| 1861 | .elevator_init_fn = as_init_queue, | 1867 | .elevator_init_fn = as_init_queue, |
| 1862 | .elevator_exit_fn = as_exit_queue, | 1868 | .elevator_exit_fn = as_exit_queue, |
| 1869 | .trim = as_trim, | ||
| 1863 | }, | 1870 | }, |
| 1864 | 1871 | ||
| 1865 | .elevator_ktype = &as_ktype, | 1872 | .elevator_ktype = &as_ktype, |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 521c56d4fdbc..7102bafc98b3 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -1211,6 +1211,13 @@ static void cfq_free_io_context(struct cfq_io_context *cic) | |||
| 1211 | kmem_cache_free(cfq_ioc_pool, cic); | 1211 | kmem_cache_free(cfq_ioc_pool, cic); |
| 1212 | } | 1212 | } |
| 1213 | 1213 | ||
| 1214 | static void cfq_trim(struct io_context *ioc) | ||
| 1215 | { | ||
| 1216 | ioc->set_ioprio = NULL; | ||
| 1217 | if (ioc->cic) | ||
| 1218 | cfq_free_io_context(ioc->cic); | ||
| 1219 | } | ||
| 1220 | |||
| 1214 | /* | 1221 | /* |
| 1215 | * Called with interrupts disabled | 1222 | * Called with interrupts disabled |
| 1216 | */ | 1223 | */ |
| @@ -2472,6 +2479,7 @@ static struct elevator_type iosched_cfq = { | |||
| 2472 | .elevator_may_queue_fn = cfq_may_queue, | 2479 | .elevator_may_queue_fn = cfq_may_queue, |
| 2473 | .elevator_init_fn = cfq_init_queue, | 2480 | .elevator_init_fn = cfq_init_queue, |
| 2474 | .elevator_exit_fn = cfq_exit_queue, | 2481 | .elevator_exit_fn = cfq_exit_queue, |
| 2482 | .trim = cfq_trim, | ||
| 2475 | }, | 2483 | }, |
| 2476 | .elevator_ktype = &cfq_ktype, | 2484 | .elevator_ktype = &cfq_ktype, |
| 2477 | .elevator_name = "cfq", | 2485 | .elevator_name = "cfq", |
diff --git a/block/elevator.c b/block/elevator.c index 24b702d649a9..0232df2b16e6 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
| @@ -675,21 +675,15 @@ void elv_unregister(struct elevator_type *e) | |||
| 675 | /* | 675 | /* |
| 676 | * Iterate every thread in the process to remove the io contexts. | 676 | * Iterate every thread in the process to remove the io contexts. |
| 677 | */ | 677 | */ |
| 678 | read_lock(&tasklist_lock); | 678 | if (e->ops.trim) { |
| 679 | do_each_thread(g, p) { | 679 | read_lock(&tasklist_lock); |
| 680 | struct io_context *ioc = p->io_context; | 680 | do_each_thread(g, p) { |
| 681 | if (ioc && ioc->cic) { | 681 | task_lock(p); |
| 682 | ioc->cic->exit(ioc->cic); | 682 | e->ops.trim(p->io_context); |
| 683 | ioc->cic->dtor(ioc->cic); | 683 | task_unlock(p); |
| 684 | ioc->cic = NULL; | 684 | } while_each_thread(g, p); |
| 685 | } | 685 | read_unlock(&tasklist_lock); |
| 686 | if (ioc && ioc->aic) { | 686 | } |
| 687 | ioc->aic->exit(ioc->aic); | ||
| 688 | ioc->aic->dtor(ioc->aic); | ||
| 689 | ioc->aic = NULL; | ||
| 690 | } | ||
| 691 | } while_each_thread(g, p); | ||
| 692 | read_unlock(&tasklist_lock); | ||
| 693 | 687 | ||
| 694 | spin_lock_irq(&elv_list_lock); | 688 | spin_lock_irq(&elv_list_lock); |
| 695 | list_del_init(&e->list); | 689 | list_del_init(&e->list); |
diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 18cf1f3e1184..f65766ef0532 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h | |||
| @@ -48,6 +48,7 @@ struct elevator_ops | |||
| 48 | 48 | ||
| 49 | elevator_init_fn *elevator_init_fn; | 49 | elevator_init_fn *elevator_init_fn; |
| 50 | elevator_exit_fn *elevator_exit_fn; | 50 | elevator_exit_fn *elevator_exit_fn; |
| 51 | void (*trim)(struct io_context *); | ||
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | #define ELV_NAME_MAX (16) | 54 | #define ELV_NAME_MAX (16) |
