diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/cfq-iosched.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 069a61017c02..aa1e9535e358 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -196,6 +196,7 @@ enum cfqq_state_flags { | |||
196 | CFQ_CFQQ_FLAG_slice_new, /* no requests dispatched in slice */ | 196 | CFQ_CFQQ_FLAG_slice_new, /* no requests dispatched in slice */ |
197 | CFQ_CFQQ_FLAG_sync, /* synchronous queue */ | 197 | CFQ_CFQQ_FLAG_sync, /* synchronous queue */ |
198 | CFQ_CFQQ_FLAG_coop, /* has done a coop jump of the queue */ | 198 | CFQ_CFQQ_FLAG_coop, /* has done a coop jump of the queue */ |
199 | CFQ_CFQQ_FLAG_coop_preempt, /* coop preempt */ | ||
199 | }; | 200 | }; |
200 | 201 | ||
201 | #define CFQ_CFQQ_FNS(name) \ | 202 | #define CFQ_CFQQ_FNS(name) \ |
@@ -222,6 +223,7 @@ CFQ_CFQQ_FNS(prio_changed); | |||
222 | CFQ_CFQQ_FNS(slice_new); | 223 | CFQ_CFQQ_FNS(slice_new); |
223 | CFQ_CFQQ_FNS(sync); | 224 | CFQ_CFQQ_FNS(sync); |
224 | CFQ_CFQQ_FNS(coop); | 225 | CFQ_CFQQ_FNS(coop); |
226 | CFQ_CFQQ_FNS(coop_preempt); | ||
225 | #undef CFQ_CFQQ_FNS | 227 | #undef CFQ_CFQQ_FNS |
226 | 228 | ||
227 | #define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \ | 229 | #define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \ |
@@ -945,10 +947,13 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd, | |||
945 | { | 947 | { |
946 | if (!cfqq) { | 948 | if (!cfqq) { |
947 | cfqq = cfq_get_next_queue(cfqd); | 949 | cfqq = cfq_get_next_queue(cfqd); |
948 | if (cfqq) | 950 | if (cfqq && !cfq_cfqq_coop_preempt(cfqq)) |
949 | cfq_clear_cfqq_coop(cfqq); | 951 | cfq_clear_cfqq_coop(cfqq); |
950 | } | 952 | } |
951 | 953 | ||
954 | if (cfqq) | ||
955 | cfq_clear_cfqq_coop_preempt(cfqq); | ||
956 | |||
952 | __cfq_set_active_queue(cfqd, cfqq); | 957 | __cfq_set_active_queue(cfqd, cfqq); |
953 | return cfqq; | 958 | return cfqq; |
954 | } | 959 | } |
@@ -2051,7 +2056,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
2051 | * it's a metadata request and the current queue is doing regular IO. | 2056 | * it's a metadata request and the current queue is doing regular IO. |
2052 | */ | 2057 | */ |
2053 | if (rq_is_meta(rq) && !cfqq->meta_pending) | 2058 | if (rq_is_meta(rq) && !cfqq->meta_pending) |
2054 | return false; | 2059 | return true; |
2055 | 2060 | ||
2056 | /* | 2061 | /* |
2057 | * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice. | 2062 | * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice. |
@@ -2066,8 +2071,16 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
2066 | * if this request is as-good as one we would expect from the | 2071 | * if this request is as-good as one we would expect from the |
2067 | * current cfqq, let it preempt | 2072 | * current cfqq, let it preempt |
2068 | */ | 2073 | */ |
2069 | if (cfq_rq_close(cfqd, rq)) | 2074 | if (cfq_rq_close(cfqd, rq) && (!cfq_cfqq_coop(new_cfqq) || |
2075 | cfqd->busy_queues == 1)) { | ||
2076 | /* | ||
2077 | * Mark new queue coop_preempt, so its coop flag will not be | ||
2078 | * cleared when new queue gets scheduled at the very first time | ||
2079 | */ | ||
2080 | cfq_mark_cfqq_coop_preempt(new_cfqq); | ||
2081 | cfq_mark_cfqq_coop(new_cfqq); | ||
2070 | return true; | 2082 | return true; |
2083 | } | ||
2071 | 2084 | ||
2072 | return false; | 2085 | return false; |
2073 | } | 2086 | } |