aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c50
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
888static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, 888static 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
1532static 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
1531static void __cfq_set_active_queue(struct cfq_data *cfqd, 1538static 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 */
1559static void 1566static 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
1607static inline void cfq_slice_expired(struct cfq_data *cfqd, bool timed_out) 1614static 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
2178expire: 2187expire:
2179 cfq_slice_expired(cfqd, 0); 2188 cfq_slice_expired(cfqd, 0, false);
2180new_queue: 2189new_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,
3143static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) 3157static 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 }
3614expire: 3628expire:
3615 cfq_slice_expired(cfqd, timed_out); 3629 cfq_slice_expired(cfqd, timed_out, false);
3616out_kick: 3630out_kick:
3617 cfq_schedule_dispatch(cfqd); 3631 cfq_schedule_dispatch(cfqd);
3618out_cont: 3632out_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,