aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2006-04-18 03:45:18 -0400
committerJens Axboe <axboe@suse.de>2006-04-18 03:45:18 -0400
commitdbecf3ab40b5a6cc4499543778cd9f9682c0abad (patch)
tree56dcd8c30835472b54017e1cb5fd852386ee9e49 /block/cfq-iosched.c
parentfba822722e3f9d438fca8fd9541d7ddd447d7a48 (diff)
[PATCH 2/2] cfq: fix cic's rbtree traversal
When queue dies, we set cic->key=NULL as dead mark. So, when we traverse a rbtree, we must check whether it's still valid key. if it was invalidated, drop it, then restart the traversal from top. Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 01820b1094e9..246feae16c60 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1472,15 +1472,31 @@ out:
1472 return cfqq; 1472 return cfqq;
1473} 1473}
1474 1474
1475static void
1476cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
1477{
1478 read_lock(&cfq_exit_lock);
1479 rb_erase(&cic->rb_node, &ioc->cic_root);
1480 read_unlock(&cfq_exit_lock);
1481 kmem_cache_free(cfq_ioc_pool, cic);
1482 atomic_dec(&ioc_count);
1483}
1484
1475static struct cfq_io_context * 1485static struct cfq_io_context *
1476cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc) 1486cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc)
1477{ 1487{
1478 struct rb_node *n = ioc->cic_root.rb_node; 1488 struct rb_node *n;
1479 struct cfq_io_context *cic; 1489 struct cfq_io_context *cic;
1480 void *key = cfqd; 1490 void *key = cfqd;
1481 1491
1492restart:
1493 n = ioc->cic_root.rb_node;
1482 while (n) { 1494 while (n) {
1483 cic = rb_entry(n, struct cfq_io_context, rb_node); 1495 cic = rb_entry(n, struct cfq_io_context, rb_node);
1496 if (unlikely(!cic->key)) {
1497 cfq_drop_dead_cic(ioc, cic);
1498 goto restart;
1499 }
1484 1500
1485 if (key < cic->key) 1501 if (key < cic->key)
1486 n = n->rb_left; 1502 n = n->rb_left;
@@ -1497,20 +1513,24 @@ static inline void
1497cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, 1513cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
1498 struct cfq_io_context *cic) 1514 struct cfq_io_context *cic)
1499{ 1515{
1500 struct rb_node **p = &ioc->cic_root.rb_node; 1516 struct rb_node **p;
1501 struct rb_node *parent = NULL; 1517 struct rb_node *parent;
1502 struct cfq_io_context *__cic; 1518 struct cfq_io_context *__cic;
1503 1519
1504 read_lock(&cfq_exit_lock);
1505
1506 cic->ioc = ioc; 1520 cic->ioc = ioc;
1507 cic->key = cfqd; 1521 cic->key = cfqd;
1508 1522
1509 ioc->set_ioprio = cfq_ioc_set_ioprio; 1523 ioc->set_ioprio = cfq_ioc_set_ioprio;
1510 1524restart:
1525 parent = NULL;
1526 p = &ioc->cic_root.rb_node;
1511 while (*p) { 1527 while (*p) {
1512 parent = *p; 1528 parent = *p;
1513 __cic = rb_entry(parent, struct cfq_io_context, rb_node); 1529 __cic = rb_entry(parent, struct cfq_io_context, rb_node);
1530 if (unlikely(!__cic->key)) {
1531 cfq_drop_dead_cic(ioc, cic);
1532 goto restart;
1533 }
1514 1534
1515 if (cic->key < __cic->key) 1535 if (cic->key < __cic->key)
1516 p = &(*p)->rb_left; 1536 p = &(*p)->rb_left;
@@ -1520,6 +1540,7 @@ cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
1520 BUG(); 1540 BUG();
1521 } 1541 }
1522 1542
1543 read_lock(&cfq_exit_lock);
1523 rb_link_node(&cic->rb_node, parent, p); 1544 rb_link_node(&cic->rb_node, parent, p);
1524 rb_insert_color(&cic->rb_node, &ioc->cic_root); 1545 rb_insert_color(&cic->rb_node, &ioc->cic_root);
1525 list_add(&cic->queue_list, &cfqd->cic_list); 1546 list_add(&cic->queue_list, &cfqd->cic_list);