aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/cfq-iosched.c53
1 files changed, 22 insertions, 31 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 0452108a932e..c6e649f3cae7 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -152,7 +152,6 @@ struct cfq_queue {
152 unsigned long slice_start; 152 unsigned long slice_start;
153 unsigned long slice_end; 153 unsigned long slice_end;
154 unsigned long slice_left; 154 unsigned long slice_left;
155 unsigned long service_last;
156 155
157 /* number of requests that are on the dispatch list */ 156 /* number of requests that are on the dispatch list */
158 int on_dispatch[2]; 157 int on_dispatch[2];
@@ -174,6 +173,7 @@ enum cfqq_state_flags {
174 CFQ_CFQQ_FLAG_fifo_expire, 173 CFQ_CFQQ_FLAG_fifo_expire,
175 CFQ_CFQQ_FLAG_idle_window, 174 CFQ_CFQQ_FLAG_idle_window,
176 CFQ_CFQQ_FLAG_prio_changed, 175 CFQ_CFQQ_FLAG_prio_changed,
176 CFQ_CFQQ_FLAG_queue_new,
177}; 177};
178 178
179#define CFQ_CFQQ_FNS(name) \ 179#define CFQ_CFQQ_FNS(name) \
@@ -198,6 +198,7 @@ CFQ_CFQQ_FNS(must_dispatch);
198CFQ_CFQQ_FNS(fifo_expire); 198CFQ_CFQQ_FNS(fifo_expire);
199CFQ_CFQQ_FNS(idle_window); 199CFQ_CFQQ_FNS(idle_window);
200CFQ_CFQQ_FNS(prio_changed); 200CFQ_CFQQ_FNS(prio_changed);
201CFQ_CFQQ_FNS(queue_new);
201#undef CFQ_CFQQ_FNS 202#undef CFQ_CFQQ_FNS
202 203
203static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); 204static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
@@ -350,7 +351,7 @@ cfq_find_next_rq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
350static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) 351static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
351{ 352{
352 struct cfq_data *cfqd = cfqq->cfqd; 353 struct cfq_data *cfqd = cfqq->cfqd;
353 struct list_head *list, *entry; 354 struct list_head *list;
354 355
355 BUG_ON(!cfq_cfqq_on_rr(cfqq)); 356 BUG_ON(!cfq_cfqq_on_rr(cfqq));
356 357
@@ -375,31 +376,26 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
375 } 376 }
376 377
377 /* 378 /*
378 * if queue was preempted, just add to front to be fair. busy_rr 379 * If this queue was preempted or is new (never been serviced), let
379 * isn't sorted, but insert at the back for fairness. 380 * it be added first for fairness but beind other new queues.
381 * Otherwise, just add to the back of the list.
380 */ 382 */
381 if (preempted || list == &cfqd->busy_rr) { 383 if (preempted || cfq_cfqq_queue_new(cfqq)) {
382 if (preempted) 384 struct list_head *n = list;
383 list = list->prev; 385 struct cfq_queue *__cfqq;
384 386
385 list_add_tail(&cfqq->cfq_list, list); 387 while (n->next != list) {
386 return; 388 __cfqq = list_entry_cfqq(n->next);
387 } 389 if (!cfq_cfqq_queue_new(__cfqq))
390 break;
388 391
389 /* 392 n = n->next;
390 * sort by when queue was last serviced 393 }
391 */
392 entry = list;
393 while ((entry = entry->prev) != list) {
394 struct cfq_queue *__cfqq = list_entry_cfqq(entry);
395 394
396 if (!__cfqq->service_last) 395 list = n;
397 break;
398 if (time_before(__cfqq->service_last, cfqq->service_last))
399 break;
400 } 396 }
401 397
402 list_add(&cfqq->cfq_list, entry); 398 list_add_tail(&cfqq->cfq_list, list);
403} 399}
404 400
405/* 401/*
@@ -591,13 +587,12 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
591 if (cfq_cfqq_wait_request(cfqq)) 587 if (cfq_cfqq_wait_request(cfqq))
592 del_timer(&cfqd->idle_slice_timer); 588 del_timer(&cfqd->idle_slice_timer);
593 589
594 if (!preempted && !cfq_cfqq_dispatched(cfqq)) { 590 if (!preempted && !cfq_cfqq_dispatched(cfqq))
595 cfqq->service_last = now;
596 cfq_schedule_dispatch(cfqd); 591 cfq_schedule_dispatch(cfqd);
597 }
598 592
599 cfq_clear_cfqq_must_dispatch(cfqq); 593 cfq_clear_cfqq_must_dispatch(cfqq);
600 cfq_clear_cfqq_wait_request(cfqq); 594 cfq_clear_cfqq_wait_request(cfqq);
595 cfq_clear_cfqq_queue_new(cfqq);
601 596
602 /* 597 /*
603 * store what was left of this slice, if the queue idled out 598 * store what was left of this slice, if the queue idled out
@@ -1297,13 +1292,13 @@ retry:
1297 hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); 1292 hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
1298 atomic_set(&cfqq->ref, 0); 1293 atomic_set(&cfqq->ref, 0);
1299 cfqq->cfqd = cfqd; 1294 cfqq->cfqd = cfqd;
1300 cfqq->service_last = 0;
1301 /* 1295 /*
1302 * set ->slice_left to allow preemption for a new process 1296 * set ->slice_left to allow preemption for a new process
1303 */ 1297 */
1304 cfqq->slice_left = 2 * cfqd->cfq_slice_idle; 1298 cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
1305 cfq_mark_cfqq_idle_window(cfqq); 1299 cfq_mark_cfqq_idle_window(cfqq);
1306 cfq_mark_cfqq_prio_changed(cfqq); 1300 cfq_mark_cfqq_prio_changed(cfqq);
1301 cfq_mark_cfqq_queue_new(cfqq);
1307 cfq_init_prio_data(cfqq); 1302 cfq_init_prio_data(cfqq);
1308 } 1303 }
1309 1304
@@ -1672,12 +1667,8 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq)
1672 if (!cfq_class_idle(cfqq)) 1667 if (!cfq_class_idle(cfqq))
1673 cfqd->last_end_request = now; 1668 cfqd->last_end_request = now;
1674 1669
1675 if (!cfq_cfqq_dispatched(cfqq)) { 1670 if (!cfq_cfqq_dispatched(cfqq) && cfq_cfqq_on_rr(cfqq))
1676 if (cfq_cfqq_on_rr(cfqq)) { 1671 cfq_resort_rr_list(cfqq, 0);
1677 cfqq->service_last = now;
1678 cfq_resort_rr_list(cfqq, 0);
1679 }
1680 }
1681 1672
1682 if (sync) 1673 if (sync)
1683 RQ_CIC(rq)->last_end_request = now; 1674 RQ_CIC(rq)->last_end_request = now;