diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 66 |
1 files changed, 33 insertions, 33 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 0f962ecae91f..f4e1006c253d 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -1143,24 +1143,37 @@ static void cfq_put_queue(struct cfq_queue *cfqq) | |||
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | /* | 1145 | /* |
1146 | * Call func for each cic attached to this ioc. Returns number of cic's seen. | 1146 | * Call func for each cic attached to this ioc. |
1147 | */ | 1147 | */ |
1148 | static unsigned int | 1148 | static void |
1149 | call_for_each_cic(struct io_context *ioc, | 1149 | call_for_each_cic(struct io_context *ioc, |
1150 | void (*func)(struct io_context *, struct cfq_io_context *)) | 1150 | void (*func)(struct io_context *, struct cfq_io_context *)) |
1151 | { | 1151 | { |
1152 | struct cfq_io_context *cic; | 1152 | struct cfq_io_context *cic; |
1153 | struct hlist_node *n; | 1153 | struct hlist_node *n; |
1154 | int called = 0; | ||
1155 | 1154 | ||
1156 | rcu_read_lock(); | 1155 | rcu_read_lock(); |
1157 | hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) { | 1156 | hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) |
1158 | func(ioc, cic); | 1157 | func(ioc, cic); |
1159 | called++; | ||
1160 | } | ||
1161 | rcu_read_unlock(); | 1158 | rcu_read_unlock(); |
1159 | } | ||
1160 | |||
1161 | static void cfq_cic_free_rcu(struct rcu_head *head) | ||
1162 | { | ||
1163 | struct cfq_io_context *cic; | ||
1164 | |||
1165 | cic = container_of(head, struct cfq_io_context, rcu_head); | ||
1166 | |||
1167 | kmem_cache_free(cfq_ioc_pool, cic); | ||
1168 | elv_ioc_count_dec(ioc_count); | ||
1162 | 1169 | ||
1163 | return called; | 1170 | if (ioc_gone && !elv_ioc_count_read(ioc_count)) |
1171 | complete(ioc_gone); | ||
1172 | } | ||
1173 | |||
1174 | static void cfq_cic_free(struct cfq_io_context *cic) | ||
1175 | { | ||
1176 | call_rcu(&cic->rcu_head, cfq_cic_free_rcu); | ||
1164 | } | 1177 | } |
1165 | 1178 | ||
1166 | static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic) | 1179 | static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic) |
@@ -1174,24 +1187,18 @@ static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic) | |||
1174 | hlist_del_rcu(&cic->cic_list); | 1187 | hlist_del_rcu(&cic->cic_list); |
1175 | spin_unlock_irqrestore(&ioc->lock, flags); | 1188 | spin_unlock_irqrestore(&ioc->lock, flags); |
1176 | 1189 | ||
1177 | kmem_cache_free(cfq_ioc_pool, cic); | 1190 | cfq_cic_free(cic); |
1178 | } | 1191 | } |
1179 | 1192 | ||
1180 | static void cfq_free_io_context(struct io_context *ioc) | 1193 | static void cfq_free_io_context(struct io_context *ioc) |
1181 | { | 1194 | { |
1182 | int freed; | ||
1183 | |||
1184 | /* | 1195 | /* |
1185 | * ioc->refcount is zero here, so no more cic's are allowed to be | 1196 | * ioc->refcount is zero here, or we are called from elv_unregister(), |
1186 | * linked into this ioc. So it should be ok to iterate over the known | 1197 | * so no more cic's are allowed to be linked into this ioc. So it |
1187 | * list, we will see all cic's since no new ones are added. | 1198 | * should be ok to iterate over the known list, we will see all cic's |
1199 | * since no new ones are added. | ||
1188 | */ | 1200 | */ |
1189 | freed = call_for_each_cic(ioc, cic_free_func); | 1201 | call_for_each_cic(ioc, cic_free_func); |
1190 | |||
1191 | elv_ioc_count_mod(ioc_count, -freed); | ||
1192 | |||
1193 | if (ioc_gone && !elv_ioc_count_read(ioc_count)) | ||
1194 | complete(ioc_gone); | ||
1195 | } | 1202 | } |
1196 | 1203 | ||
1197 | static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 1204 | static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
@@ -1207,6 +1214,8 @@ static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
1207 | static void __cfq_exit_single_io_context(struct cfq_data *cfqd, | 1214 | static void __cfq_exit_single_io_context(struct cfq_data *cfqd, |
1208 | struct cfq_io_context *cic) | 1215 | struct cfq_io_context *cic) |
1209 | { | 1216 | { |
1217 | struct io_context *ioc = cic->ioc; | ||
1218 | |||
1210 | list_del_init(&cic->queue_list); | 1219 | list_del_init(&cic->queue_list); |
1211 | 1220 | ||
1212 | /* | 1221 | /* |
@@ -1216,6 +1225,9 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, | |||
1216 | cic->dead_key = (unsigned long) cic->key; | 1225 | cic->dead_key = (unsigned long) cic->key; |
1217 | cic->key = NULL; | 1226 | cic->key = NULL; |
1218 | 1227 | ||
1228 | if (ioc->ioc_data == cic) | ||
1229 | rcu_assign_pointer(ioc->ioc_data, NULL); | ||
1230 | |||
1219 | if (cic->cfqq[ASYNC]) { | 1231 | if (cic->cfqq[ASYNC]) { |
1220 | cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]); | 1232 | cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]); |
1221 | cic->cfqq[ASYNC] = NULL; | 1233 | cic->cfqq[ASYNC] = NULL; |
@@ -1248,7 +1260,6 @@ static void cfq_exit_single_io_context(struct io_context *ioc, | |||
1248 | */ | 1260 | */ |
1249 | static void cfq_exit_io_context(struct io_context *ioc) | 1261 | static void cfq_exit_io_context(struct io_context *ioc) |
1250 | { | 1262 | { |
1251 | rcu_assign_pointer(ioc->ioc_data, NULL); | ||
1252 | call_for_each_cic(ioc, cfq_exit_single_io_context); | 1263 | call_for_each_cic(ioc, cfq_exit_single_io_context); |
1253 | } | 1264 | } |
1254 | 1265 | ||
@@ -1458,15 +1469,6 @@ cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc, | |||
1458 | return cfqq; | 1469 | return cfqq; |
1459 | } | 1470 | } |
1460 | 1471 | ||
1461 | static void cfq_cic_free(struct cfq_io_context *cic) | ||
1462 | { | ||
1463 | kmem_cache_free(cfq_ioc_pool, cic); | ||
1464 | elv_ioc_count_dec(ioc_count); | ||
1465 | |||
1466 | if (ioc_gone && !elv_ioc_count_read(ioc_count)) | ||
1467 | complete(ioc_gone); | ||
1468 | } | ||
1469 | |||
1470 | /* | 1472 | /* |
1471 | * We drop cfq io contexts lazily, so we may find a dead one. | 1473 | * We drop cfq io contexts lazily, so we may find a dead one. |
1472 | */ | 1474 | */ |
@@ -1480,8 +1482,7 @@ cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc, | |||
1480 | 1482 | ||
1481 | spin_lock_irqsave(&ioc->lock, flags); | 1483 | spin_lock_irqsave(&ioc->lock, flags); |
1482 | 1484 | ||
1483 | if (ioc->ioc_data == cic) | 1485 | BUG_ON(ioc->ioc_data == cic); |
1484 | rcu_assign_pointer(ioc->ioc_data, NULL); | ||
1485 | 1486 | ||
1486 | radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd); | 1487 | radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd); |
1487 | hlist_del_rcu(&cic->cic_list); | 1488 | hlist_del_rcu(&cic->cic_list); |
@@ -2138,7 +2139,7 @@ static int __init cfq_slab_setup(void) | |||
2138 | if (!cfq_pool) | 2139 | if (!cfq_pool) |
2139 | goto fail; | 2140 | goto fail; |
2140 | 2141 | ||
2141 | cfq_ioc_pool = KMEM_CACHE(cfq_io_context, SLAB_DESTROY_BY_RCU); | 2142 | cfq_ioc_pool = KMEM_CACHE(cfq_io_context, 0); |
2142 | if (!cfq_ioc_pool) | 2143 | if (!cfq_ioc_pool) |
2143 | goto fail; | 2144 | goto fail; |
2144 | 2145 | ||
@@ -2286,7 +2287,6 @@ static void __exit cfq_exit(void) | |||
2286 | smp_wmb(); | 2287 | smp_wmb(); |
2287 | if (elv_ioc_count_read(ioc_count)) | 2288 | if (elv_ioc_count_read(ioc_count)) |
2288 | wait_for_completion(ioc_gone); | 2289 | wait_for_completion(ioc_gone); |
2289 | synchronize_rcu(); | ||
2290 | cfq_slab_kill(); | 2290 | cfq_slab_kill(); |
2291 | } | 2291 | } |
2292 | 2292 | ||