diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/cfq-iosched.c | 53 |
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); | |||
198 | CFQ_CFQQ_FNS(fifo_expire); | 198 | CFQ_CFQQ_FNS(fifo_expire); |
199 | CFQ_CFQQ_FNS(idle_window); | 199 | CFQ_CFQQ_FNS(idle_window); |
200 | CFQ_CFQQ_FNS(prio_changed); | 200 | CFQ_CFQQ_FNS(prio_changed); |
201 | CFQ_CFQQ_FNS(queue_new); | ||
201 | #undef CFQ_CFQQ_FNS | 202 | #undef CFQ_CFQQ_FNS |
202 | 203 | ||
203 | static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); | 204 | static 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, | |||
350 | static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) | 351 | static 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; |