diff options
| -rw-r--r-- | block/cfq-iosched.c | 87 |
1 files changed, 32 insertions, 55 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 4a0397022f5b..a8437042e28a 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -45,9 +45,6 @@ static int cfq_slice_idle = HZ / 125; | |||
| 45 | */ | 45 | */ |
| 46 | #define CFQ_QHASH_SHIFT 6 | 46 | #define CFQ_QHASH_SHIFT 6 |
| 47 | #define CFQ_QHASH_ENTRIES (1 << CFQ_QHASH_SHIFT) | 47 | #define CFQ_QHASH_ENTRIES (1 << CFQ_QHASH_SHIFT) |
| 48 | #define list_entry_qhash(entry) hlist_entry((entry), struct cfq_queue, cfq_hash) | ||
| 49 | |||
| 50 | #define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list) | ||
| 51 | 48 | ||
| 52 | #define RQ_CIC(rq) ((struct cfq_io_context*)(rq)->elevator_private) | 49 | #define RQ_CIC(rq) ((struct cfq_io_context*)(rq)->elevator_private) |
| 53 | #define RQ_CFQQ(rq) ((rq)->elevator_private2) | 50 | #define RQ_CFQQ(rq) ((rq)->elevator_private2) |
| @@ -91,7 +88,6 @@ struct cfq_data { | |||
| 91 | * rr list of queues with requests and the count of them | 88 | * rr list of queues with requests and the count of them |
| 92 | */ | 89 | */ |
| 93 | struct cfq_rb_root service_tree; | 90 | struct cfq_rb_root service_tree; |
| 94 | struct list_head cur_rr; | ||
| 95 | unsigned int busy_queues; | 91 | unsigned int busy_queues; |
| 96 | 92 | ||
| 97 | /* | 93 | /* |
| @@ -146,8 +142,6 @@ struct cfq_queue { | |||
| 146 | struct hlist_node cfq_hash; | 142 | struct hlist_node cfq_hash; |
| 147 | /* hash key */ | 143 | /* hash key */ |
| 148 | unsigned int key; | 144 | unsigned int key; |
| 149 | /* member of the rr/busy/cur/idle cfqd list */ | ||
| 150 | struct list_head cfq_list; | ||
| 151 | /* service_tree member */ | 145 | /* service_tree member */ |
| 152 | struct rb_node rb_node; | 146 | struct rb_node rb_node; |
| 153 | /* service_tree key */ | 147 | /* service_tree key */ |
| @@ -452,16 +446,19 @@ static unsigned long cfq_slice_offset(struct cfq_data *cfqd, | |||
| 452 | * we will service the queues. | 446 | * we will service the queues. |
| 453 | */ | 447 | */ |
| 454 | static void cfq_service_tree_add(struct cfq_data *cfqd, | 448 | static void cfq_service_tree_add(struct cfq_data *cfqd, |
| 455 | struct cfq_queue *cfqq) | 449 | struct cfq_queue *cfqq, int add_front) |
| 456 | { | 450 | { |
| 457 | struct rb_node **p = &cfqd->service_tree.rb.rb_node; | 451 | struct rb_node **p = &cfqd->service_tree.rb.rb_node; |
| 458 | struct rb_node *parent = NULL; | 452 | struct rb_node *parent = NULL; |
| 459 | unsigned long rb_key; | 453 | unsigned long rb_key; |
| 460 | int left; | 454 | int left; |
| 461 | 455 | ||
| 462 | rb_key = cfq_slice_offset(cfqd, cfqq) + jiffies; | 456 | if (!add_front) { |
| 463 | rb_key += cfqq->slice_resid; | 457 | rb_key = cfq_slice_offset(cfqd, cfqq) + jiffies; |
| 464 | cfqq->slice_resid = 0; | 458 | rb_key += cfqq->slice_resid; |
| 459 | cfqq->slice_resid = 0; | ||
| 460 | } else | ||
| 461 | rb_key = 0; | ||
| 465 | 462 | ||
| 466 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) { | 463 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) { |
| 467 | /* | 464 | /* |
| @@ -516,13 +513,13 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, | |||
| 516 | /* | 513 | /* |
| 517 | * Update cfqq's position in the service tree. | 514 | * Update cfqq's position in the service tree. |
| 518 | */ | 515 | */ |
| 519 | static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) | 516 | static void cfq_resort_rr_list(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
| 520 | { | 517 | { |
| 521 | /* | 518 | /* |
| 522 | * Resorting requires the cfqq to be on the RR list already. | 519 | * Resorting requires the cfqq to be on the RR list already. |
| 523 | */ | 520 | */ |
| 524 | if (cfq_cfqq_on_rr(cfqq)) | 521 | if (cfq_cfqq_on_rr(cfqq)) |
| 525 | cfq_service_tree_add(cfqq->cfqd, cfqq); | 522 | cfq_service_tree_add(cfqd, cfqq, 0); |
| 526 | } | 523 | } |
| 527 | 524 | ||
| 528 | /* | 525 | /* |
| @@ -536,7 +533,7 @@ cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 536 | cfq_mark_cfqq_on_rr(cfqq); | 533 | cfq_mark_cfqq_on_rr(cfqq); |
| 537 | cfqd->busy_queues++; | 534 | cfqd->busy_queues++; |
| 538 | 535 | ||
| 539 | cfq_resort_rr_list(cfqq, 0); | 536 | cfq_resort_rr_list(cfqd, cfqq); |
| 540 | } | 537 | } |
| 541 | 538 | ||
| 542 | /* | 539 | /* |
| @@ -548,7 +545,6 @@ cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 548 | { | 545 | { |
| 549 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); | 546 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); |
| 550 | cfq_clear_cfqq_on_rr(cfqq); | 547 | cfq_clear_cfqq_on_rr(cfqq); |
| 551 | list_del_init(&cfqq->cfq_list); | ||
| 552 | 548 | ||
| 553 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) | 549 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) |
| 554 | cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree); | 550 | cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree); |
| @@ -771,7 +767,7 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
| 771 | if (timed_out && !cfq_cfqq_slice_new(cfqq)) | 767 | if (timed_out && !cfq_cfqq_slice_new(cfqq)) |
| 772 | cfqq->slice_resid = cfqq->slice_end - jiffies; | 768 | cfqq->slice_resid = cfqq->slice_end - jiffies; |
| 773 | 769 | ||
| 774 | cfq_resort_rr_list(cfqq, preempted); | 770 | cfq_resort_rr_list(cfqd, cfqq); |
| 775 | 771 | ||
| 776 | if (cfqq == cfqd->active_queue) | 772 | if (cfqq == cfqd->active_queue) |
| 777 | cfqd->active_queue = NULL; | 773 | cfqd->active_queue = NULL; |
| @@ -799,31 +795,28 @@ static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted, | |||
| 799 | */ | 795 | */ |
| 800 | static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd) | 796 | static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd) |
| 801 | { | 797 | { |
| 802 | struct cfq_queue *cfqq = NULL; | 798 | struct cfq_queue *cfqq; |
| 799 | struct rb_node *n; | ||
| 803 | 800 | ||
| 804 | if (!list_empty(&cfqd->cur_rr)) { | 801 | if (RB_EMPTY_ROOT(&cfqd->service_tree.rb)) |
| 805 | /* | 802 | return NULL; |
| 806 | * if current list is non-empty, grab first entry. | ||
| 807 | */ | ||
| 808 | cfqq = list_entry_cfqq(cfqd->cur_rr.next); | ||
| 809 | } else if (!RB_EMPTY_ROOT(&cfqd->service_tree.rb)) { | ||
| 810 | struct rb_node *n = cfq_rb_first(&cfqd->service_tree); | ||
| 811 | 803 | ||
| 812 | cfqq = rb_entry(n, struct cfq_queue, rb_node); | 804 | n = cfq_rb_first(&cfqd->service_tree); |
| 813 | if (cfq_class_idle(cfqq)) { | 805 | cfqq = rb_entry(n, struct cfq_queue, rb_node); |
| 814 | unsigned long end; | ||
| 815 | 806 | ||
| 816 | /* | 807 | if (cfq_class_idle(cfqq)) { |
| 817 | * if we have idle queues and no rt or be queues had | 808 | unsigned long end; |
| 818 | * pending requests, either allow immediate service if | 809 | |
| 819 | * the grace period has passed or arm the idle grace | 810 | /* |
| 820 | * timer | 811 | * if we have idle queues and no rt or be queues had |
| 821 | */ | 812 | * pending requests, either allow immediate service if |
| 822 | end = cfqd->last_end_request + CFQ_IDLE_GRACE; | 813 | * the grace period has passed or arm the idle grace |
| 823 | if (time_before(jiffies, end)) { | 814 | * timer |
| 824 | mod_timer(&cfqd->idle_class_timer, end); | 815 | */ |
| 825 | cfqq = NULL; | 816 | end = cfqd->last_end_request + CFQ_IDLE_GRACE; |
| 826 | } | 817 | if (time_before(jiffies, end)) { |
| 818 | mod_timer(&cfqd->idle_class_timer, end); | ||
| 819 | cfqq = NULL; | ||
| 827 | } | 820 | } |
| 828 | } | 821 | } |
| 829 | 822 | ||
| @@ -1075,18 +1068,6 @@ static inline int __cfq_forced_dispatch_cfqq(struct cfq_queue *cfqq) | |||
| 1075 | return dispatched; | 1068 | return dispatched; |
| 1076 | } | 1069 | } |
| 1077 | 1070 | ||
| 1078 | static int cfq_forced_dispatch_cfqqs(struct list_head *list) | ||
| 1079 | { | ||
| 1080 | struct cfq_queue *cfqq, *next; | ||
| 1081 | int dispatched; | ||
| 1082 | |||
| 1083 | dispatched = 0; | ||
| 1084 | list_for_each_entry_safe(cfqq, next, list, cfq_list) | ||
| 1085 | dispatched += __cfq_forced_dispatch_cfqq(cfqq); | ||
| 1086 | |||
| 1087 | return dispatched; | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | /* | 1071 | /* |
| 1091 | * Drain our current requests. Used for barriers and when switching | 1072 | * Drain our current requests. Used for barriers and when switching |
| 1092 | * io schedulers on-the-fly. | 1073 | * io schedulers on-the-fly. |
| @@ -1102,8 +1083,6 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd) | |||
| 1102 | dispatched += __cfq_forced_dispatch_cfqq(cfqq); | 1083 | dispatched += __cfq_forced_dispatch_cfqq(cfqq); |
| 1103 | } | 1084 | } |
| 1104 | 1085 | ||
| 1105 | dispatched += cfq_forced_dispatch_cfqqs(&cfqd->cur_rr); | ||
| 1106 | |||
| 1107 | cfq_slice_expired(cfqd, 0, 0); | 1086 | cfq_slice_expired(cfqd, 0, 0); |
| 1108 | 1087 | ||
| 1109 | BUG_ON(cfqd->busy_queues); | 1088 | BUG_ON(cfqd->busy_queues); |
| @@ -1433,7 +1412,6 @@ retry: | |||
| 1433 | memset(cfqq, 0, sizeof(*cfqq)); | 1412 | memset(cfqq, 0, sizeof(*cfqq)); |
| 1434 | 1413 | ||
| 1435 | INIT_HLIST_NODE(&cfqq->cfq_hash); | 1414 | INIT_HLIST_NODE(&cfqq->cfq_hash); |
| 1436 | INIT_LIST_HEAD(&cfqq->cfq_list); | ||
| 1437 | RB_CLEAR_NODE(&cfqq->rb_node); | 1415 | RB_CLEAR_NODE(&cfqq->rb_node); |
| 1438 | INIT_LIST_HEAD(&cfqq->fifo); | 1416 | INIT_LIST_HEAD(&cfqq->fifo); |
| 1439 | 1417 | ||
| @@ -1712,8 +1690,8 @@ static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 1712 | * so we know that it will be selected next. | 1690 | * so we know that it will be selected next. |
| 1713 | */ | 1691 | */ |
| 1714 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); | 1692 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); |
| 1715 | list_del_init(&cfqq->cfq_list); | 1693 | |
| 1716 | list_add(&cfqq->cfq_list, &cfqd->cur_rr); | 1694 | cfq_service_tree_add(cfqd, cfqq, 1); |
| 1717 | 1695 | ||
| 1718 | cfqq->slice_end = 0; | 1696 | cfqq->slice_end = 0; |
| 1719 | cfq_mark_cfqq_slice_new(cfqq); | 1697 | cfq_mark_cfqq_slice_new(cfqq); |
| @@ -2077,7 +2055,6 @@ static void *cfq_init_queue(request_queue_t *q) | |||
| 2077 | memset(cfqd, 0, sizeof(*cfqd)); | 2055 | memset(cfqd, 0, sizeof(*cfqd)); |
| 2078 | 2056 | ||
| 2079 | cfqd->service_tree = CFQ_RB_ROOT; | 2057 | cfqd->service_tree = CFQ_RB_ROOT; |
| 2080 | INIT_LIST_HEAD(&cfqd->cur_rr); | ||
| 2081 | INIT_LIST_HEAD(&cfqd->cic_list); | 2058 | INIT_LIST_HEAD(&cfqd->cic_list); |
| 2082 | 2059 | ||
| 2083 | cfqd->cfq_hash = kmalloc_node(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL, q->node); | 2060 | cfqd->cfq_hash = kmalloc_node(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL, q->node); |
