aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c66
1 files changed, 43 insertions, 23 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 0d3b70de3d80..a55a9bd75bd1 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -154,6 +154,8 @@ struct cfq_queue {
154 unsigned long rb_key; 154 unsigned long rb_key;
155 /* prio tree member */ 155 /* prio tree member */
156 struct rb_node p_node; 156 struct rb_node p_node;
157 /* prio tree root we belong to, if any */
158 struct rb_root *p_root;
157 /* sorted list of pending requests */ 159 /* sorted list of pending requests */
158 struct rb_root sort_list; 160 struct rb_root sort_list;
159 /* if fifo isn't expired, next request to serve */ 161 /* if fifo isn't expired, next request to serve */
@@ -558,10 +560,10 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq,
558} 560}
559 561
560static struct cfq_queue * 562static struct cfq_queue *
561cfq_prio_tree_lookup(struct cfq_data *cfqd, int ioprio, sector_t sector, 563cfq_prio_tree_lookup(struct cfq_data *cfqd, struct rb_root *root,
562 struct rb_node **ret_parent, struct rb_node ***rb_link) 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 struct rb_node **p, *parent; 567 struct rb_node **p, *parent;
566 struct cfq_queue *cfqq = NULL; 568 struct cfq_queue *cfqq = NULL;
567 569
@@ -584,34 +586,38 @@ cfq_prio_tree_lookup(struct cfq_data *cfqd, int ioprio, sector_t sector,
584 else 586 else
585 break; 587 break;
586 p = n; 588 p = n;
589 cfqq = NULL;
587 } 590 }
588 591
589 *ret_parent = parent; 592 *ret_parent = parent;
590 if (rb_link) 593 if (rb_link)
591 *rb_link = p; 594 *rb_link = p;
592 return NULL; 595 return cfqq;
593} 596}
594 597
595static void cfq_prio_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq) 598static void cfq_prio_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq)
596{ 599{
597 struct rb_root *root = &cfqd->prio_trees[cfqq->ioprio];
598 struct rb_node **p, *parent; 600 struct rb_node **p, *parent;
599 struct cfq_queue *__cfqq; 601 struct cfq_queue *__cfqq;
600 602
601 if (!RB_EMPTY_NODE(&cfqq->p_node)) 603 if (cfqq->p_root) {
602 rb_erase_init(&cfqq->p_node, root); 604 rb_erase(&cfqq->p_node, cfqq->p_root);
605 cfqq->p_root = NULL;
606 }
603 607
604 if (cfq_class_idle(cfqq)) 608 if (cfq_class_idle(cfqq))
605 return; 609 return;
606 if (!cfqq->next_rq) 610 if (!cfqq->next_rq)
607 return; 611 return;
608 612
609 __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,
610 &parent, &p); 615 &parent, &p);
611 BUG_ON(__cfqq); 616 if (!__cfqq) {
612 617 rb_link_node(&cfqq->p_node, parent, p);
613 rb_link_node(&cfqq->p_node, parent, p); 618 rb_insert_color(&cfqq->p_node, cfqq->p_root);
614 rb_insert_color(&cfqq->p_node, root); 619 } else
620 cfqq->p_root = NULL;
615} 621}
616 622
617/* 623/*
@@ -656,8 +662,10 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
656 662
657 if (!RB_EMPTY_NODE(&cfqq->rb_node)) 663 if (!RB_EMPTY_NODE(&cfqq->rb_node))
658 cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree); 664 cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree);
659 if (!RB_EMPTY_NODE(&cfqq->p_node)) 665 if (cfqq->p_root) {
660 rb_erase_init(&cfqq->p_node, &cfqd->prio_trees[cfqq->ioprio]); 666 rb_erase(&cfqq->p_node, cfqq->p_root);
667 cfqq->p_root = NULL;
668 }
661 669
662 BUG_ON(!cfqd->busy_queues); 670 BUG_ON(!cfqd->busy_queues);
663 cfqd->busy_queues--; 671 cfqd->busy_queues--;
@@ -947,20 +955,24 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
947 return cfqd->last_position - rq->sector; 955 return cfqd->last_position - rq->sector;
948} 956}
949 957
958#define CIC_SEEK_THR 8 * 1024
959#define CIC_SEEKY(cic) ((cic)->seek_mean > CIC_SEEK_THR)
960
950static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq) 961static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq)
951{ 962{
952 struct cfq_io_context *cic = cfqd->active_cic; 963 struct cfq_io_context *cic = cfqd->active_cic;
964 sector_t sdist = cic->seek_mean;
953 965
954 if (!sample_valid(cic->seek_samples)) 966 if (!sample_valid(cic->seek_samples))
955 return 0; 967 sdist = CIC_SEEK_THR;
956 968
957 return cfq_dist_from_last(cfqd, rq) <= cic->seek_mean; 969 return cfq_dist_from_last(cfqd, rq) <= sdist;
958} 970}
959 971
960static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, 972static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
961 struct cfq_queue *cur_cfqq) 973 struct cfq_queue *cur_cfqq)
962{ 974{
963 struct rb_root *root = &cfqd->prio_trees[cur_cfqq->ioprio]; 975 struct rb_root *root = &cfqd->prio_trees[cur_cfqq->org_ioprio];
964 struct rb_node *parent, *node; 976 struct rb_node *parent, *node;
965 struct cfq_queue *__cfqq; 977 struct cfq_queue *__cfqq;
966 sector_t sector = cfqd->last_position; 978 sector_t sector = cfqd->last_position;
@@ -972,8 +984,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,
972 * First, if we find a request starting at the end of the last 984 * First, if we find a request starting at the end of the last
973 * request, choose it. 985 * request, choose it.
974 */ 986 */
975 __cfqq = cfq_prio_tree_lookup(cfqd, cur_cfqq->ioprio, 987 __cfqq = cfq_prio_tree_lookup(cfqd, root, sector, &parent, NULL);
976 sector, &parent, NULL);
977 if (__cfqq) 988 if (__cfqq)
978 return __cfqq; 989 return __cfqq;
979 990
@@ -1039,9 +1050,6 @@ static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd,
1039 return cfqq; 1050 return cfqq;
1040} 1051}
1041 1052
1042
1043#define CIC_SEEKY(cic) ((cic)->seek_mean > (8 * 1024))
1044
1045static void cfq_arm_slice_timer(struct cfq_data *cfqd) 1053static void cfq_arm_slice_timer(struct cfq_data *cfqd)
1046{ 1054{
1047 struct cfq_queue *cfqq = cfqd->active_queue; 1055 struct cfq_queue *cfqq = cfqd->active_queue;
@@ -1908,7 +1916,9 @@ cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
1908 sector_t sdist; 1916 sector_t sdist;
1909 u64 total; 1917 u64 total;
1910 1918
1911 if (cic->last_request_pos < rq->sector) 1919 if (!cic->last_request_pos)
1920 sdist = 0;
1921 else if (cic->last_request_pos < rq->sector)
1912 sdist = rq->sector - cic->last_request_pos; 1922 sdist = rq->sector - cic->last_request_pos;
1913 else 1923 else
1914 sdist = cic->last_request_pos - rq->sector; 1924 sdist = cic->last_request_pos - rq->sector;
@@ -2443,12 +2453,22 @@ static void cfq_exit_queue(struct elevator_queue *e)
2443static void *cfq_init_queue(struct request_queue *q) 2453static void *cfq_init_queue(struct request_queue *q)
2444{ 2454{
2445 struct cfq_data *cfqd; 2455 struct cfq_data *cfqd;
2456 int i;
2446 2457
2447 cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node); 2458 cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
2448 if (!cfqd) 2459 if (!cfqd)
2449 return NULL; 2460 return NULL;
2450 2461
2451 cfqd->service_tree = CFQ_RB_ROOT; 2462 cfqd->service_tree = CFQ_RB_ROOT;
2463
2464 /*
2465 * Not strictly needed (since RB_ROOT just clears the node and we
2466 * zeroed cfqd on alloc), but better be safe in case someone decides
2467 * to add magic to the rb code
2468 */
2469 for (i = 0; i < CFQ_PRIO_LISTS; i++)
2470 cfqd->prio_trees[i] = RB_ROOT;
2471
2452 INIT_LIST_HEAD(&cfqd->cic_list); 2472 INIT_LIST_HEAD(&cfqd->cic_list);
2453 2473
2454 cfqd->queue = q; 2474 cfqd->queue = q;