diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 11ce6aaf1bd0..8e9d84825e1c 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -133,6 +133,7 @@ struct cfq_data { | |||
133 | mempool_t *crq_pool; | 133 | mempool_t *crq_pool; |
134 | 134 | ||
135 | int rq_in_driver; | 135 | int rq_in_driver; |
136 | int hw_tag; | ||
136 | 137 | ||
137 | /* | 138 | /* |
138 | * schedule slice state info | 139 | * schedule slice state info |
@@ -500,10 +501,13 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) | |||
500 | 501 | ||
501 | /* | 502 | /* |
502 | * if queue was preempted, just add to front to be fair. busy_rr | 503 | * if queue was preempted, just add to front to be fair. busy_rr |
503 | * isn't sorted. | 504 | * isn't sorted, but insert at the back for fairness. |
504 | */ | 505 | */ |
505 | if (preempted || list == &cfqd->busy_rr) { | 506 | if (preempted || list == &cfqd->busy_rr) { |
506 | list_add(&cfqq->cfq_list, list); | 507 | if (preempted) |
508 | list = list->prev; | ||
509 | |||
510 | list_add_tail(&cfqq->cfq_list, list); | ||
507 | return; | 511 | return; |
508 | } | 512 | } |
509 | 513 | ||
@@ -664,6 +668,15 @@ static void cfq_activate_request(request_queue_t *q, struct request *rq) | |||
664 | struct cfq_data *cfqd = q->elevator->elevator_data; | 668 | struct cfq_data *cfqd = q->elevator->elevator_data; |
665 | 669 | ||
666 | cfqd->rq_in_driver++; | 670 | cfqd->rq_in_driver++; |
671 | |||
672 | /* | ||
673 | * If the depth is larger 1, it really could be queueing. But lets | ||
674 | * make the mark a little higher - idling could still be good for | ||
675 | * low queueing, and a low queueing number could also just indicate | ||
676 | * a SCSI mid layer like behaviour where limit+1 is often seen. | ||
677 | */ | ||
678 | if (!cfqd->hw_tag && cfqd->rq_in_driver > 4) | ||
679 | cfqd->hw_tag = 1; | ||
667 | } | 680 | } |
668 | 681 | ||
669 | static void cfq_deactivate_request(request_queue_t *q, struct request *rq) | 682 | static void cfq_deactivate_request(request_queue_t *q, struct request *rq) |
@@ -879,6 +892,13 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) | |||
879 | cfqq = list_entry_cfqq(cfqd->cur_rr.next); | 892 | cfqq = list_entry_cfqq(cfqd->cur_rr.next); |
880 | 893 | ||
881 | /* | 894 | /* |
895 | * If no new queues are available, check if the busy list has some | ||
896 | * before falling back to idle io. | ||
897 | */ | ||
898 | if (!cfqq && !list_empty(&cfqd->busy_rr)) | ||
899 | cfqq = list_entry_cfqq(cfqd->busy_rr.next); | ||
900 | |||
901 | /* | ||
882 | * if we have idle queues and no rt or be queues had pending | 902 | * if we have idle queues and no rt or be queues had pending |
883 | * requests, either allow immediate service if the grace period | 903 | * requests, either allow immediate service if the grace period |
884 | * has passed or arm the idle grace timer | 904 | * has passed or arm the idle grace timer |
@@ -1458,7 +1478,8 @@ retry: | |||
1458 | * set ->slice_left to allow preemption for a new process | 1478 | * set ->slice_left to allow preemption for a new process |
1459 | */ | 1479 | */ |
1460 | cfqq->slice_left = 2 * cfqd->cfq_slice_idle; | 1480 | cfqq->slice_left = 2 * cfqd->cfq_slice_idle; |
1461 | cfq_mark_cfqq_idle_window(cfqq); | 1481 | if (!cfqd->hw_tag) |
1482 | cfq_mark_cfqq_idle_window(cfqq); | ||
1462 | cfq_mark_cfqq_prio_changed(cfqq); | 1483 | cfq_mark_cfqq_prio_changed(cfqq); |
1463 | cfq_init_prio_data(cfqq); | 1484 | cfq_init_prio_data(cfqq); |
1464 | } | 1485 | } |
@@ -1649,7 +1670,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1649 | { | 1670 | { |
1650 | int enable_idle = cfq_cfqq_idle_window(cfqq); | 1671 | int enable_idle = cfq_cfqq_idle_window(cfqq); |
1651 | 1672 | ||
1652 | if (!cic->ioc->task || !cfqd->cfq_slice_idle) | 1673 | if (!cic->ioc->task || !cfqd->cfq_slice_idle || cfqd->hw_tag) |
1653 | enable_idle = 0; | 1674 | enable_idle = 0; |
1654 | else if (sample_valid(cic->ttime_samples)) { | 1675 | else if (sample_valid(cic->ttime_samples)) { |
1655 | if (cic->ttime_mean > cfqd->cfq_slice_idle) | 1676 | if (cic->ttime_mean > cfqd->cfq_slice_idle) |
@@ -1740,14 +1761,24 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1740 | 1761 | ||
1741 | cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); | 1762 | cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); |
1742 | 1763 | ||
1764 | cic = crq->io_context; | ||
1765 | |||
1743 | /* | 1766 | /* |
1744 | * we never wait for an async request and we don't allow preemption | 1767 | * we never wait for an async request and we don't allow preemption |
1745 | * of an async request. so just return early | 1768 | * of an async request. so just return early |
1746 | */ | 1769 | */ |
1747 | if (!cfq_crq_is_sync(crq)) | 1770 | if (!cfq_crq_is_sync(crq)) { |
1771 | /* | ||
1772 | * sync process issued an async request, if it's waiting | ||
1773 | * then expire it and kick rq handling. | ||
1774 | */ | ||
1775 | if (cic == cfqd->active_cic && | ||
1776 | del_timer(&cfqd->idle_slice_timer)) { | ||
1777 | cfq_slice_expired(cfqd, 0); | ||
1778 | cfq_start_queueing(cfqd, cfqq); | ||
1779 | } | ||
1748 | return; | 1780 | return; |
1749 | 1781 | } | |
1750 | cic = crq->io_context; | ||
1751 | 1782 | ||
1752 | cfq_update_io_thinktime(cfqd, cic); | 1783 | cfq_update_io_thinktime(cfqd, cic); |
1753 | cfq_update_io_seektime(cfqd, cic, crq); | 1784 | cfq_update_io_seektime(cfqd, cic, crq); |
@@ -2165,10 +2196,9 @@ static void cfq_idle_class_timer(unsigned long data) | |||
2165 | * race with a non-idle queue, reset timer | 2196 | * race with a non-idle queue, reset timer |
2166 | */ | 2197 | */ |
2167 | end = cfqd->last_end_request + CFQ_IDLE_GRACE; | 2198 | end = cfqd->last_end_request + CFQ_IDLE_GRACE; |
2168 | if (!time_after_eq(jiffies, end)) { | 2199 | if (!time_after_eq(jiffies, end)) |
2169 | cfqd->idle_class_timer.expires = end; | 2200 | mod_timer(&cfqd->idle_class_timer, end); |
2170 | add_timer(&cfqd->idle_class_timer); | 2201 | else |
2171 | } else | ||
2172 | cfq_schedule_dispatch(cfqd); | 2202 | cfq_schedule_dispatch(cfqd); |
2173 | 2203 | ||
2174 | spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); | 2204 | spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); |