aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/cfq-iosched.c166
1 files changed, 90 insertions, 76 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 9e809345f71a..a0102a507dae 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -160,6 +160,7 @@ struct cfq_queue {
160 160
161 unsigned long slice_end; 161 unsigned long slice_end;
162 long slice_resid; 162 long slice_resid;
163 unsigned int slice_dispatch;
163 164
164 /* pending metadata requests */ 165 /* pending metadata requests */
165 int meta_pending; 166 int meta_pending;
@@ -774,10 +775,16 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd,
774 if (cfqq) { 775 if (cfqq) {
775 cfq_log_cfqq(cfqd, cfqq, "set_active"); 776 cfq_log_cfqq(cfqd, cfqq, "set_active");
776 cfqq->slice_end = 0; 777 cfqq->slice_end = 0;
778 cfqq->slice_dispatch = 0;
779
780 cfq_clear_cfqq_must_dispatch(cfqq);
781 cfq_clear_cfqq_wait_request(cfqq);
777 cfq_clear_cfqq_must_alloc_slice(cfqq); 782 cfq_clear_cfqq_must_alloc_slice(cfqq);
778 cfq_clear_cfqq_fifo_expire(cfqq); 783 cfq_clear_cfqq_fifo_expire(cfqq);
779 cfq_mark_cfqq_slice_new(cfqq); 784 cfq_mark_cfqq_slice_new(cfqq);
780 cfq_clear_cfqq_queue_new(cfqq); 785 cfq_clear_cfqq_queue_new(cfqq);
786
787 del_timer(&cfqd->idle_slice_timer);
781 } 788 }
782 789
783 cfqd->active_queue = cfqq; 790 cfqd->active_queue = cfqq;
@@ -1053,66 +1060,6 @@ keep_queue:
1053 return cfqq; 1060 return cfqq;
1054} 1061}
1055 1062
1056/*
1057 * Dispatch some requests from cfqq, moving them to the request queue
1058 * dispatch list.
1059 */
1060static int
1061__cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1062 int max_dispatch)
1063{
1064 int dispatched = 0;
1065
1066 BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
1067
1068 do {
1069 struct request *rq;
1070
1071 /*
1072 * follow expired path, else get first next available
1073 */
1074 rq = cfq_check_fifo(cfqq);
1075 if (rq == NULL)
1076 rq = cfqq->next_rq;
1077
1078 /*
1079 * finally, insert request into driver dispatch list
1080 */
1081 cfq_dispatch_insert(cfqd->queue, rq);
1082
1083 dispatched++;
1084
1085 if (!cfqd->active_cic) {
1086 atomic_inc(&RQ_CIC(rq)->ioc->refcount);
1087 cfqd->active_cic = RQ_CIC(rq);
1088 }
1089
1090 if (RB_EMPTY_ROOT(&cfqq->sort_list))
1091 break;
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
1100 } while (dispatched < max_dispatch);
1101
1102 /*
1103 * expire an async queue immediately if it has used up its slice. idle
1104 * queue always expire after 1 dispatch round.
1105 */
1106 if (cfqd->busy_queues > 1 && ((!cfq_cfqq_sync(cfqq) &&
1107 dispatched >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
1108 cfq_class_idle(cfqq))) {
1109 cfqq->slice_end = jiffies + 1;
1110 cfq_slice_expired(cfqd, 0);
1111 }
1112
1113 return dispatched;
1114}
1115
1116static int __cfq_forced_dispatch_cfqq(struct cfq_queue *cfqq) 1063static int __cfq_forced_dispatch_cfqq(struct cfq_queue *cfqq)
1117{ 1064{
1118 int dispatched = 0; 1065 int dispatched = 0;
@@ -1146,11 +1093,45 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd)
1146 return dispatched; 1093 return dispatched;
1147} 1094}
1148 1095
1096/*
1097 * Dispatch a request from cfqq, moving them to the request queue
1098 * dispatch list.
1099 */
1100static void cfq_dispatch_request(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1101{
1102 struct request *rq;
1103
1104 BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
1105
1106 /*
1107 * follow expired path, else get first next available
1108 */
1109 rq = cfq_check_fifo(cfqq);
1110 if (!rq)
1111 rq = cfqq->next_rq;
1112
1113 /*
1114 * insert request into driver dispatch list
1115 */
1116 cfq_dispatch_insert(cfqd->queue, rq);
1117
1118 if (!cfqd->active_cic) {
1119 struct cfq_io_context *cic = RQ_CIC(rq);
1120
1121 atomic_inc(&cic->ioc->refcount);
1122 cfqd->active_cic = cic;
1123 }
1124}
1125
1126/*
1127 * Find the cfqq that we need to service and move a request from that to the
1128 * dispatch list
1129 */
1149static int cfq_dispatch_requests(struct request_queue *q, int force) 1130static int cfq_dispatch_requests(struct request_queue *q, int force)
1150{ 1131{
1151 struct cfq_data *cfqd = q->elevator->elevator_data; 1132 struct cfq_data *cfqd = q->elevator->elevator_data;
1152 struct cfq_queue *cfqq; 1133 struct cfq_queue *cfqq;
1153 int dispatched; 1134 unsigned int max_dispatch;
1154 1135
1155 if (!cfqd->busy_queues) 1136 if (!cfqd->busy_queues)
1156 return 0; 1137 return 0;
@@ -1158,29 +1139,62 @@ static int cfq_dispatch_requests(struct request_queue *q, int force)
1158 if (unlikely(force)) 1139 if (unlikely(force))
1159 return cfq_forced_dispatch(cfqd); 1140 return cfq_forced_dispatch(cfqd);
1160 1141
1161 dispatched = 0; 1142 cfqq = cfq_select_queue(cfqd);
1162 while ((cfqq = cfq_select_queue(cfqd)) != NULL) { 1143 if (!cfqq)
1163 int max_dispatch; 1144 return 0;
1145
1146 /*
1147 * If this is an async queue and we have sync IO in flight, let it wait
1148 */
1149 if (cfqd->sync_flight && !cfq_cfqq_sync(cfqq))
1150 return 0;
1164 1151
1165 max_dispatch = cfqd->cfq_quantum; 1152 max_dispatch = cfqd->cfq_quantum;
1153 if (cfq_class_idle(cfqq))
1154 max_dispatch = 1;
1155
1156 /*
1157 * Does this cfqq already have too much IO in flight?
1158 */
1159 if (cfqq->dispatched >= max_dispatch) {
1160 /*
1161 * idle queue must always only have a single IO in flight
1162 */
1166 if (cfq_class_idle(cfqq)) 1163 if (cfq_class_idle(cfqq))
1167 max_dispatch = 1; 1164 return 0;
1168 1165
1169 if (cfqq->dispatched >= max_dispatch && cfqd->busy_queues > 1) 1166 /*
1170 break; 1167 * We have other queues, don't allow more IO from this one
1168 */
1169 if (cfqd->busy_queues > 1)
1170 return 0;
1171 1171
1172 if (cfqd->sync_flight && !cfq_cfqq_sync(cfqq)) 1172 /*
1173 break; 1173 * we are the only queue, allow up to 4 times of 'quantum'
1174 */
1175 if (cfqq->dispatched >= 4 * max_dispatch)
1176 return 0;
1177 }
1174 1178
1175 cfq_clear_cfqq_must_dispatch(cfqq); 1179 /*
1176 cfq_clear_cfqq_wait_request(cfqq); 1180 * Dispatch a request from this cfqq
1177 del_timer(&cfqd->idle_slice_timer); 1181 */
1182 cfq_dispatch_request(cfqd, cfqq);
1183 cfqq->slice_dispatch++;
1178 1184
1179 dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); 1185 /*
1186 * expire an async queue immediately if it has used up its slice. idle
1187 * queue always expire after 1 dispatch round.
1188 */
1189 if (cfqd->busy_queues > 1 && ((!cfq_cfqq_sync(cfqq) &&
1190 cfqq->slice_dispatch >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
1191 cfq_class_idle(cfqq))) {
1192 cfqq->slice_end = jiffies + 1;
1193 cfq_slice_expired(cfqd, 0);
1180 } 1194 }
1181 1195
1182 cfq_log(cfqd, "dispatched=%d", dispatched); 1196 cfq_log(cfqd, "dispatched a request");
1183 return dispatched; 1197 return 1;
1184} 1198}
1185 1199
1186/* 1200/*