aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-03-18 15:05:53 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2006-03-18 18:34:15 -0500
commit334e94de9bea353156abd6f2242d3cc4a24562b0 (patch)
treeff4a253e9e3bf487be03bf58727a7ea40a34ba87 /block/cfq-iosched.c
parente17a9489b4a686bb5e9615e1d375c67619cb99c5 (diff)
[PATCH] deal with rmmod/put_io_context() races
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c16
1 files changed, 16 insertions, 0 deletions
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;
91static kmem_cache_t *cfq_pool; 91static kmem_cache_t *cfq_pool;
92static kmem_cache_t *cfq_ioc_pool; 92static kmem_cache_t *cfq_ioc_pool;
93 93
94static atomic_t ioc_count = ATOMIC_INIT(0);
95static 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
1214static void cfq_trim(struct io_context *ioc) 1221static 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
2511static void __exit cfq_exit(void) 2521static 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