diff options
| -rw-r--r-- | block/as-iosched.c | 15 | ||||
| -rw-r--r-- | block/cfq-iosched.c | 16 | ||||
| -rw-r--r-- | block/ll_rw_blk.c | 2 |
3 files changed, 32 insertions, 1 deletions
diff --git a/block/as-iosched.c b/block/as-iosched.c index d2ee2af44b58..55a997fc4bb4 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c | |||
| @@ -182,6 +182,9 @@ struct as_rq { | |||
| 182 | 182 | ||
| 183 | static kmem_cache_t *arq_pool; | 183 | static kmem_cache_t *arq_pool; |
| 184 | 184 | ||
| 185 | static atomic_t ioc_count = ATOMIC_INIT(0); | ||
| 186 | static struct completion *ioc_gone; | ||
| 187 | |||
| 185 | static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq); | 188 | static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq); |
| 186 | static void as_antic_stop(struct as_data *ad); | 189 | static void as_antic_stop(struct as_data *ad); |
| 187 | 190 | ||
| @@ -193,11 +196,14 @@ static void as_antic_stop(struct as_data *ad); | |||
| 193 | static void free_as_io_context(struct as_io_context *aic) | 196 | static void free_as_io_context(struct as_io_context *aic) |
| 194 | { | 197 | { |
| 195 | kfree(aic); | 198 | kfree(aic); |
| 199 | if (atomic_dec_and_test(&ioc_count) && ioc_gone) | ||
| 200 | complete(ioc_gone); | ||
| 196 | } | 201 | } |
| 197 | 202 | ||
| 198 | static void as_trim(struct io_context *ioc) | 203 | static void as_trim(struct io_context *ioc) |
| 199 | { | 204 | { |
| 200 | kfree(ioc->aic); | 205 | if (ioc->aic) |
| 206 | free_as_io_context(ioc->aic); | ||
| 201 | ioc->aic = NULL; | 207 | ioc->aic = NULL; |
| 202 | } | 208 | } |
| 203 | 209 | ||
| @@ -226,6 +232,7 @@ static struct as_io_context *alloc_as_io_context(void) | |||
| 226 | ret->seek_total = 0; | 232 | ret->seek_total = 0; |
| 227 | ret->seek_samples = 0; | 233 | ret->seek_samples = 0; |
| 228 | ret->seek_mean = 0; | 234 | ret->seek_mean = 0; |
| 235 | atomic_inc(&ioc_count); | ||
| 229 | } | 236 | } |
| 230 | 237 | ||
| 231 | return ret; | 238 | return ret; |
| @@ -1900,7 +1907,13 @@ static int __init as_init(void) | |||
| 1900 | 1907 | ||
| 1901 | static void __exit as_exit(void) | 1908 | static void __exit as_exit(void) |
| 1902 | { | 1909 | { |
| 1910 | DECLARE_COMPLETION(all_gone); | ||
| 1903 | elv_unregister(&iosched_as); | 1911 | elv_unregister(&iosched_as); |
| 1912 | ioc_gone = &all_gone; | ||
| 1913 | barrier(); | ||
| 1914 | if (atomic_read(&ioc_count)) | ||
| 1915 | complete(ioc_gone); | ||
| 1916 | synchronize_rcu(); | ||
| 1904 | kmem_cache_destroy(arq_pool); | 1917 | kmem_cache_destroy(arq_pool); |
| 1905 | } | 1918 | } |
| 1906 | 1919 | ||
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 7102bafc98b3..3cd985bece3a 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -91,6 +91,9 @@ static kmem_cache_t *crq_pool; | |||
| 91 | static kmem_cache_t *cfq_pool; | 91 | static kmem_cache_t *cfq_pool; |
| 92 | static kmem_cache_t *cfq_ioc_pool; | 92 | static kmem_cache_t *cfq_ioc_pool; |
| 93 | 93 | ||
| 94 | static atomic_t ioc_count = ATOMIC_INIT(0); | ||
| 95 | static struct completion *ioc_gone; | ||
| 96 | |||
| 94 | #define CFQ_PRIO_LISTS IOPRIO_BE_NR | 97 | #define CFQ_PRIO_LISTS IOPRIO_BE_NR |
| 95 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) | 98 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) |
| 96 | #define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE) | 99 | #define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE) |
| @@ -1202,13 +1205,17 @@ static void cfq_free_io_context(struct cfq_io_context *cic) | |||
| 1202 | { | 1205 | { |
| 1203 | struct cfq_io_context *__cic; | 1206 | struct cfq_io_context *__cic; |
| 1204 | struct list_head *entry, *next; | 1207 | struct list_head *entry, *next; |
| 1208 | int freed = 1; | ||
| 1205 | 1209 | ||
| 1206 | list_for_each_safe(entry, next, &cic->list) { | 1210 | list_for_each_safe(entry, next, &cic->list) { |
| 1207 | __cic = list_entry(entry, struct cfq_io_context, list); | 1211 | __cic = list_entry(entry, struct cfq_io_context, list); |
| 1208 | kmem_cache_free(cfq_ioc_pool, __cic); | 1212 | kmem_cache_free(cfq_ioc_pool, __cic); |
| 1213 | freed++; | ||
| 1209 | } | 1214 | } |
| 1210 | 1215 | ||
| 1211 | kmem_cache_free(cfq_ioc_pool, cic); | 1216 | kmem_cache_free(cfq_ioc_pool, cic); |
| 1217 | if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone) | ||
| 1218 | complete(ioc_gone); | ||
| 1212 | } | 1219 | } |
| 1213 | 1220 | ||
| 1214 | static void cfq_trim(struct io_context *ioc) | 1221 | static void cfq_trim(struct io_context *ioc) |
| @@ -1297,6 +1304,7 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) | |||
| 1297 | cic->dtor = cfq_free_io_context; | 1304 | cic->dtor = cfq_free_io_context; |
| 1298 | cic->exit = cfq_exit_io_context; | 1305 | cic->exit = cfq_exit_io_context; |
| 1299 | INIT_LIST_HEAD(&cic->queue_list); | 1306 | INIT_LIST_HEAD(&cic->queue_list); |
| 1307 | atomic_inc(&ioc_count); | ||
| 1300 | } | 1308 | } |
| 1301 | 1309 | ||
| 1302 | return cic; | 1310 | return cic; |
| @@ -1501,6 +1509,7 @@ restart: | |||
| 1501 | list); | 1509 | list); |
| 1502 | read_unlock(&cfq_exit_lock); | 1510 | read_unlock(&cfq_exit_lock); |
| 1503 | kmem_cache_free(cfq_ioc_pool, cic); | 1511 | kmem_cache_free(cfq_ioc_pool, cic); |
| 1512 | atomic_dec(&ioc_count); | ||
| 1504 | goto restart; | 1513 | goto restart; |
| 1505 | } | 1514 | } |
| 1506 | 1515 | ||
| @@ -1523,6 +1532,7 @@ restart: | |||
| 1523 | list_del(&__cic->list); | 1532 | list_del(&__cic->list); |
| 1524 | read_unlock(&cfq_exit_lock); | 1533 | read_unlock(&cfq_exit_lock); |
| 1525 | kmem_cache_free(cfq_ioc_pool, __cic); | 1534 | kmem_cache_free(cfq_ioc_pool, __cic); |
| 1535 | atomic_dec(&ioc_count); | ||
| 1526 | goto restart; | 1536 | goto restart; |
| 1527 | } | 1537 | } |
| 1528 | } | 1538 | } |
| @@ -2510,7 +2520,13 @@ static int __init cfq_init(void) | |||
| 2510 | 2520 | ||
| 2511 | static void __exit cfq_exit(void) | 2521 | static void __exit cfq_exit(void) |
| 2512 | { | 2522 | { |
| 2523 | DECLARE_COMPLETION(all_gone); | ||
| 2513 | elv_unregister(&iosched_cfq); | 2524 | elv_unregister(&iosched_cfq); |
| 2525 | ioc_gone = &all_gone; | ||
| 2526 | barrier(); | ||
| 2527 | if (atomic_read(&ioc_count)) | ||
| 2528 | complete(ioc_gone); | ||
| 2529 | synchronize_rcu(); | ||
| 2514 | cfq_slab_kill(); | 2530 | cfq_slab_kill(); |
| 2515 | } | 2531 | } |
| 2516 | 2532 | ||
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index caa8fcf5474b..6dc769182052 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
| @@ -3477,10 +3477,12 @@ void put_io_context(struct io_context *ioc) | |||
| 3477 | BUG_ON(atomic_read(&ioc->refcount) == 0); | 3477 | BUG_ON(atomic_read(&ioc->refcount) == 0); |
| 3478 | 3478 | ||
| 3479 | if (atomic_dec_and_test(&ioc->refcount)) { | 3479 | if (atomic_dec_and_test(&ioc->refcount)) { |
| 3480 | rcu_read_lock(); | ||
| 3480 | if (ioc->aic && ioc->aic->dtor) | 3481 | if (ioc->aic && ioc->aic->dtor) |
| 3481 | ioc->aic->dtor(ioc->aic); | 3482 | ioc->aic->dtor(ioc->aic); |
| 3482 | if (ioc->cic && ioc->cic->dtor) | 3483 | if (ioc->cic && ioc->cic->dtor) |
| 3483 | ioc->cic->dtor(ioc->cic); | 3484 | ioc->cic->dtor(ioc->cic); |
| 3485 | rcu_read_unlock(); | ||
| 3484 | 3486 | ||
| 3485 | kmem_cache_free(iocontext_cachep, ioc); | 3487 | kmem_cache_free(iocontext_cachep, ioc); |
| 3486 | } | 3488 | } |
