diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/cfq-iosched.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 94f53a1f4677..64df3fa303b0 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -1165,6 +1165,8 @@ static void cfq_free_io_context(struct io_context *ioc) | |||
1165 | struct rb_node *n; | 1165 | struct rb_node *n; |
1166 | int freed = 0; | 1166 | int freed = 0; |
1167 | 1167 | ||
1168 | ioc->ioc_data = NULL; | ||
1169 | |||
1168 | while ((n = rb_first(&ioc->cic_root)) != NULL) { | 1170 | while ((n = rb_first(&ioc->cic_root)) != NULL) { |
1169 | __cic = rb_entry(n, struct cfq_io_context, rb_node); | 1171 | __cic = rb_entry(n, struct cfq_io_context, rb_node); |
1170 | rb_erase(&__cic->rb_node, &ioc->cic_root); | 1172 | rb_erase(&__cic->rb_node, &ioc->cic_root); |
@@ -1228,10 +1230,11 @@ static void cfq_exit_io_context(struct io_context *ioc) | |||
1228 | struct cfq_io_context *__cic; | 1230 | struct cfq_io_context *__cic; |
1229 | struct rb_node *n; | 1231 | struct rb_node *n; |
1230 | 1232 | ||
1233 | ioc->ioc_data = NULL; | ||
1234 | |||
1231 | /* | 1235 | /* |
1232 | * put the reference this task is holding to the various queues | 1236 | * put the reference this task is holding to the various queues |
1233 | */ | 1237 | */ |
1234 | |||
1235 | n = rb_first(&ioc->cic_root); | 1238 | n = rb_first(&ioc->cic_root); |
1236 | while (n != NULL) { | 1239 | while (n != NULL) { |
1237 | __cic = rb_entry(n, struct cfq_io_context, rb_node); | 1240 | __cic = rb_entry(n, struct cfq_io_context, rb_node); |
@@ -1415,6 +1418,10 @@ static void | |||
1415 | cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic) | 1418 | cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic) |
1416 | { | 1419 | { |
1417 | WARN_ON(!list_empty(&cic->queue_list)); | 1420 | WARN_ON(!list_empty(&cic->queue_list)); |
1421 | |||
1422 | if (ioc->ioc_data == cic) | ||
1423 | ioc->ioc_data = NULL; | ||
1424 | |||
1418 | rb_erase(&cic->rb_node, &ioc->cic_root); | 1425 | rb_erase(&cic->rb_node, &ioc->cic_root); |
1419 | kmem_cache_free(cfq_ioc_pool, cic); | 1426 | kmem_cache_free(cfq_ioc_pool, cic); |
1420 | elv_ioc_count_dec(ioc_count); | 1427 | elv_ioc_count_dec(ioc_count); |
@@ -1430,6 +1437,13 @@ cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc) | |||
1430 | if (unlikely(!ioc)) | 1437 | if (unlikely(!ioc)) |
1431 | return NULL; | 1438 | return NULL; |
1432 | 1439 | ||
1440 | /* | ||
1441 | * we maintain a last-hit cache, to avoid browsing over the tree | ||
1442 | */ | ||
1443 | cic = ioc->ioc_data; | ||
1444 | if (cic && cic->key == cfqd) | ||
1445 | return cic; | ||
1446 | |||
1433 | restart: | 1447 | restart: |
1434 | n = ioc->cic_root.rb_node; | 1448 | n = ioc->cic_root.rb_node; |
1435 | while (n) { | 1449 | while (n) { |
@@ -1445,8 +1459,10 @@ restart: | |||
1445 | n = n->rb_left; | 1459 | n = n->rb_left; |
1446 | else if (key > k) | 1460 | else if (key > k) |
1447 | n = n->rb_right; | 1461 | n = n->rb_right; |
1448 | else | 1462 | else { |
1463 | ioc->ioc_data = cic; | ||
1449 | return cic; | 1464 | return cic; |
1465 | } | ||
1450 | } | 1466 | } |
1451 | 1467 | ||
1452 | return NULL; | 1468 | return NULL; |