diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 97d946585bc3..c95c69e199f4 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -75,8 +75,9 @@ static DEFINE_SPINLOCK(ioc_gone_lock); | |||
75 | struct cfq_rb_root { | 75 | struct cfq_rb_root { |
76 | struct rb_root rb; | 76 | struct rb_root rb; |
77 | struct rb_node *left; | 77 | struct rb_node *left; |
78 | unsigned count; | ||
78 | }; | 79 | }; |
79 | #define CFQ_RB_ROOT (struct cfq_rb_root) { RB_ROOT, NULL, } | 80 | #define CFQ_RB_ROOT (struct cfq_rb_root) { RB_ROOT, NULL, 0, } |
80 | 81 | ||
81 | /* | 82 | /* |
82 | * Per process-grouping structure | 83 | * Per process-grouping structure |
@@ -128,6 +129,7 @@ struct cfq_queue { | |||
128 | 129 | ||
129 | pid_t pid; | 130 | pid_t pid; |
130 | 131 | ||
132 | struct cfq_rb_root *service_tree; | ||
131 | struct cfq_queue *new_cfqq; | 133 | struct cfq_queue *new_cfqq; |
132 | }; | 134 | }; |
133 | 135 | ||
@@ -503,6 +505,7 @@ static void cfq_rb_erase(struct rb_node *n, struct cfq_rb_root *root) | |||
503 | if (root->left == n) | 505 | if (root->left == n) |
504 | root->left = NULL; | 506 | root->left = NULL; |
505 | rb_erase_init(n, &root->rb); | 507 | rb_erase_init(n, &root->rb); |
508 | --root->count; | ||
506 | } | 509 | } |
507 | 510 | ||
508 | /* | 511 | /* |
@@ -553,11 +556,12 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
553 | struct rb_node **p, *parent; | 556 | struct rb_node **p, *parent; |
554 | struct cfq_queue *__cfqq; | 557 | struct cfq_queue *__cfqq; |
555 | unsigned long rb_key; | 558 | unsigned long rb_key; |
559 | struct cfq_rb_root *service_tree = &cfqd->service_tree; | ||
556 | int left; | 560 | int left; |
557 | 561 | ||
558 | if (cfq_class_idle(cfqq)) { | 562 | if (cfq_class_idle(cfqq)) { |
559 | rb_key = CFQ_IDLE_DELAY; | 563 | rb_key = CFQ_IDLE_DELAY; |
560 | parent = rb_last(&cfqd->service_tree.rb); | 564 | parent = rb_last(&service_tree->rb); |
561 | if (parent && parent != &cfqq->rb_node) { | 565 | if (parent && parent != &cfqq->rb_node) { |
562 | __cfqq = rb_entry(parent, struct cfq_queue, rb_node); | 566 | __cfqq = rb_entry(parent, struct cfq_queue, rb_node); |
563 | rb_key += __cfqq->rb_key; | 567 | rb_key += __cfqq->rb_key; |
@@ -575,7 +579,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
575 | cfqq->slice_resid = 0; | 579 | cfqq->slice_resid = 0; |
576 | } else { | 580 | } else { |
577 | rb_key = -HZ; | 581 | rb_key = -HZ; |
578 | __cfqq = cfq_rb_first(&cfqd->service_tree); | 582 | __cfqq = cfq_rb_first(service_tree); |
579 | rb_key += __cfqq ? __cfqq->rb_key : jiffies; | 583 | rb_key += __cfqq ? __cfqq->rb_key : jiffies; |
580 | } | 584 | } |
581 | 585 | ||
@@ -586,12 +590,14 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
586 | if (rb_key == cfqq->rb_key) | 590 | if (rb_key == cfqq->rb_key) |
587 | return; | 591 | return; |
588 | 592 | ||
589 | cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree); | 593 | cfq_rb_erase(&cfqq->rb_node, cfqq->service_tree); |
594 | cfqq->service_tree = NULL; | ||
590 | } | 595 | } |
591 | 596 | ||
592 | left = 1; | 597 | left = 1; |
593 | parent = NULL; | 598 | parent = NULL; |
594 | p = &cfqd->service_tree.rb.rb_node; | 599 | cfqq->service_tree = service_tree; |
600 | p = &service_tree->rb.rb_node; | ||
595 | while (*p) { | 601 | while (*p) { |
596 | struct rb_node **n; | 602 | struct rb_node **n; |
597 | 603 | ||
@@ -623,11 +629,12 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
623 | } | 629 | } |
624 | 630 | ||
625 | if (left) | 631 | if (left) |
626 | cfqd->service_tree.left = &cfqq->rb_node; | 632 | service_tree->left = &cfqq->rb_node; |
627 | 633 | ||
628 | cfqq->rb_key = rb_key; | 634 | cfqq->rb_key = rb_key; |
629 | rb_link_node(&cfqq->rb_node, parent, p); | 635 | rb_link_node(&cfqq->rb_node, parent, p); |
630 | rb_insert_color(&cfqq->rb_node, &cfqd->service_tree.rb); | 636 | rb_insert_color(&cfqq->rb_node, &service_tree->rb); |
637 | service_tree->count++; | ||
631 | } | 638 | } |
632 | 639 | ||
633 | static struct cfq_queue * | 640 | static struct cfq_queue * |
@@ -730,8 +737,10 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
730 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); | 737 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); |
731 | cfq_clear_cfqq_on_rr(cfqq); | 738 | cfq_clear_cfqq_on_rr(cfqq); |
732 | 739 | ||
733 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) | 740 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) { |
734 | cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree); | 741 | cfq_rb_erase(&cfqq->rb_node, cfqq->service_tree); |
742 | cfqq->service_tree = NULL; | ||
743 | } | ||
735 | if (cfqq->p_root) { | 744 | if (cfqq->p_root) { |
736 | rb_erase(&cfqq->p_node, cfqq->p_root); | 745 | rb_erase(&cfqq->p_node, cfqq->p_root); |
737 | cfqq->p_root = NULL; | 746 | cfqq->p_root = NULL; |
@@ -2292,10 +2301,9 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq) | |||
2292 | cfq_log_cfqq(cfqd, cfqq, "insert_request"); | 2301 | cfq_log_cfqq(cfqd, cfqq, "insert_request"); |
2293 | cfq_init_prio_data(cfqq, RQ_CIC(rq)->ioc); | 2302 | cfq_init_prio_data(cfqq, RQ_CIC(rq)->ioc); |
2294 | 2303 | ||
2295 | cfq_add_rq_rb(rq); | ||
2296 | |||
2297 | rq_set_fifo_time(rq, jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]); | 2304 | rq_set_fifo_time(rq, jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]); |
2298 | list_add_tail(&rq->queuelist, &cfqq->fifo); | 2305 | list_add_tail(&rq->queuelist, &cfqq->fifo); |
2306 | cfq_add_rq_rb(rq); | ||
2299 | 2307 | ||
2300 | cfq_rq_enqueued(cfqd, cfqq, rq); | 2308 | cfq_rq_enqueued(cfqd, cfqq, rq); |
2301 | } | 2309 | } |