diff options
-rw-r--r-- | block/cfq-iosched.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 1cc10489eaf0..b9e483d9031e 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -408,6 +408,13 @@ static inline int cfq_group_busy_queues_wl(enum wl_prio_t wl, | |||
408 | + cfqg->service_trees[wl][SYNC_WORKLOAD].count; | 408 | + cfqg->service_trees[wl][SYNC_WORKLOAD].count; |
409 | } | 409 | } |
410 | 410 | ||
411 | static inline int cfqg_busy_async_queues(struct cfq_data *cfqd, | ||
412 | struct cfq_group *cfqg) | ||
413 | { | ||
414 | return cfqg->service_trees[RT_WORKLOAD][ASYNC_WORKLOAD].count | ||
415 | + cfqg->service_trees[BE_WORKLOAD][ASYNC_WORKLOAD].count; | ||
416 | } | ||
417 | |||
411 | static void cfq_dispatch_insert(struct request_queue *, struct request *); | 418 | static void cfq_dispatch_insert(struct request_queue *, struct request *); |
412 | static struct cfq_queue *cfq_get_queue(struct cfq_data *, bool, | 419 | static struct cfq_queue *cfq_get_queue(struct cfq_data *, bool, |
413 | struct io_context *, gfp_t); | 420 | struct io_context *, gfp_t); |
@@ -895,13 +902,19 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, | |||
895 | struct cfq_queue *cfqq) | 902 | struct cfq_queue *cfqq) |
896 | { | 903 | { |
897 | struct cfq_rb_root *st = &cfqd->grp_service_tree; | 904 | struct cfq_rb_root *st = &cfqd->grp_service_tree; |
898 | unsigned int used_sl; | 905 | unsigned int used_sl, charge_sl; |
906 | int nr_sync = cfqg->nr_cfqq - cfqg_busy_async_queues(cfqd, cfqg) | ||
907 | - cfqg->service_tree_idle.count; | ||
908 | |||
909 | BUG_ON(nr_sync < 0); | ||
910 | used_sl = charge_sl = cfq_cfqq_slice_usage(cfqq); | ||
899 | 911 | ||
900 | used_sl = cfq_cfqq_slice_usage(cfqq); | 912 | if (!cfq_cfqq_sync(cfqq) && !nr_sync) |
913 | charge_sl = cfqq->allocated_slice; | ||
901 | 914 | ||
902 | /* Can't update vdisktime while group is on service tree */ | 915 | /* Can't update vdisktime while group is on service tree */ |
903 | cfq_rb_erase(&cfqg->rb_node, st); | 916 | cfq_rb_erase(&cfqg->rb_node, st); |
904 | cfqg->vdisktime += cfq_scale_slice(used_sl, cfqg); | 917 | cfqg->vdisktime += cfq_scale_slice(charge_sl, cfqg); |
905 | __cfq_group_service_tree_add(st, cfqg); | 918 | __cfq_group_service_tree_add(st, cfqg); |
906 | 919 | ||
907 | /* This group is being expired. Save the context */ | 920 | /* This group is being expired. Save the context */ |
@@ -2016,11 +2029,24 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg) | |||
2016 | max_t(unsigned, cfqg->busy_queues_avg[cfqd->serving_prio], | 2029 | max_t(unsigned, cfqg->busy_queues_avg[cfqd->serving_prio], |
2017 | cfq_group_busy_queues_wl(cfqd->serving_prio, cfqd, cfqg)); | 2030 | cfq_group_busy_queues_wl(cfqd->serving_prio, cfqd, cfqg)); |
2018 | 2031 | ||
2019 | if (cfqd->serving_type == ASYNC_WORKLOAD) | 2032 | if (cfqd->serving_type == ASYNC_WORKLOAD) { |
2033 | unsigned int tmp; | ||
2034 | |||
2035 | /* | ||
2036 | * Async queues are currently system wide. Just taking | ||
2037 | * proportion of queues with-in same group will lead to higher | ||
2038 | * async ratio system wide as generally root group is going | ||
2039 | * to have higher weight. A more accurate thing would be to | ||
2040 | * calculate system wide asnc/sync ratio. | ||
2041 | */ | ||
2042 | tmp = cfq_target_latency * cfqg_busy_async_queues(cfqd, cfqg); | ||
2043 | tmp = tmp/cfqd->busy_queues; | ||
2044 | slice = min_t(unsigned, slice, tmp); | ||
2045 | |||
2020 | /* async workload slice is scaled down according to | 2046 | /* async workload slice is scaled down according to |
2021 | * the sync/async slice ratio. */ | 2047 | * the sync/async slice ratio. */ |
2022 | slice = slice * cfqd->cfq_slice[0] / cfqd->cfq_slice[1]; | 2048 | slice = slice * cfqd->cfq_slice[0] / cfqd->cfq_slice[1]; |
2023 | else | 2049 | } else |
2024 | /* sync workload slice is at least 2 * cfq_slice_idle */ | 2050 | /* sync workload slice is at least 2 * cfq_slice_idle */ |
2025 | slice = max(slice, 2 * cfqd->cfq_slice_idle); | 2051 | slice = max(slice, 2 * cfqd->cfq_slice_idle); |
2026 | 2052 | ||