aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorDivyesh Shah <dpshah@google.com>2009-01-30 06:46:41 -0500
committerJens Axboe <jens.axboe@oracle.com>2009-01-30 06:47:33 -0500
commit3a9a3f6cc55418dd1525e636dccbbe13c394f652 (patch)
treeb23c46b8ecec0a338e4e81454e482f7dcd3ded0c /block
parentbc58ba9468d94d62c56ab9b47173583ec140b165 (diff)
cfq-iosched: Allow RT requests to pre-empt ongoing BE timeslice
This patch adds the ability to pre-empt an ongoing BE timeslice when a RT request is waiting for the current timeslice to complete. This reduces the wait time to disk for RT requests from an upper bound of 4 (current value of cfq_quantum) to 1 disk request. Applied Jens' suggeested changes to avoid the rb lookup and use !cfq_class_rt() and retested. Latency(secs) for the RT task when doing sequential reads from 10G file. | only RT | RT + BE | RT + BE + this patch small (512 byte) reads | 143 | 163 | 145 large (1Mb) reads | 142 | 158 | 146 Signed-off-by: Divyesh Shah <dpshah@google.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r--block/cfq-iosched.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index e8525fa72823..664ebfd092ec 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -84,6 +84,11 @@ struct cfq_data {
84 */ 84 */
85 struct cfq_rb_root service_tree; 85 struct cfq_rb_root service_tree;
86 unsigned int busy_queues; 86 unsigned int busy_queues;
87 /*
88 * Used to track any pending rt requests so we can pre-empt current
89 * non-RT cfqq in service when this value is non-zero.
90 */
91 unsigned int busy_rt_queues;
87 92
88 int rq_in_driver; 93 int rq_in_driver;
89 int sync_flight; 94 int sync_flight;
@@ -562,6 +567,8 @@ static void cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
562 BUG_ON(cfq_cfqq_on_rr(cfqq)); 567 BUG_ON(cfq_cfqq_on_rr(cfqq));
563 cfq_mark_cfqq_on_rr(cfqq); 568 cfq_mark_cfqq_on_rr(cfqq);
564 cfqd->busy_queues++; 569 cfqd->busy_queues++;
570 if (cfq_class_rt(cfqq))
571 cfqd->busy_rt_queues++;
565 572
566 cfq_resort_rr_list(cfqd, cfqq); 573 cfq_resort_rr_list(cfqd, cfqq);
567} 574}
@@ -581,6 +588,8 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
581 588
582 BUG_ON(!cfqd->busy_queues); 589 BUG_ON(!cfqd->busy_queues);
583 cfqd->busy_queues--; 590 cfqd->busy_queues--;
591 if (cfq_class_rt(cfqq))
592 cfqd->busy_rt_queues--;
584} 593}
585 594
586/* 595/*
@@ -1005,6 +1014,20 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
1005 goto expire; 1014 goto expire;
1006 1015
1007 /* 1016 /*
1017 * If we have a RT cfqq waiting, then we pre-empt the current non-rt
1018 * cfqq.
1019 */
1020 if (!cfq_class_rt(cfqq) && cfqd->busy_rt_queues) {
1021 /*
1022 * We simulate this as cfqq timed out so that it gets to bank
1023 * the remaining of its time slice.
1024 */
1025 cfq_log_cfqq(cfqd, cfqq, "preempt");
1026 cfq_slice_expired(cfqd, 1);
1027 goto new_queue;
1028 }
1029
1030 /*
1008 * The active queue has requests and isn't expired, allow it to 1031 * The active queue has requests and isn't expired, allow it to
1009 * dispatch. 1032 * dispatch.
1010 */ 1033 */
@@ -1067,6 +1090,13 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1067 if (RB_EMPTY_ROOT(&cfqq->sort_list)) 1090 if (RB_EMPTY_ROOT(&cfqq->sort_list))
1068 break; 1091 break;
1069 1092
1093 /*
1094 * If there is a non-empty RT cfqq waiting for current
1095 * cfqq's timeslice to complete, pre-empt this cfqq
1096 */
1097 if (!cfq_class_rt(cfqq) && cfqd->busy_rt_queues)
1098 break;
1099
1070 } while (dispatched < max_dispatch); 1100 } while (dispatched < max_dispatch);
1071 1101
1072 /* 1102 /*
@@ -1801,6 +1831,12 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
1801 if (rq_is_meta(rq) && !cfqq->meta_pending) 1831 if (rq_is_meta(rq) && !cfqq->meta_pending)
1802 return 1; 1832 return 1;
1803 1833
1834 /*
1835 * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice.
1836 */
1837 if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
1838 return 1;
1839
1804 if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq)) 1840 if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
1805 return 0; 1841 return 0;
1806 1842
@@ -1870,7 +1906,8 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1870 /* 1906 /*
1871 * not the active queue - expire current slice if it is 1907 * not the active queue - expire current slice if it is
1872 * idle and has expired it's mean thinktime or this new queue 1908 * idle and has expired it's mean thinktime or this new queue
1873 * has some old slice time left and is of higher priority 1909 * has some old slice time left and is of higher priority or
1910 * this new queue is RT and the current one is BE
1874 */ 1911 */
1875 cfq_preempt_queue(cfqd, cfqq); 1912 cfq_preempt_queue(cfqd, cfqq);
1876 cfq_mark_cfqq_must_dispatch(cfqq); 1913 cfq_mark_cfqq_must_dispatch(cfqq);