diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 8e0b86a9111a..b6e095c7ef5e 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -886,7 +886,7 @@ static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq) | |||
886 | } | 886 | } |
887 | 887 | ||
888 | static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, | 888 | static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, |
889 | struct cfq_queue *cfqq) | 889 | struct cfq_queue *cfqq, bool forced) |
890 | { | 890 | { |
891 | struct cfq_rb_root *st = &cfqd->grp_service_tree; | 891 | struct cfq_rb_root *st = &cfqd->grp_service_tree; |
892 | unsigned int used_sl, charge_sl; | 892 | unsigned int used_sl, charge_sl; |
@@ -916,6 +916,7 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, | |||
916 | cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime, | 916 | cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime, |
917 | st->min_vdisktime); | 917 | st->min_vdisktime); |
918 | blkiocg_update_timeslice_used(&cfqg->blkg, used_sl); | 918 | blkiocg_update_timeslice_used(&cfqg->blkg, used_sl); |
919 | blkiocg_set_start_empty_time(&cfqg->blkg, forced); | ||
919 | } | 920 | } |
920 | 921 | ||
921 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | 922 | #ifdef CONFIG_CFQ_GROUP_IOSCHED |
@@ -1528,6 +1529,12 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq, | |||
1528 | return cfqq == RQ_CFQQ(rq); | 1529 | return cfqq == RQ_CFQQ(rq); |
1529 | } | 1530 | } |
1530 | 1531 | ||
1532 | static inline void cfq_del_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
1533 | { | ||
1534 | del_timer(&cfqd->idle_slice_timer); | ||
1535 | blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg); | ||
1536 | } | ||
1537 | |||
1531 | static void __cfq_set_active_queue(struct cfq_data *cfqd, | 1538 | static void __cfq_set_active_queue(struct cfq_data *cfqd, |
1532 | struct cfq_queue *cfqq) | 1539 | struct cfq_queue *cfqq) |
1533 | { | 1540 | { |
@@ -1547,7 +1554,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd, | |||
1547 | cfq_clear_cfqq_fifo_expire(cfqq); | 1554 | cfq_clear_cfqq_fifo_expire(cfqq); |
1548 | cfq_mark_cfqq_slice_new(cfqq); | 1555 | cfq_mark_cfqq_slice_new(cfqq); |
1549 | 1556 | ||
1550 | del_timer(&cfqd->idle_slice_timer); | 1557 | cfq_del_timer(cfqd, cfqq); |
1551 | } | 1558 | } |
1552 | 1559 | ||
1553 | cfqd->active_queue = cfqq; | 1560 | cfqd->active_queue = cfqq; |
@@ -1558,12 +1565,12 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd, | |||
1558 | */ | 1565 | */ |
1559 | static void | 1566 | static void |
1560 | __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | 1567 | __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
1561 | bool timed_out) | 1568 | bool timed_out, bool forced) |
1562 | { | 1569 | { |
1563 | cfq_log_cfqq(cfqd, cfqq, "slice expired t=%d", timed_out); | 1570 | cfq_log_cfqq(cfqd, cfqq, "slice expired t=%d", timed_out); |
1564 | 1571 | ||
1565 | if (cfq_cfqq_wait_request(cfqq)) | 1572 | if (cfq_cfqq_wait_request(cfqq)) |
1566 | del_timer(&cfqd->idle_slice_timer); | 1573 | cfq_del_timer(cfqd, cfqq); |
1567 | 1574 | ||
1568 | cfq_clear_cfqq_wait_request(cfqq); | 1575 | cfq_clear_cfqq_wait_request(cfqq); |
1569 | cfq_clear_cfqq_wait_busy(cfqq); | 1576 | cfq_clear_cfqq_wait_busy(cfqq); |
@@ -1585,7 +1592,7 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1585 | cfq_log_cfqq(cfqd, cfqq, "resid=%ld", cfqq->slice_resid); | 1592 | cfq_log_cfqq(cfqd, cfqq, "resid=%ld", cfqq->slice_resid); |
1586 | } | 1593 | } |
1587 | 1594 | ||
1588 | cfq_group_served(cfqd, cfqq->cfqg, cfqq); | 1595 | cfq_group_served(cfqd, cfqq->cfqg, cfqq, forced); |
1589 | 1596 | ||
1590 | if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list)) | 1597 | if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list)) |
1591 | cfq_del_cfqq_rr(cfqd, cfqq); | 1598 | cfq_del_cfqq_rr(cfqd, cfqq); |
@@ -1604,12 +1611,13 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1604 | } | 1611 | } |
1605 | } | 1612 | } |
1606 | 1613 | ||
1607 | static inline void cfq_slice_expired(struct cfq_data *cfqd, bool timed_out) | 1614 | static inline void cfq_slice_expired(struct cfq_data *cfqd, bool timed_out, |
1615 | bool forced) | ||
1608 | { | 1616 | { |
1609 | struct cfq_queue *cfqq = cfqd->active_queue; | 1617 | struct cfq_queue *cfqq = cfqd->active_queue; |
1610 | 1618 | ||
1611 | if (cfqq) | 1619 | if (cfqq) |
1612 | __cfq_slice_expired(cfqd, cfqq, timed_out); | 1620 | __cfq_slice_expired(cfqd, cfqq, timed_out, forced); |
1613 | } | 1621 | } |
1614 | 1622 | ||
1615 | /* | 1623 | /* |
@@ -1865,6 +1873,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
1865 | sl = cfqd->cfq_slice_idle; | 1873 | sl = cfqd->cfq_slice_idle; |
1866 | 1874 | ||
1867 | mod_timer(&cfqd->idle_slice_timer, jiffies + sl); | 1875 | mod_timer(&cfqd->idle_slice_timer, jiffies + sl); |
1876 | blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg); | ||
1868 | cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl); | 1877 | cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl); |
1869 | } | 1878 | } |
1870 | 1879 | ||
@@ -2176,7 +2185,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) | |||
2176 | } | 2185 | } |
2177 | 2186 | ||
2178 | expire: | 2187 | expire: |
2179 | cfq_slice_expired(cfqd, 0); | 2188 | cfq_slice_expired(cfqd, 0, false); |
2180 | new_queue: | 2189 | new_queue: |
2181 | /* | 2190 | /* |
2182 | * Current queue expired. Check if we have to switch to a new | 2191 | * Current queue expired. Check if we have to switch to a new |
@@ -2202,7 +2211,7 @@ static int __cfq_forced_dispatch_cfqq(struct cfq_queue *cfqq) | |||
2202 | BUG_ON(!list_empty(&cfqq->fifo)); | 2211 | BUG_ON(!list_empty(&cfqq->fifo)); |
2203 | 2212 | ||
2204 | /* By default cfqq is not expired if it is empty. Do it explicitly */ | 2213 | /* By default cfqq is not expired if it is empty. Do it explicitly */ |
2205 | __cfq_slice_expired(cfqq->cfqd, cfqq, 0); | 2214 | __cfq_slice_expired(cfqq->cfqd, cfqq, 0, true); |
2206 | return dispatched; | 2215 | return dispatched; |
2207 | } | 2216 | } |
2208 | 2217 | ||
@@ -2218,7 +2227,7 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd) | |||
2218 | while ((cfqq = cfq_get_next_queue_forced(cfqd)) != NULL) | 2227 | while ((cfqq = cfq_get_next_queue_forced(cfqd)) != NULL) |
2219 | dispatched += __cfq_forced_dispatch_cfqq(cfqq); | 2228 | dispatched += __cfq_forced_dispatch_cfqq(cfqq); |
2220 | 2229 | ||
2221 | cfq_slice_expired(cfqd, 0); | 2230 | cfq_slice_expired(cfqd, 0, true); |
2222 | BUG_ON(cfqd->busy_queues); | 2231 | BUG_ON(cfqd->busy_queues); |
2223 | 2232 | ||
2224 | cfq_log(cfqd, "forced_dispatch=%d", dispatched); | 2233 | cfq_log(cfqd, "forced_dispatch=%d", dispatched); |
@@ -2382,10 +2391,15 @@ static int cfq_dispatch_requests(struct request_queue *q, int force) | |||
2382 | cfqq->slice_dispatch >= cfq_prio_to_maxrq(cfqd, cfqq)) || | 2391 | cfqq->slice_dispatch >= cfq_prio_to_maxrq(cfqd, cfqq)) || |
2383 | cfq_class_idle(cfqq))) { | 2392 | cfq_class_idle(cfqq))) { |
2384 | cfqq->slice_end = jiffies + 1; | 2393 | cfqq->slice_end = jiffies + 1; |
2385 | cfq_slice_expired(cfqd, 0); | 2394 | cfq_slice_expired(cfqd, 0, false); |
2386 | } | 2395 | } |
2387 | 2396 | ||
2388 | cfq_log_cfqq(cfqd, cfqq, "dispatched a request"); | 2397 | cfq_log_cfqq(cfqd, cfqq, "dispatched a request"); |
2398 | /* | ||
2399 | * This is needed since we don't exactly match the mod_timer() and | ||
2400 | * del_timer() calls in CFQ. | ||
2401 | */ | ||
2402 | blkiocg_update_idle_time_stats(&cfqq->cfqg->blkg); | ||
2389 | return 1; | 2403 | return 1; |
2390 | } | 2404 | } |
2391 | 2405 | ||
@@ -2413,7 +2427,7 @@ static void cfq_put_queue(struct cfq_queue *cfqq) | |||
2413 | orig_cfqg = cfqq->orig_cfqg; | 2427 | orig_cfqg = cfqq->orig_cfqg; |
2414 | 2428 | ||
2415 | if (unlikely(cfqd->active_queue == cfqq)) { | 2429 | if (unlikely(cfqd->active_queue == cfqq)) { |
2416 | __cfq_slice_expired(cfqd, cfqq, 0); | 2430 | __cfq_slice_expired(cfqd, cfqq, 0, false); |
2417 | cfq_schedule_dispatch(cfqd); | 2431 | cfq_schedule_dispatch(cfqd); |
2418 | } | 2432 | } |
2419 | 2433 | ||
@@ -2514,7 +2528,7 @@ static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
2514 | struct cfq_queue *__cfqq, *next; | 2528 | struct cfq_queue *__cfqq, *next; |
2515 | 2529 | ||
2516 | if (unlikely(cfqq == cfqd->active_queue)) { | 2530 | if (unlikely(cfqq == cfqd->active_queue)) { |
2517 | __cfq_slice_expired(cfqd, cfqq, 0); | 2531 | __cfq_slice_expired(cfqd, cfqq, 0, false); |
2518 | cfq_schedule_dispatch(cfqd); | 2532 | cfq_schedule_dispatch(cfqd); |
2519 | } | 2533 | } |
2520 | 2534 | ||
@@ -3143,7 +3157,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
3143 | static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 3157 | static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
3144 | { | 3158 | { |
3145 | cfq_log_cfqq(cfqd, cfqq, "preempt"); | 3159 | cfq_log_cfqq(cfqd, cfqq, "preempt"); |
3146 | cfq_slice_expired(cfqd, 1); | 3160 | cfq_slice_expired(cfqd, 1, false); |
3147 | 3161 | ||
3148 | /* | 3162 | /* |
3149 | * Put the new queue at the front of the of the current list, | 3163 | * Put the new queue at the front of the of the current list, |
@@ -3191,7 +3205,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
3191 | if (cfq_cfqq_wait_request(cfqq)) { | 3205 | if (cfq_cfqq_wait_request(cfqq)) { |
3192 | if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE || | 3206 | if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE || |
3193 | cfqd->busy_queues > 1) { | 3207 | cfqd->busy_queues > 1) { |
3194 | del_timer(&cfqd->idle_slice_timer); | 3208 | cfq_del_timer(cfqd, cfqq); |
3195 | cfq_clear_cfqq_wait_request(cfqq); | 3209 | cfq_clear_cfqq_wait_request(cfqq); |
3196 | __blk_run_queue(cfqd->queue); | 3210 | __blk_run_queue(cfqd->queue); |
3197 | } else | 3211 | } else |
@@ -3352,7 +3366,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) | |||
3352 | * - when there is a close cooperator | 3366 | * - when there is a close cooperator |
3353 | */ | 3367 | */ |
3354 | if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq)) | 3368 | if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq)) |
3355 | cfq_slice_expired(cfqd, 1); | 3369 | cfq_slice_expired(cfqd, 1, false); |
3356 | else if (sync && cfqq_empty && | 3370 | else if (sync && cfqq_empty && |
3357 | !cfq_close_cooperator(cfqd, cfqq)) { | 3371 | !cfq_close_cooperator(cfqd, cfqq)) { |
3358 | cfqd->noidle_tree_requires_idle |= !rq_noidle(rq); | 3372 | cfqd->noidle_tree_requires_idle |= !rq_noidle(rq); |
@@ -3612,7 +3626,7 @@ static void cfq_idle_slice_timer(unsigned long data) | |||
3612 | cfq_clear_cfqq_deep(cfqq); | 3626 | cfq_clear_cfqq_deep(cfqq); |
3613 | } | 3627 | } |
3614 | expire: | 3628 | expire: |
3615 | cfq_slice_expired(cfqd, timed_out); | 3629 | cfq_slice_expired(cfqd, timed_out, false); |
3616 | out_kick: | 3630 | out_kick: |
3617 | cfq_schedule_dispatch(cfqd); | 3631 | cfq_schedule_dispatch(cfqd); |
3618 | out_cont: | 3632 | out_cont: |
@@ -3655,7 +3669,7 @@ static void cfq_exit_queue(struct elevator_queue *e) | |||
3655 | spin_lock_irq(q->queue_lock); | 3669 | spin_lock_irq(q->queue_lock); |
3656 | 3670 | ||
3657 | if (cfqd->active_queue) | 3671 | if (cfqd->active_queue) |
3658 | __cfq_slice_expired(cfqd, cfqd->active_queue, 0); | 3672 | __cfq_slice_expired(cfqd, cfqd->active_queue, 0, false); |
3659 | 3673 | ||
3660 | while (!list_empty(&cfqd->cic_list)) { | 3674 | while (!list_empty(&cfqd->cic_list)) { |
3661 | struct cfq_io_context *cic = list_entry(cfqd->cic_list.next, | 3675 | struct cfq_io_context *cic = list_entry(cfqd->cic_list.next, |