Commit f2d1f0ae7851be5ebd9613a80dac139270938809

Authored by Jens Axboe
1 parent 3ac6c9f8a6

cfq-iosched: cache prio_tree root in cfqq->p_root

Currently we look it up from ->ioprio, but ->ioprio can change if
either the process gets its IO priority changed explicitly, or if
cfq decides to temporarily boost it. So if we are unlucky, we can
end up attempting to remove a node from a different rbtree root than
where it was added.

Fix this by using ->org_ioprio as the prio_tree index, since that
will only change for explicit IO priority settings (not for a boost).
Additionally cache the rbtree root inside the cfqq, then we don't have
to add code to reinsert the cfqq in the prio_tree if IO priority changes.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

Showing 1 changed file with 20 additions and 14 deletions Side-by-side Diff

... ... @@ -154,6 +154,8 @@
154 154 unsigned long rb_key;
155 155 /* prio tree member */
156 156 struct rb_node p_node;
  157 + /* prio tree root we belong to, if any */
  158 + struct rb_root *p_root;
157 159 /* sorted list of pending requests */
158 160 struct rb_root sort_list;
159 161 /* if fifo isn't expired, next request to serve */
160 162  
... ... @@ -558,10 +560,10 @@
558 560 }
559 561  
560 562 static struct cfq_queue *
561   -cfq_prio_tree_lookup(struct cfq_data *cfqd, int ioprio, sector_t sector,
562   - struct rb_node **ret_parent, struct rb_node ***rb_link)
  563 +cfq_prio_tree_lookup(struct cfq_data *cfqd, struct rb_root *root,
  564 + sector_t sector, struct rb_node **ret_parent,
  565 + struct rb_node ***rb_link)
563 566 {
564   - struct rb_root *root = &cfqd->prio_trees[ioprio];
565 567 struct rb_node **p, *parent;
566 568 struct cfq_queue *cfqq = NULL;
567 569  
568 570  
569 571  
570 572  
... ... @@ -595,24 +597,27 @@
595 597  
596 598 static void cfq_prio_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq)
597 599 {
598   - struct rb_root *root = &cfqd->prio_trees[cfqq->ioprio];
599 600 struct rb_node **p, *parent;
600 601 struct cfq_queue *__cfqq;
601 602  
602   - if (!RB_EMPTY_NODE(&cfqq->p_node))
603   - rb_erase_init(&cfqq->p_node, root);
  603 + if (cfqq->p_root) {
  604 + rb_erase(&cfqq->p_node, cfqq->p_root);
  605 + cfqq->p_root = NULL;
  606 + }
604 607  
605 608 if (cfq_class_idle(cfqq))
606 609 return;
607 610 if (!cfqq->next_rq)
608 611 return;
609 612  
610   - __cfqq = cfq_prio_tree_lookup(cfqd, cfqq->ioprio, cfqq->next_rq->sector,
  613 + cfqq->p_root = &cfqd->prio_trees[cfqq->org_ioprio];
  614 + __cfqq = cfq_prio_tree_lookup(cfqd, cfqq->p_root, cfqq->next_rq->sector,
611 615 &parent, &p);
612 616 if (!__cfqq) {
613 617 rb_link_node(&cfqq->p_node, parent, p);
614   - rb_insert_color(&cfqq->p_node, root);
615   - }
  618 + rb_insert_color(&cfqq->p_node, cfqq->p_root);
  619 + } else
  620 + cfqq->p_root = NULL;
616 621 }
617 622  
618 623 /*
... ... @@ -657,8 +662,10 @@
657 662  
658 663 if (!RB_EMPTY_NODE(&cfqq->rb_node))
659 664 cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree);
660   - if (!RB_EMPTY_NODE(&cfqq->p_node))
661   - rb_erase_init(&cfqq->p_node, &cfqd->prio_trees[cfqq->ioprio]);
  665 + if (cfqq->p_root) {
  666 + rb_erase(&cfqq->p_node, cfqq->p_root);
  667 + cfqq->p_root = NULL;
  668 + }
662 669  
663 670 BUG_ON(!cfqd->busy_queues);
664 671 cfqd->busy_queues--;
... ... @@ -965,7 +972,7 @@
965 972 static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
966 973 struct cfq_queue *cur_cfqq)
967 974 {
968   - struct rb_root *root = &cfqd->prio_trees[cur_cfqq->ioprio];
  975 + struct rb_root *root = &cfqd->prio_trees[cur_cfqq->org_ioprio];
969 976 struct rb_node *parent, *node;
970 977 struct cfq_queue *__cfqq;
971 978 sector_t sector = cfqd->last_position;
... ... @@ -977,8 +984,7 @@
977 984 * First, if we find a request starting at the end of the last
978 985 * request, choose it.
979 986 */
980   - __cfqq = cfq_prio_tree_lookup(cfqd, cur_cfqq->ioprio,
981   - sector, &parent, NULL);
  987 + __cfqq = cfq_prio_tree_lookup(cfqd, root, sector, &parent, NULL);
982 988 if (__cfqq)
983 989 return __cfqq;
984 990