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.c117
1 files changed, 34 insertions, 83 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 8830893e062f..8fe1a0ddb511 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -26,9 +26,9 @@ static const int cfq_slice_async_rq = 2;
26static int cfq_slice_idle = HZ / 125; 26static int cfq_slice_idle = HZ / 125;
27 27
28/* 28/*
29 * grace period before allowing idle class to get disk access 29 * offset from end of service tree
30 */ 30 */
31#define CFQ_IDLE_GRACE (HZ / 10) 31#define CFQ_IDLE_DELAY (HZ / 5)
32 32
33/* 33/*
34 * below this threshold, we consider thinktime immediate 34 * below this threshold, we consider thinktime immediate
@@ -98,8 +98,6 @@ struct cfq_data {
98 struct cfq_queue *async_cfqq[2][IOPRIO_BE_NR]; 98 struct cfq_queue *async_cfqq[2][IOPRIO_BE_NR];
99 struct cfq_queue *async_idle_cfqq; 99 struct cfq_queue *async_idle_cfqq;
100 100
101 struct timer_list idle_class_timer;
102
103 sector_t last_position; 101 sector_t last_position;
104 unsigned long last_end_request; 102 unsigned long last_end_request;
105 103
@@ -384,12 +382,15 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2)
384/* 382/*
385 * The below is leftmost cache rbtree addon 383 * The below is leftmost cache rbtree addon
386 */ 384 */
387static struct rb_node *cfq_rb_first(struct cfq_rb_root *root) 385static struct cfq_queue *cfq_rb_first(struct cfq_rb_root *root)
388{ 386{
389 if (!root->left) 387 if (!root->left)
390 root->left = rb_first(&root->rb); 388 root->left = rb_first(&root->rb);
391 389
392 return root->left; 390 if (root->left)
391 return rb_entry(root->left, struct cfq_queue, rb_node);
392
393 return NULL;
393} 394}
394 395
395static void cfq_rb_erase(struct rb_node *n, struct cfq_rb_root *root) 396static void cfq_rb_erase(struct rb_node *n, struct cfq_rb_root *root)
@@ -446,12 +447,20 @@ static unsigned long cfq_slice_offset(struct cfq_data *cfqd,
446static void cfq_service_tree_add(struct cfq_data *cfqd, 447static void cfq_service_tree_add(struct cfq_data *cfqd,
447 struct cfq_queue *cfqq, int add_front) 448 struct cfq_queue *cfqq, int add_front)
448{ 449{
449 struct rb_node **p = &cfqd->service_tree.rb.rb_node; 450 struct rb_node **p, *parent;
450 struct rb_node *parent = NULL; 451 struct cfq_queue *__cfqq;
451 unsigned long rb_key; 452 unsigned long rb_key;
452 int left; 453 int left;
453 454
454 if (!add_front) { 455 if (cfq_class_idle(cfqq)) {
456 rb_key = CFQ_IDLE_DELAY;
457 parent = rb_last(&cfqd->service_tree.rb);
458 if (parent && parent != &cfqq->rb_node) {
459 __cfqq = rb_entry(parent, struct cfq_queue, rb_node);
460 rb_key += __cfqq->rb_key;
461 } else
462 rb_key += jiffies;
463 } else if (!add_front) {
455 rb_key = cfq_slice_offset(cfqd, cfqq) + jiffies; 464 rb_key = cfq_slice_offset(cfqd, cfqq) + jiffies;
456 rb_key += cfqq->slice_resid; 465 rb_key += cfqq->slice_resid;
457 cfqq->slice_resid = 0; 466 cfqq->slice_resid = 0;
@@ -469,8 +478,9 @@ static void cfq_service_tree_add(struct cfq_data *cfqd,
469 } 478 }
470 479
471 left = 1; 480 left = 1;
481 parent = NULL;
482 p = &cfqd->service_tree.rb.rb_node;
472 while (*p) { 483 while (*p) {
473 struct cfq_queue *__cfqq;
474 struct rb_node **n; 484 struct rb_node **n;
475 485
476 parent = *p; 486 parent = *p;
@@ -736,11 +746,6 @@ static inline void
736__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) 746__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
737{ 747{
738 if (cfqq) { 748 if (cfqq) {
739 /*
740 * stop potential idle class queues waiting service
741 */
742 del_timer(&cfqd->idle_class_timer);
743
744 cfqq->slice_end = 0; 749 cfqq->slice_end = 0;
745 cfq_clear_cfqq_must_alloc_slice(cfqq); 750 cfq_clear_cfqq_must_alloc_slice(cfqq);
746 cfq_clear_cfqq_fifo_expire(cfqq); 751 cfq_clear_cfqq_fifo_expire(cfqq);
@@ -789,47 +794,16 @@ static inline void cfq_slice_expired(struct cfq_data *cfqd, int timed_out)
789 __cfq_slice_expired(cfqd, cfqq, timed_out); 794 __cfq_slice_expired(cfqd, cfqq, timed_out);
790} 795}
791 796
792static int start_idle_class_timer(struct cfq_data *cfqd)
793{
794 unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE;
795 unsigned long now = jiffies;
796
797 if (time_before(now, end) &&
798 time_after_eq(now, cfqd->last_end_request)) {
799 mod_timer(&cfqd->idle_class_timer, end);
800 return 1;
801 }
802
803 return 0;
804}
805
806/* 797/*
807 * Get next queue for service. Unless we have a queue preemption, 798 * Get next queue for service. Unless we have a queue preemption,
808 * we'll simply select the first cfqq in the service tree. 799 * we'll simply select the first cfqq in the service tree.
809 */ 800 */
810static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd) 801static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd)
811{ 802{
812 struct cfq_queue *cfqq;
813 struct rb_node *n;
814
815 if (RB_EMPTY_ROOT(&cfqd->service_tree.rb)) 803 if (RB_EMPTY_ROOT(&cfqd->service_tree.rb))
816 return NULL; 804 return NULL;
817 805
818 n = cfq_rb_first(&cfqd->service_tree); 806 return cfq_rb_first(&cfqd->service_tree);
819 cfqq = rb_entry(n, struct cfq_queue, rb_node);
820
821 if (cfq_class_idle(cfqq)) {
822 /*
823 * if we have idle queues and no rt or be queues had
824 * pending requests, either allow immediate service if
825 * the grace period has passed or arm the idle grace
826 * timer
827 */
828 if (start_idle_class_timer(cfqd))
829 cfqq = NULL;
830 }
831
832 return cfqq;
833} 807}
834 808
835/* 809/*
@@ -1087,14 +1061,11 @@ static inline int __cfq_forced_dispatch_cfqq(struct cfq_queue *cfqq)
1087 */ 1061 */
1088static int cfq_forced_dispatch(struct cfq_data *cfqd) 1062static int cfq_forced_dispatch(struct cfq_data *cfqd)
1089{ 1063{
1064 struct cfq_queue *cfqq;
1090 int dispatched = 0; 1065 int dispatched = 0;
1091 struct rb_node *n;
1092
1093 while ((n = cfq_rb_first(&cfqd->service_tree)) != NULL) {
1094 struct cfq_queue *cfqq = rb_entry(n, struct cfq_queue, rb_node);
1095 1066
1067 while ((cfqq = cfq_rb_first(&cfqd->service_tree)) != NULL)
1096 dispatched += __cfq_forced_dispatch_cfqq(cfqq); 1068 dispatched += __cfq_forced_dispatch_cfqq(cfqq);
1097 }
1098 1069
1099 cfq_slice_expired(cfqd, 0); 1070 cfq_slice_expired(cfqd, 0);
1100 1071
@@ -1437,15 +1408,16 @@ retry:
1437 atomic_set(&cfqq->ref, 0); 1408 atomic_set(&cfqq->ref, 0);
1438 cfqq->cfqd = cfqd; 1409 cfqq->cfqd = cfqd;
1439 1410
1440 if (is_sync) {
1441 cfq_mark_cfqq_idle_window(cfqq);
1442 cfq_mark_cfqq_sync(cfqq);
1443 }
1444
1445 cfq_mark_cfqq_prio_changed(cfqq); 1411 cfq_mark_cfqq_prio_changed(cfqq);
1446 cfq_mark_cfqq_queue_new(cfqq); 1412 cfq_mark_cfqq_queue_new(cfqq);
1447 1413
1448 cfq_init_prio_data(cfqq, ioc); 1414 cfq_init_prio_data(cfqq, ioc);
1415
1416 if (is_sync) {
1417 if (!cfq_class_idle(cfqq))
1418 cfq_mark_cfqq_idle_window(cfqq);
1419 cfq_mark_cfqq_sync(cfqq);
1420 }
1449 } 1421 }
1450 1422
1451 if (new_cfqq) 1423 if (new_cfqq)
@@ -1697,7 +1669,10 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1697{ 1669{
1698 int enable_idle; 1670 int enable_idle;
1699 1671
1700 if (!cfq_cfqq_sync(cfqq)) 1672 /*
1673 * Don't idle for async or idle io prio class
1674 */
1675 if (!cfq_cfqq_sync(cfqq) || cfq_class_idle(cfqq))
1701 return; 1676 return;
1702 1677
1703 enable_idle = cfq_cfqq_idle_window(cfqq); 1678 enable_idle = cfq_cfqq_idle_window(cfqq);
@@ -1876,7 +1851,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
1876 cfq_set_prio_slice(cfqd, cfqq); 1851 cfq_set_prio_slice(cfqd, cfqq);
1877 cfq_clear_cfqq_slice_new(cfqq); 1852 cfq_clear_cfqq_slice_new(cfqq);
1878 } 1853 }
1879 if (cfq_slice_used(cfqq)) 1854 if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq))
1880 cfq_slice_expired(cfqd, 1); 1855 cfq_slice_expired(cfqd, 1);
1881 else if (sync && RB_EMPTY_ROOT(&cfqq->sort_list)) 1856 else if (sync && RB_EMPTY_ROOT(&cfqq->sort_list))
1882 cfq_arm_slice_timer(cfqd); 1857 cfq_arm_slice_timer(cfqd);
@@ -2080,29 +2055,9 @@ out_cont:
2080 spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); 2055 spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
2081} 2056}
2082 2057
2083/*
2084 * Timer running if an idle class queue is waiting for service
2085 */
2086static void cfq_idle_class_timer(unsigned long data)
2087{
2088 struct cfq_data *cfqd = (struct cfq_data *) data;
2089 unsigned long flags;
2090
2091 spin_lock_irqsave(cfqd->queue->queue_lock, flags);
2092
2093 /*
2094 * race with a non-idle queue, reset timer
2095 */
2096 if (!start_idle_class_timer(cfqd))
2097 cfq_schedule_dispatch(cfqd);
2098
2099 spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
2100}
2101
2102static void cfq_shutdown_timer_wq(struct cfq_data *cfqd) 2058static void cfq_shutdown_timer_wq(struct cfq_data *cfqd)
2103{ 2059{
2104 del_timer_sync(&cfqd->idle_slice_timer); 2060 del_timer_sync(&cfqd->idle_slice_timer);
2105 del_timer_sync(&cfqd->idle_class_timer);
2106 kblockd_flush_work(&cfqd->unplug_work); 2061 kblockd_flush_work(&cfqd->unplug_work);
2107} 2062}
2108 2063
@@ -2167,10 +2122,6 @@ static void *cfq_init_queue(struct request_queue *q)
2167 cfqd->idle_slice_timer.function = cfq_idle_slice_timer; 2122 cfqd->idle_slice_timer.function = cfq_idle_slice_timer;
2168 cfqd->idle_slice_timer.data = (unsigned long) cfqd; 2123 cfqd->idle_slice_timer.data = (unsigned long) cfqd;
2169 2124
2170 init_timer(&cfqd->idle_class_timer);
2171 cfqd->idle_class_timer.function = cfq_idle_class_timer;
2172 cfqd->idle_class_timer.data = (unsigned long) cfqd;
2173
2174 INIT_WORK(&cfqd->unplug_work, cfq_kick_queue); 2125 INIT_WORK(&cfqd->unplug_work, cfq_kick_queue);
2175 2126
2176 cfqd->last_end_request = jiffies; 2127 cfqd->last_end_request = jiffies;