diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 300 |
1 files changed, 250 insertions, 50 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index a4809de6fea6..a55a9bd75bd1 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -56,9 +56,6 @@ static DEFINE_SPINLOCK(ioc_gone_lock); | |||
56 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) | 56 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) |
57 | #define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) | 57 | #define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) |
58 | 58 | ||
59 | #define ASYNC (0) | ||
60 | #define SYNC (1) | ||
61 | |||
62 | #define sample_valid(samples) ((samples) > 80) | 59 | #define sample_valid(samples) ((samples) > 80) |
63 | 60 | ||
64 | /* | 61 | /* |
@@ -83,6 +80,14 @@ struct cfq_data { | |||
83 | * rr list of queues with requests and the count of them | 80 | * rr list of queues with requests and the count of them |
84 | */ | 81 | */ |
85 | struct cfq_rb_root service_tree; | 82 | struct cfq_rb_root service_tree; |
83 | |||
84 | /* | ||
85 | * Each priority tree is sorted by next_request position. These | ||
86 | * trees are used when determining if two or more queues are | ||
87 | * interleaving requests (see cfq_close_cooperator). | ||
88 | */ | ||
89 | struct rb_root prio_trees[CFQ_PRIO_LISTS]; | ||
90 | |||
86 | unsigned int busy_queues; | 91 | unsigned int busy_queues; |
87 | /* | 92 | /* |
88 | * Used to track any pending rt requests so we can pre-empt current | 93 | * Used to track any pending rt requests so we can pre-empt current |
@@ -147,6 +152,10 @@ struct cfq_queue { | |||
147 | struct rb_node rb_node; | 152 | struct rb_node rb_node; |
148 | /* service_tree key */ | 153 | /* service_tree key */ |
149 | unsigned long rb_key; | 154 | unsigned long rb_key; |
155 | /* prio tree member */ | ||
156 | struct rb_node p_node; | ||
157 | /* prio tree root we belong to, if any */ | ||
158 | struct rb_root *p_root; | ||
150 | /* sorted list of pending requests */ | 159 | /* sorted list of pending requests */ |
151 | struct rb_root sort_list; | 160 | struct rb_root sort_list; |
152 | /* if fifo isn't expired, next request to serve */ | 161 | /* if fifo isn't expired, next request to serve */ |
@@ -185,6 +194,7 @@ enum cfqq_state_flags { | |||
185 | CFQ_CFQQ_FLAG_prio_changed, /* task priority has changed */ | 194 | CFQ_CFQQ_FLAG_prio_changed, /* task priority has changed */ |
186 | CFQ_CFQQ_FLAG_slice_new, /* no requests dispatched in slice */ | 195 | CFQ_CFQQ_FLAG_slice_new, /* no requests dispatched in slice */ |
187 | CFQ_CFQQ_FLAG_sync, /* synchronous queue */ | 196 | CFQ_CFQQ_FLAG_sync, /* synchronous queue */ |
197 | CFQ_CFQQ_FLAG_coop, /* has done a coop jump of the queue */ | ||
188 | }; | 198 | }; |
189 | 199 | ||
190 | #define CFQ_CFQQ_FNS(name) \ | 200 | #define CFQ_CFQQ_FNS(name) \ |
@@ -211,6 +221,7 @@ CFQ_CFQQ_FNS(idle_window); | |||
211 | CFQ_CFQQ_FNS(prio_changed); | 221 | CFQ_CFQQ_FNS(prio_changed); |
212 | CFQ_CFQQ_FNS(slice_new); | 222 | CFQ_CFQQ_FNS(slice_new); |
213 | CFQ_CFQQ_FNS(sync); | 223 | CFQ_CFQQ_FNS(sync); |
224 | CFQ_CFQQ_FNS(coop); | ||
214 | #undef CFQ_CFQQ_FNS | 225 | #undef CFQ_CFQQ_FNS |
215 | 226 | ||
216 | #define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \ | 227 | #define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \ |
@@ -419,13 +430,17 @@ static struct cfq_queue *cfq_rb_first(struct cfq_rb_root *root) | |||
419 | return NULL; | 430 | return NULL; |
420 | } | 431 | } |
421 | 432 | ||
433 | static void rb_erase_init(struct rb_node *n, struct rb_root *root) | ||
434 | { | ||
435 | rb_erase(n, root); | ||
436 | RB_CLEAR_NODE(n); | ||
437 | } | ||
438 | |||
422 | static void cfq_rb_erase(struct rb_node *n, struct cfq_rb_root *root) | 439 | static void cfq_rb_erase(struct rb_node *n, struct cfq_rb_root *root) |
423 | { | 440 | { |
424 | if (root->left == n) | 441 | if (root->left == n) |
425 | root->left = NULL; | 442 | root->left = NULL; |
426 | 443 | rb_erase_init(n, &root->rb); | |
427 | rb_erase(n, &root->rb); | ||
428 | RB_CLEAR_NODE(n); | ||
429 | } | 444 | } |
430 | 445 | ||
431 | /* | 446 | /* |
@@ -470,8 +485,8 @@ static unsigned long cfq_slice_offset(struct cfq_data *cfqd, | |||
470 | * requests waiting to be processed. It is sorted in the order that | 485 | * requests waiting to be processed. It is sorted in the order that |
471 | * we will service the queues. | 486 | * we will service the queues. |
472 | */ | 487 | */ |
473 | static void cfq_service_tree_add(struct cfq_data *cfqd, | 488 | static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
474 | struct cfq_queue *cfqq, int add_front) | 489 | int add_front) |
475 | { | 490 | { |
476 | struct rb_node **p, *parent; | 491 | struct rb_node **p, *parent; |
477 | struct cfq_queue *__cfqq; | 492 | struct cfq_queue *__cfqq; |
@@ -544,6 +559,67 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, | |||
544 | rb_insert_color(&cfqq->rb_node, &cfqd->service_tree.rb); | 559 | rb_insert_color(&cfqq->rb_node, &cfqd->service_tree.rb); |
545 | } | 560 | } |
546 | 561 | ||
562 | static struct cfq_queue * | ||
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) | ||
566 | { | ||
567 | struct rb_node **p, *parent; | ||
568 | struct cfq_queue *cfqq = NULL; | ||
569 | |||
570 | parent = NULL; | ||
571 | p = &root->rb_node; | ||
572 | while (*p) { | ||
573 | struct rb_node **n; | ||
574 | |||
575 | parent = *p; | ||
576 | cfqq = rb_entry(parent, struct cfq_queue, p_node); | ||
577 | |||
578 | /* | ||
579 | * Sort strictly based on sector. Smallest to the left, | ||
580 | * largest to the right. | ||
581 | */ | ||
582 | if (sector > cfqq->next_rq->sector) | ||
583 | n = &(*p)->rb_right; | ||
584 | else if (sector < cfqq->next_rq->sector) | ||
585 | n = &(*p)->rb_left; | ||
586 | else | ||
587 | break; | ||
588 | p = n; | ||
589 | cfqq = NULL; | ||
590 | } | ||
591 | |||
592 | *ret_parent = parent; | ||
593 | if (rb_link) | ||
594 | *rb_link = p; | ||
595 | return cfqq; | ||
596 | } | ||
597 | |||
598 | static void cfq_prio_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
599 | { | ||
600 | struct rb_node **p, *parent; | ||
601 | struct cfq_queue *__cfqq; | ||
602 | |||
603 | if (cfqq->p_root) { | ||
604 | rb_erase(&cfqq->p_node, cfqq->p_root); | ||
605 | cfqq->p_root = NULL; | ||
606 | } | ||
607 | |||
608 | if (cfq_class_idle(cfqq)) | ||
609 | return; | ||
610 | if (!cfqq->next_rq) | ||
611 | return; | ||
612 | |||
613 | cfqq->p_root = &cfqd->prio_trees[cfqq->org_ioprio]; | ||
614 | __cfqq = cfq_prio_tree_lookup(cfqd, cfqq->p_root, cfqq->next_rq->sector, | ||
615 | &parent, &p); | ||
616 | if (!__cfqq) { | ||
617 | rb_link_node(&cfqq->p_node, parent, p); | ||
618 | rb_insert_color(&cfqq->p_node, cfqq->p_root); | ||
619 | } else | ||
620 | cfqq->p_root = NULL; | ||
621 | } | ||
622 | |||
547 | /* | 623 | /* |
548 | * Update cfqq's position in the service tree. | 624 | * Update cfqq's position in the service tree. |
549 | */ | 625 | */ |
@@ -552,8 +628,10 @@ static void cfq_resort_rr_list(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
552 | /* | 628 | /* |
553 | * Resorting requires the cfqq to be on the RR list already. | 629 | * Resorting requires the cfqq to be on the RR list already. |
554 | */ | 630 | */ |
555 | if (cfq_cfqq_on_rr(cfqq)) | 631 | if (cfq_cfqq_on_rr(cfqq)) { |
556 | cfq_service_tree_add(cfqd, cfqq, 0); | 632 | cfq_service_tree_add(cfqd, cfqq, 0); |
633 | cfq_prio_tree_add(cfqd, cfqq); | ||
634 | } | ||
557 | } | 635 | } |
558 | 636 | ||
559 | /* | 637 | /* |
@@ -584,6 +662,10 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
584 | 662 | ||
585 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) | 663 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) |
586 | cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree); | 664 | cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree); |
665 | if (cfqq->p_root) { | ||
666 | rb_erase(&cfqq->p_node, cfqq->p_root); | ||
667 | cfqq->p_root = NULL; | ||
668 | } | ||
587 | 669 | ||
588 | BUG_ON(!cfqd->busy_queues); | 670 | BUG_ON(!cfqd->busy_queues); |
589 | cfqd->busy_queues--; | 671 | cfqd->busy_queues--; |
@@ -613,7 +695,7 @@ static void cfq_add_rq_rb(struct request *rq) | |||
613 | { | 695 | { |
614 | struct cfq_queue *cfqq = RQ_CFQQ(rq); | 696 | struct cfq_queue *cfqq = RQ_CFQQ(rq); |
615 | struct cfq_data *cfqd = cfqq->cfqd; | 697 | struct cfq_data *cfqd = cfqq->cfqd; |
616 | struct request *__alias; | 698 | struct request *__alias, *prev; |
617 | 699 | ||
618 | cfqq->queued[rq_is_sync(rq)]++; | 700 | cfqq->queued[rq_is_sync(rq)]++; |
619 | 701 | ||
@@ -630,7 +712,15 @@ static void cfq_add_rq_rb(struct request *rq) | |||
630 | /* | 712 | /* |
631 | * check if this request is a better next-serve candidate | 713 | * check if this request is a better next-serve candidate |
632 | */ | 714 | */ |
715 | prev = cfqq->next_rq; | ||
633 | cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq); | 716 | cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq); |
717 | |||
718 | /* | ||
719 | * adjust priority tree position, if ->next_rq changes | ||
720 | */ | ||
721 | if (prev != cfqq->next_rq) | ||
722 | cfq_prio_tree_add(cfqd, cfqq); | ||
723 | |||
634 | BUG_ON(!cfqq->next_rq); | 724 | BUG_ON(!cfqq->next_rq); |
635 | } | 725 | } |
636 | 726 | ||
@@ -843,11 +933,15 @@ static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd) | |||
843 | /* | 933 | /* |
844 | * Get and set a new active queue for service. | 934 | * Get and set a new active queue for service. |
845 | */ | 935 | */ |
846 | static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) | 936 | static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd, |
937 | struct cfq_queue *cfqq) | ||
847 | { | 938 | { |
848 | struct cfq_queue *cfqq; | 939 | if (!cfqq) { |
940 | cfqq = cfq_get_next_queue(cfqd); | ||
941 | if (cfqq) | ||
942 | cfq_clear_cfqq_coop(cfqq); | ||
943 | } | ||
849 | 944 | ||
850 | cfqq = cfq_get_next_queue(cfqd); | ||
851 | __cfq_set_active_queue(cfqd, cfqq); | 945 | __cfq_set_active_queue(cfqd, cfqq); |
852 | return cfqq; | 946 | return cfqq; |
853 | } | 947 | } |
@@ -861,28 +955,100 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd, | |||
861 | return cfqd->last_position - rq->sector; | 955 | return cfqd->last_position - rq->sector; |
862 | } | 956 | } |
863 | 957 | ||
958 | #define CIC_SEEK_THR 8 * 1024 | ||
959 | #define CIC_SEEKY(cic) ((cic)->seek_mean > CIC_SEEK_THR) | ||
960 | |||
864 | static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq) | 961 | static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq) |
865 | { | 962 | { |
866 | struct cfq_io_context *cic = cfqd->active_cic; | 963 | struct cfq_io_context *cic = cfqd->active_cic; |
964 | sector_t sdist = cic->seek_mean; | ||
867 | 965 | ||
868 | if (!sample_valid(cic->seek_samples)) | 966 | if (!sample_valid(cic->seek_samples)) |
869 | return 0; | 967 | sdist = CIC_SEEK_THR; |
968 | |||
969 | return cfq_dist_from_last(cfqd, rq) <= sdist; | ||
970 | } | ||
971 | |||
972 | static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, | ||
973 | struct cfq_queue *cur_cfqq) | ||
974 | { | ||
975 | struct rb_root *root = &cfqd->prio_trees[cur_cfqq->org_ioprio]; | ||
976 | struct rb_node *parent, *node; | ||
977 | struct cfq_queue *__cfqq; | ||
978 | sector_t sector = cfqd->last_position; | ||
979 | |||
980 | if (RB_EMPTY_ROOT(root)) | ||
981 | return NULL; | ||
982 | |||
983 | /* | ||
984 | * First, if we find a request starting at the end of the last | ||
985 | * request, choose it. | ||
986 | */ | ||
987 | __cfqq = cfq_prio_tree_lookup(cfqd, root, sector, &parent, NULL); | ||
988 | if (__cfqq) | ||
989 | return __cfqq; | ||
990 | |||
991 | /* | ||
992 | * If the exact sector wasn't found, the parent of the NULL leaf | ||
993 | * will contain the closest sector. | ||
994 | */ | ||
995 | __cfqq = rb_entry(parent, struct cfq_queue, p_node); | ||
996 | if (cfq_rq_close(cfqd, __cfqq->next_rq)) | ||
997 | return __cfqq; | ||
998 | |||
999 | if (__cfqq->next_rq->sector < sector) | ||
1000 | node = rb_next(&__cfqq->p_node); | ||
1001 | else | ||
1002 | node = rb_prev(&__cfqq->p_node); | ||
1003 | if (!node) | ||
1004 | return NULL; | ||
870 | 1005 | ||
871 | return cfq_dist_from_last(cfqd, rq) <= cic->seek_mean; | 1006 | __cfqq = rb_entry(node, struct cfq_queue, p_node); |
1007 | if (cfq_rq_close(cfqd, __cfqq->next_rq)) | ||
1008 | return __cfqq; | ||
1009 | |||
1010 | return NULL; | ||
872 | } | 1011 | } |
873 | 1012 | ||
874 | static int cfq_close_cooperator(struct cfq_data *cfq_data, | 1013 | /* |
875 | struct cfq_queue *cfqq) | 1014 | * cfqd - obvious |
1015 | * cur_cfqq - passed in so that we don't decide that the current queue is | ||
1016 | * closely cooperating with itself. | ||
1017 | * | ||
1018 | * So, basically we're assuming that that cur_cfqq has dispatched at least | ||
1019 | * one request, and that cfqd->last_position reflects a position on the disk | ||
1020 | * associated with the I/O issued by cur_cfqq. I'm not sure this is a valid | ||
1021 | * assumption. | ||
1022 | */ | ||
1023 | static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd, | ||
1024 | struct cfq_queue *cur_cfqq, | ||
1025 | int probe) | ||
876 | { | 1026 | { |
1027 | struct cfq_queue *cfqq; | ||
1028 | |||
1029 | /* | ||
1030 | * A valid cfq_io_context is necessary to compare requests against | ||
1031 | * the seek_mean of the current cfqq. | ||
1032 | */ | ||
1033 | if (!cfqd->active_cic) | ||
1034 | return NULL; | ||
1035 | |||
877 | /* | 1036 | /* |
878 | * We should notice if some of the queues are cooperating, eg | 1037 | * We should notice if some of the queues are cooperating, eg |
879 | * working closely on the same area of the disk. In that case, | 1038 | * working closely on the same area of the disk. In that case, |
880 | * we can group them together and don't waste time idling. | 1039 | * we can group them together and don't waste time idling. |
881 | */ | 1040 | */ |
882 | return 0; | 1041 | cfqq = cfqq_close(cfqd, cur_cfqq); |
883 | } | 1042 | if (!cfqq) |
1043 | return NULL; | ||
884 | 1044 | ||
885 | #define CIC_SEEKY(cic) ((cic)->seek_mean > (8 * 1024)) | 1045 | if (cfq_cfqq_coop(cfqq)) |
1046 | return NULL; | ||
1047 | |||
1048 | if (!probe) | ||
1049 | cfq_mark_cfqq_coop(cfqq); | ||
1050 | return cfqq; | ||
1051 | } | ||
886 | 1052 | ||
887 | static void cfq_arm_slice_timer(struct cfq_data *cfqd) | 1053 | static void cfq_arm_slice_timer(struct cfq_data *cfqd) |
888 | { | 1054 | { |
@@ -920,13 +1086,6 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
920 | if (!cic || !atomic_read(&cic->ioc->nr_tasks)) | 1086 | if (!cic || !atomic_read(&cic->ioc->nr_tasks)) |
921 | return; | 1087 | return; |
922 | 1088 | ||
923 | /* | ||
924 | * See if this prio level has a good candidate | ||
925 | */ | ||
926 | if (cfq_close_cooperator(cfqd, cfqq) && | ||
927 | (sample_valid(cic->ttime_samples) && cic->ttime_mean > 2)) | ||
928 | return; | ||
929 | |||
930 | cfq_mark_cfqq_wait_request(cfqq); | 1089 | cfq_mark_cfqq_wait_request(cfqq); |
931 | 1090 | ||
932 | /* | 1091 | /* |
@@ -939,7 +1098,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
939 | sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT)); | 1098 | sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT)); |
940 | 1099 | ||
941 | mod_timer(&cfqd->idle_slice_timer, jiffies + sl); | 1100 | mod_timer(&cfqd->idle_slice_timer, jiffies + sl); |
942 | cfq_log(cfqd, "arm_idle: %lu", sl); | 1101 | cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl); |
943 | } | 1102 | } |
944 | 1103 | ||
945 | /* | 1104 | /* |
@@ -1003,7 +1162,7 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
1003 | */ | 1162 | */ |
1004 | static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) | 1163 | static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) |
1005 | { | 1164 | { |
1006 | struct cfq_queue *cfqq; | 1165 | struct cfq_queue *cfqq, *new_cfqq = NULL; |
1007 | 1166 | ||
1008 | cfqq = cfqd->active_queue; | 1167 | cfqq = cfqd->active_queue; |
1009 | if (!cfqq) | 1168 | if (!cfqq) |
@@ -1037,6 +1196,16 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) | |||
1037 | goto keep_queue; | 1196 | goto keep_queue; |
1038 | 1197 | ||
1039 | /* | 1198 | /* |
1199 | * If another queue has a request waiting within our mean seek | ||
1200 | * distance, let it run. The expire code will check for close | ||
1201 | * cooperators and put the close queue at the front of the service | ||
1202 | * tree. | ||
1203 | */ | ||
1204 | new_cfqq = cfq_close_cooperator(cfqd, cfqq, 0); | ||
1205 | if (new_cfqq) | ||
1206 | goto expire; | ||
1207 | |||
1208 | /* | ||
1040 | * No requests pending. If the active queue still has requests in | 1209 | * No requests pending. If the active queue still has requests in |
1041 | * flight or is idling for a new request, allow either of these | 1210 | * flight or is idling for a new request, allow either of these |
1042 | * conditions to happen (or time out) before selecting a new queue. | 1211 | * conditions to happen (or time out) before selecting a new queue. |
@@ -1050,7 +1219,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) | |||
1050 | expire: | 1219 | expire: |
1051 | cfq_slice_expired(cfqd, 0); | 1220 | cfq_slice_expired(cfqd, 0); |
1052 | new_queue: | 1221 | new_queue: |
1053 | cfqq = cfq_set_active_queue(cfqd); | 1222 | cfqq = cfq_set_active_queue(cfqd, new_cfqq); |
1054 | keep_queue: | 1223 | keep_queue: |
1055 | return cfqq; | 1224 | return cfqq; |
1056 | } | 1225 | } |
@@ -1333,14 +1502,14 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, | |||
1333 | if (ioc->ioc_data == cic) | 1502 | if (ioc->ioc_data == cic) |
1334 | rcu_assign_pointer(ioc->ioc_data, NULL); | 1503 | rcu_assign_pointer(ioc->ioc_data, NULL); |
1335 | 1504 | ||
1336 | if (cic->cfqq[ASYNC]) { | 1505 | if (cic->cfqq[BLK_RW_ASYNC]) { |
1337 | cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]); | 1506 | cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); |
1338 | cic->cfqq[ASYNC] = NULL; | 1507 | cic->cfqq[BLK_RW_ASYNC] = NULL; |
1339 | } | 1508 | } |
1340 | 1509 | ||
1341 | if (cic->cfqq[SYNC]) { | 1510 | if (cic->cfqq[BLK_RW_SYNC]) { |
1342 | cfq_exit_cfqq(cfqd, cic->cfqq[SYNC]); | 1511 | cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_SYNC]); |
1343 | cic->cfqq[SYNC] = NULL; | 1512 | cic->cfqq[BLK_RW_SYNC] = NULL; |
1344 | } | 1513 | } |
1345 | } | 1514 | } |
1346 | 1515 | ||
@@ -1449,17 +1618,18 @@ static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic) | |||
1449 | 1618 | ||
1450 | spin_lock_irqsave(cfqd->queue->queue_lock, flags); | 1619 | spin_lock_irqsave(cfqd->queue->queue_lock, flags); |
1451 | 1620 | ||
1452 | cfqq = cic->cfqq[ASYNC]; | 1621 | cfqq = cic->cfqq[BLK_RW_ASYNC]; |
1453 | if (cfqq) { | 1622 | if (cfqq) { |
1454 | struct cfq_queue *new_cfqq; | 1623 | struct cfq_queue *new_cfqq; |
1455 | new_cfqq = cfq_get_queue(cfqd, ASYNC, cic->ioc, GFP_ATOMIC); | 1624 | new_cfqq = cfq_get_queue(cfqd, BLK_RW_ASYNC, cic->ioc, |
1625 | GFP_ATOMIC); | ||
1456 | if (new_cfqq) { | 1626 | if (new_cfqq) { |
1457 | cic->cfqq[ASYNC] = new_cfqq; | 1627 | cic->cfqq[BLK_RW_ASYNC] = new_cfqq; |
1458 | cfq_put_queue(cfqq); | 1628 | cfq_put_queue(cfqq); |
1459 | } | 1629 | } |
1460 | } | 1630 | } |
1461 | 1631 | ||
1462 | cfqq = cic->cfqq[SYNC]; | 1632 | cfqq = cic->cfqq[BLK_RW_SYNC]; |
1463 | if (cfqq) | 1633 | if (cfqq) |
1464 | cfq_mark_cfqq_prio_changed(cfqq); | 1634 | cfq_mark_cfqq_prio_changed(cfqq); |
1465 | 1635 | ||
@@ -1510,6 +1680,7 @@ retry: | |||
1510 | } | 1680 | } |
1511 | 1681 | ||
1512 | RB_CLEAR_NODE(&cfqq->rb_node); | 1682 | RB_CLEAR_NODE(&cfqq->rb_node); |
1683 | RB_CLEAR_NODE(&cfqq->p_node); | ||
1513 | INIT_LIST_HEAD(&cfqq->fifo); | 1684 | INIT_LIST_HEAD(&cfqq->fifo); |
1514 | 1685 | ||
1515 | atomic_set(&cfqq->ref, 0); | 1686 | atomic_set(&cfqq->ref, 0); |
@@ -1745,7 +1916,9 @@ cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic, | |||
1745 | sector_t sdist; | 1916 | sector_t sdist; |
1746 | u64 total; | 1917 | u64 total; |
1747 | 1918 | ||
1748 | 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) | ||
1749 | sdist = rq->sector - cic->last_request_pos; | 1922 | sdist = rq->sector - cic->last_request_pos; |
1750 | else | 1923 | else |
1751 | sdist = cic->last_request_pos - rq->sector; | 1924 | sdist = cic->last_request_pos - rq->sector; |
@@ -1905,10 +2078,20 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1905 | * Remember that we saw a request from this process, but | 2078 | * Remember that we saw a request from this process, but |
1906 | * don't start queuing just yet. Otherwise we risk seeing lots | 2079 | * don't start queuing just yet. Otherwise we risk seeing lots |
1907 | * of tiny requests, because we disrupt the normal plugging | 2080 | * of tiny requests, because we disrupt the normal plugging |
1908 | * and merging. | 2081 | * and merging. If the request is already larger than a single |
2082 | * page, let it rip immediately. For that case we assume that | ||
2083 | * merging is already done. Ditto for a busy system that | ||
2084 | * has other work pending, don't risk delaying until the | ||
2085 | * idle timer unplug to continue working. | ||
1909 | */ | 2086 | */ |
1910 | if (cfq_cfqq_wait_request(cfqq)) | 2087 | if (cfq_cfqq_wait_request(cfqq)) { |
2088 | if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE || | ||
2089 | cfqd->busy_queues > 1) { | ||
2090 | del_timer(&cfqd->idle_slice_timer); | ||
2091 | blk_start_queueing(cfqd->queue); | ||
2092 | } | ||
1911 | cfq_mark_cfqq_must_dispatch(cfqq); | 2093 | cfq_mark_cfqq_must_dispatch(cfqq); |
2094 | } | ||
1912 | } else if (cfq_should_preempt(cfqd, cfqq, rq)) { | 2095 | } else if (cfq_should_preempt(cfqd, cfqq, rq)) { |
1913 | /* | 2096 | /* |
1914 | * not the active queue - expire current slice if it is | 2097 | * not the active queue - expire current slice if it is |
@@ -1992,16 +2175,24 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) | |||
1992 | * or if we want to idle in case it has no pending requests. | 2175 | * or if we want to idle in case it has no pending requests. |
1993 | */ | 2176 | */ |
1994 | if (cfqd->active_queue == cfqq) { | 2177 | if (cfqd->active_queue == cfqq) { |
2178 | const bool cfqq_empty = RB_EMPTY_ROOT(&cfqq->sort_list); | ||
2179 | |||
1995 | if (cfq_cfqq_slice_new(cfqq)) { | 2180 | if (cfq_cfqq_slice_new(cfqq)) { |
1996 | cfq_set_prio_slice(cfqd, cfqq); | 2181 | cfq_set_prio_slice(cfqd, cfqq); |
1997 | cfq_clear_cfqq_slice_new(cfqq); | 2182 | cfq_clear_cfqq_slice_new(cfqq); |
1998 | } | 2183 | } |
2184 | /* | ||
2185 | * If there are no requests waiting in this queue, and | ||
2186 | * there are other queues ready to issue requests, AND | ||
2187 | * those other queues are issuing requests within our | ||
2188 | * mean seek distance, give them a chance to run instead | ||
2189 | * of idling. | ||
2190 | */ | ||
1999 | if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq)) | 2191 | if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq)) |
2000 | cfq_slice_expired(cfqd, 1); | 2192 | cfq_slice_expired(cfqd, 1); |
2001 | else if (sync && !rq_noidle(rq) && | 2193 | else if (cfqq_empty && !cfq_close_cooperator(cfqd, cfqq, 1) && |
2002 | RB_EMPTY_ROOT(&cfqq->sort_list)) { | 2194 | sync && !rq_noidle(rq)) |
2003 | cfq_arm_slice_timer(cfqd); | 2195 | cfq_arm_slice_timer(cfqd); |
2004 | } | ||
2005 | } | 2196 | } |
2006 | 2197 | ||
2007 | if (!cfqd->rq_in_driver) | 2198 | if (!cfqd->rq_in_driver) |
@@ -2062,7 +2253,7 @@ static int cfq_may_queue(struct request_queue *q, int rw) | |||
2062 | if (!cic) | 2253 | if (!cic) |
2063 | return ELV_MQUEUE_MAY; | 2254 | return ELV_MQUEUE_MAY; |
2064 | 2255 | ||
2065 | cfqq = cic_to_cfqq(cic, rw & REQ_RW_SYNC); | 2256 | cfqq = cic_to_cfqq(cic, rw_is_sync(rw)); |
2066 | if (cfqq) { | 2257 | if (cfqq) { |
2067 | cfq_init_prio_data(cfqq, cic->ioc); | 2258 | cfq_init_prio_data(cfqq, cic->ioc); |
2068 | cfq_prio_boost(cfqq); | 2259 | cfq_prio_boost(cfqq); |
@@ -2152,11 +2343,10 @@ static void cfq_kick_queue(struct work_struct *work) | |||
2152 | struct cfq_data *cfqd = | 2343 | struct cfq_data *cfqd = |
2153 | container_of(work, struct cfq_data, unplug_work); | 2344 | container_of(work, struct cfq_data, unplug_work); |
2154 | struct request_queue *q = cfqd->queue; | 2345 | struct request_queue *q = cfqd->queue; |
2155 | unsigned long flags; | ||
2156 | 2346 | ||
2157 | spin_lock_irqsave(q->queue_lock, flags); | 2347 | spin_lock_irq(q->queue_lock); |
2158 | blk_start_queueing(q); | 2348 | blk_start_queueing(q); |
2159 | spin_unlock_irqrestore(q->queue_lock, flags); | 2349 | spin_unlock_irq(q->queue_lock); |
2160 | } | 2350 | } |
2161 | 2351 | ||
2162 | /* | 2352 | /* |
@@ -2263,12 +2453,22 @@ static void cfq_exit_queue(struct elevator_queue *e) | |||
2263 | static void *cfq_init_queue(struct request_queue *q) | 2453 | static void *cfq_init_queue(struct request_queue *q) |
2264 | { | 2454 | { |
2265 | struct cfq_data *cfqd; | 2455 | struct cfq_data *cfqd; |
2456 | int i; | ||
2266 | 2457 | ||
2267 | cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node); | 2458 | cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node); |
2268 | if (!cfqd) | 2459 | if (!cfqd) |
2269 | return NULL; | 2460 | return NULL; |
2270 | 2461 | ||
2271 | 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 | |||
2272 | INIT_LIST_HEAD(&cfqd->cic_list); | 2472 | INIT_LIST_HEAD(&cfqd->cic_list); |
2273 | 2473 | ||
2274 | cfqd->queue = q; | 2474 | cfqd->queue = q; |