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.c51
1 files changed, 17 insertions, 34 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index ee130f14d1fc..023f4e69a337 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -42,16 +42,13 @@ static const int cfq_hist_divisor = 4;
42 */ 42 */
43#define CFQ_MIN_TT (2) 43#define CFQ_MIN_TT (2)
44 44
45/*
46 * Allow merged cfqqs to perform this amount of seeky I/O before
47 * deciding to break the queues up again.
48 */
49#define CFQQ_COOP_TOUT (HZ)
50
51#define CFQ_SLICE_SCALE (5) 45#define CFQ_SLICE_SCALE (5)
52#define CFQ_HW_QUEUE_MIN (5) 46#define CFQ_HW_QUEUE_MIN (5)
53#define CFQ_SERVICE_SHIFT 12 47#define CFQ_SERVICE_SHIFT 12
54 48
49#define CFQQ_SEEK_THR 8 * 1024
50#define CFQQ_SEEKY(cfqq) ((cfqq)->seek_mean > CFQQ_SEEK_THR)
51
55#define RQ_CIC(rq) \ 52#define RQ_CIC(rq) \
56 ((struct cfq_io_context *) (rq)->elevator_private) 53 ((struct cfq_io_context *) (rq)->elevator_private)
57#define RQ_CFQQ(rq) (struct cfq_queue *) ((rq)->elevator_private2) 54#define RQ_CFQQ(rq) (struct cfq_queue *) ((rq)->elevator_private2)
@@ -137,7 +134,6 @@ struct cfq_queue {
137 u64 seek_total; 134 u64 seek_total;
138 sector_t seek_mean; 135 sector_t seek_mean;
139 sector_t last_request_pos; 136 sector_t last_request_pos;
140 unsigned long seeky_start;
141 137
142 pid_t pid; 138 pid_t pid;
143 139
@@ -314,6 +310,7 @@ enum cfqq_state_flags {
314 CFQ_CFQQ_FLAG_slice_new, /* no requests dispatched in slice */ 310 CFQ_CFQQ_FLAG_slice_new, /* no requests dispatched in slice */
315 CFQ_CFQQ_FLAG_sync, /* synchronous queue */ 311 CFQ_CFQQ_FLAG_sync, /* synchronous queue */
316 CFQ_CFQQ_FLAG_coop, /* cfqq is shared */ 312 CFQ_CFQQ_FLAG_coop, /* cfqq is shared */
313 CFQ_CFQQ_FLAG_split_coop, /* shared cfqq will be splitted */
317 CFQ_CFQQ_FLAG_deep, /* sync cfqq experienced large depth */ 314 CFQ_CFQQ_FLAG_deep, /* sync cfqq experienced large depth */
318 CFQ_CFQQ_FLAG_wait_busy, /* Waiting for next request */ 315 CFQ_CFQQ_FLAG_wait_busy, /* Waiting for next request */
319}; 316};
@@ -342,6 +339,7 @@ CFQ_CFQQ_FNS(prio_changed);
342CFQ_CFQQ_FNS(slice_new); 339CFQ_CFQQ_FNS(slice_new);
343CFQ_CFQQ_FNS(sync); 340CFQ_CFQQ_FNS(sync);
344CFQ_CFQQ_FNS(coop); 341CFQ_CFQQ_FNS(coop);
342CFQ_CFQQ_FNS(split_coop);
345CFQ_CFQQ_FNS(deep); 343CFQ_CFQQ_FNS(deep);
346CFQ_CFQQ_FNS(wait_busy); 344CFQ_CFQQ_FNS(wait_busy);
347#undef CFQ_CFQQ_FNS 345#undef CFQ_CFQQ_FNS
@@ -1566,6 +1564,15 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1566 cfq_clear_cfqq_wait_busy(cfqq); 1564 cfq_clear_cfqq_wait_busy(cfqq);
1567 1565
1568 /* 1566 /*
1567 * If this cfqq is shared between multiple processes, check to
1568 * make sure that those processes are still issuing I/Os within
1569 * the mean seek distance. If not, it may be time to break the
1570 * queues apart again.
1571 */
1572 if (cfq_cfqq_coop(cfqq) && CFQQ_SEEKY(cfqq))
1573 cfq_mark_cfqq_split_coop(cfqq);
1574
1575 /*
1569 * store what was left of this slice, if the queue idled/timed out 1576 * store what was left of this slice, if the queue idled/timed out
1570 */ 1577 */
1571 if (timed_out && !cfq_cfqq_slice_new(cfqq)) { 1578 if (timed_out && !cfq_cfqq_slice_new(cfqq)) {
@@ -1663,9 +1670,6 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
1663 return cfqd->last_position - blk_rq_pos(rq); 1670 return cfqd->last_position - blk_rq_pos(rq);
1664} 1671}
1665 1672
1666#define CFQQ_SEEK_THR 8 * 1024
1667#define CFQQ_SEEKY(cfqq) ((cfqq)->seek_mean > CFQQ_SEEK_THR)
1668
1669static inline int cfq_rq_close(struct cfq_data *cfqd, struct cfq_queue *cfqq, 1673static inline int cfq_rq_close(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1670 struct request *rq, bool for_preempt) 1674 struct request *rq, bool for_preempt)
1671{ 1675{
@@ -1803,7 +1807,7 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1803 * Otherwise, we do only if they are the last ones 1807 * Otherwise, we do only if they are the last ones
1804 * in their service tree. 1808 * in their service tree.
1805 */ 1809 */
1806 return service_tree->count == 1; 1810 return service_tree->count == 1 && cfq_cfqq_sync(cfqq);
1807} 1811}
1808 1812
1809static void cfq_arm_slice_timer(struct cfq_data *cfqd) 1813static void cfq_arm_slice_timer(struct cfq_data *cfqd)
@@ -3000,19 +3004,6 @@ cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_queue *cfqq,
3000 total = cfqq->seek_total + (cfqq->seek_samples/2); 3004 total = cfqq->seek_total + (cfqq->seek_samples/2);
3001 do_div(total, cfqq->seek_samples); 3005 do_div(total, cfqq->seek_samples);
3002 cfqq->seek_mean = (sector_t)total; 3006 cfqq->seek_mean = (sector_t)total;
3003
3004 /*
3005 * If this cfqq is shared between multiple processes, check to
3006 * make sure that those processes are still issuing I/Os within
3007 * the mean seek distance. If not, it may be time to break the
3008 * queues apart again.
3009 */
3010 if (cfq_cfqq_coop(cfqq)) {
3011 if (CFQQ_SEEKY(cfqq) && !cfqq->seeky_start)
3012 cfqq->seeky_start = jiffies;
3013 else if (!CFQQ_SEEKY(cfqq))
3014 cfqq->seeky_start = 0;
3015 }
3016} 3007}
3017 3008
3018/* 3009/*
@@ -3453,14 +3444,6 @@ cfq_merge_cfqqs(struct cfq_data *cfqd, struct cfq_io_context *cic,
3453 return cic_to_cfqq(cic, 1); 3444 return cic_to_cfqq(cic, 1);
3454} 3445}
3455 3446
3456static int should_split_cfqq(struct cfq_queue *cfqq)
3457{
3458 if (cfqq->seeky_start &&
3459 time_after(jiffies, cfqq->seeky_start + CFQQ_COOP_TOUT))
3460 return 1;
3461 return 0;
3462}
3463
3464/* 3447/*
3465 * Returns NULL if a new cfqq should be allocated, or the old cfqq if this 3448 * Returns NULL if a new cfqq should be allocated, or the old cfqq if this
3466 * was the last process referring to said cfqq. 3449 * was the last process referring to said cfqq.
@@ -3469,9 +3452,9 @@ static struct cfq_queue *
3469split_cfqq(struct cfq_io_context *cic, struct cfq_queue *cfqq) 3452split_cfqq(struct cfq_io_context *cic, struct cfq_queue *cfqq)
3470{ 3453{
3471 if (cfqq_process_refs(cfqq) == 1) { 3454 if (cfqq_process_refs(cfqq) == 1) {
3472 cfqq->seeky_start = 0;
3473 cfqq->pid = current->pid; 3455 cfqq->pid = current->pid;
3474 cfq_clear_cfqq_coop(cfqq); 3456 cfq_clear_cfqq_coop(cfqq);
3457 cfq_clear_cfqq_split_coop(cfqq);
3475 return cfqq; 3458 return cfqq;
3476 } 3459 }
3477 3460
@@ -3510,7 +3493,7 @@ new_queue:
3510 /* 3493 /*
3511 * If the queue was seeky for too long, break it apart. 3494 * If the queue was seeky for too long, break it apart.
3512 */ 3495 */
3513 if (cfq_cfqq_coop(cfqq) && should_split_cfqq(cfqq)) { 3496 if (cfq_cfqq_coop(cfqq) && cfq_cfqq_split_coop(cfqq)) {
3514 cfq_log_cfqq(cfqd, cfqq, "breaking apart cfqq"); 3497 cfq_log_cfqq(cfqd, cfqq, "breaking apart cfqq");
3515 cfqq = split_cfqq(cic, cfqq); 3498 cfqq = split_cfqq(cic, cfqq);
3516 if (!cfqq) 3499 if (!cfqq)