diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 89e0d1cc14ba..12e380b2c4e4 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -178,6 +178,8 @@ struct cfq_group { | |||
178 | /* group service_tree key */ | 178 | /* group service_tree key */ |
179 | u64 vdisktime; | 179 | u64 vdisktime; |
180 | unsigned int weight; | 180 | unsigned int weight; |
181 | unsigned int new_weight; | ||
182 | bool needs_update; | ||
181 | 183 | ||
182 | /* number of cfqq currently on this group */ | 184 | /* number of cfqq currently on this group */ |
183 | int nr_cfqq; | 185 | int nr_cfqq; |
@@ -853,7 +855,27 @@ __cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) | |||
853 | } | 855 | } |
854 | 856 | ||
855 | static void | 857 | static void |
856 | cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg) | 858 | cfq_update_group_weight(struct cfq_group *cfqg) |
859 | { | ||
860 | BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); | ||
861 | if (cfqg->needs_update) { | ||
862 | cfqg->weight = cfqg->new_weight; | ||
863 | cfqg->needs_update = false; | ||
864 | } | ||
865 | } | ||
866 | |||
867 | static void | ||
868 | cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) | ||
869 | { | ||
870 | BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); | ||
871 | |||
872 | cfq_update_group_weight(cfqg); | ||
873 | __cfq_group_service_tree_add(st, cfqg); | ||
874 | st->total_weight += cfqg->weight; | ||
875 | } | ||
876 | |||
877 | static void | ||
878 | cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg) | ||
857 | { | 879 | { |
858 | struct cfq_rb_root *st = &cfqd->grp_service_tree; | 880 | struct cfq_rb_root *st = &cfqd->grp_service_tree; |
859 | struct cfq_group *__cfqg; | 881 | struct cfq_group *__cfqg; |
@@ -874,13 +896,19 @@ cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg) | |||
874 | cfqg->vdisktime = __cfqg->vdisktime + CFQ_IDLE_DELAY; | 896 | cfqg->vdisktime = __cfqg->vdisktime + CFQ_IDLE_DELAY; |
875 | } else | 897 | } else |
876 | cfqg->vdisktime = st->min_vdisktime; | 898 | cfqg->vdisktime = st->min_vdisktime; |
899 | cfq_group_service_tree_add(st, cfqg); | ||
900 | } | ||
877 | 901 | ||
878 | __cfq_group_service_tree_add(st, cfqg); | 902 | static void |
879 | st->total_weight += cfqg->weight; | 903 | cfq_group_service_tree_del(struct cfq_rb_root *st, struct cfq_group *cfqg) |
904 | { | ||
905 | st->total_weight -= cfqg->weight; | ||
906 | if (!RB_EMPTY_NODE(&cfqg->rb_node)) | ||
907 | cfq_rb_erase(&cfqg->rb_node, st); | ||
880 | } | 908 | } |
881 | 909 | ||
882 | static void | 910 | static void |
883 | cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg) | 911 | cfq_group_notify_queue_del(struct cfq_data *cfqd, struct cfq_group *cfqg) |
884 | { | 912 | { |
885 | struct cfq_rb_root *st = &cfqd->grp_service_tree; | 913 | struct cfq_rb_root *st = &cfqd->grp_service_tree; |
886 | 914 | ||
@@ -892,9 +920,7 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg) | |||
892 | return; | 920 | return; |
893 | 921 | ||
894 | cfq_log_cfqg(cfqd, cfqg, "del_from_rr group"); | 922 | cfq_log_cfqg(cfqd, cfqg, "del_from_rr group"); |
895 | st->total_weight -= cfqg->weight; | 923 | cfq_group_service_tree_del(st, cfqg); |
896 | if (!RB_EMPTY_NODE(&cfqg->rb_node)) | ||
897 | cfq_rb_erase(&cfqg->rb_node, st); | ||
898 | cfqg->saved_workload_slice = 0; | 924 | cfqg->saved_workload_slice = 0; |
899 | cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1); | 925 | cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1); |
900 | } | 926 | } |
@@ -948,9 +974,10 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, | |||
948 | charge = cfqq->allocated_slice; | 974 | charge = cfqq->allocated_slice; |
949 | 975 | ||
950 | /* Can't update vdisktime while group is on service tree */ | 976 | /* Can't update vdisktime while group is on service tree */ |
951 | cfq_rb_erase(&cfqg->rb_node, st); | 977 | cfq_group_service_tree_del(st, cfqg); |
952 | cfqg->vdisktime += cfq_scale_slice(charge, cfqg); | 978 | cfqg->vdisktime += cfq_scale_slice(charge, cfqg); |
953 | __cfq_group_service_tree_add(st, cfqg); | 979 | /* If a new weight was requested, update now, off tree */ |
980 | cfq_group_service_tree_add(st, cfqg); | ||
954 | 981 | ||
955 | /* This group is being expired. Save the context */ | 982 | /* This group is being expired. Save the context */ |
956 | if (time_after(cfqd->workload_expires, jiffies)) { | 983 | if (time_after(cfqd->workload_expires, jiffies)) { |
@@ -982,7 +1009,9 @@ static inline struct cfq_group *cfqg_of_blkg(struct blkio_group *blkg) | |||
982 | void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg, | 1009 | void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg, |
983 | unsigned int weight) | 1010 | unsigned int weight) |
984 | { | 1011 | { |
985 | cfqg_of_blkg(blkg)->weight = weight; | 1012 | struct cfq_group *cfqg = cfqg_of_blkg(blkg); |
1013 | cfqg->new_weight = weight; | ||
1014 | cfqg->needs_update = true; | ||
986 | } | 1015 | } |
987 | 1016 | ||
988 | static struct cfq_group * | 1017 | static struct cfq_group * |
@@ -1255,7 +1284,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1255 | service_tree->count++; | 1284 | service_tree->count++; |
1256 | if ((add_front || !new_cfqq) && !group_changed) | 1285 | if ((add_front || !new_cfqq) && !group_changed) |
1257 | return; | 1286 | return; |
1258 | cfq_group_service_tree_add(cfqd, cfqq->cfqg); | 1287 | cfq_group_notify_queue_add(cfqd, cfqq->cfqg); |
1259 | } | 1288 | } |
1260 | 1289 | ||
1261 | static struct cfq_queue * | 1290 | static struct cfq_queue * |
@@ -1368,7 +1397,7 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
1368 | cfqq->p_root = NULL; | 1397 | cfqq->p_root = NULL; |
1369 | } | 1398 | } |
1370 | 1399 | ||
1371 | cfq_group_service_tree_del(cfqd, cfqq->cfqg); | 1400 | cfq_group_notify_queue_del(cfqd, cfqq->cfqg); |
1372 | BUG_ON(!cfqd->busy_queues); | 1401 | BUG_ON(!cfqd->busy_queues); |
1373 | cfqd->busy_queues--; | 1402 | cfqd->busy_queues--; |
1374 | if (cfq_cfqq_sync(cfqq)) | 1403 | if (cfq_cfqq_sync(cfqq)) |