From: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
To: lizefan-hv44wF8Li93QT0dZR+AlfA@public.gmane.org,
axboe-tSWWG44O7X1aa/9Udqfwiw@public.gmane.org,
vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org
Cc: ctalbott-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
rni-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [PATCH 13/24] cfq-iosched: implement hierarchy-ready cfq_group charge scaling
Date: Fri, 28 Dec 2012 12:35:35 -0800 [thread overview]
Message-ID: <1356726946-26037-14-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1356726946-26037-1-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Currently, cfqg charges are scaled directly according to cfqg->weight.
Regardless of the number of active cfqgs or the amount of active
weights, a given weight value always scales charge the same way. This
works fine as long as all cfqgs are treated equally regardless of
their positions in the hierarchy, which is what cfq currently
implements. It can't work in hierarchical settings because the
interpretation of a given weight value depends on where the weight is
located in the hierarchy.
This patch reimplements cfqg charge scaling so that it can be used to
support hierarchy properly. The scheme is fairly simple and
light-weight.
* When a cfqg is added to the service tree, v(disktime)weight is
calculated. It walks up the tree to root calculating the fraction
it has in the hierarchy. At each level, the fraction can be
calculated as
cfqg->weight / parent->level_weight
By compounding these, the global fraction of vdisktime the cfqg has
claim to - vfraction - can be determined.
* When the cfqg needs to be charged, the charge is scaled inversely
proportionally to the vfraction.
The new scaling scheme uses the same CFQ_SERVICE_SHIFT for fixed point
representation as before; however, the smallest scaling factor is now
1 (ie. 1 << CFQ_SERVICE_SHIFT). This is different from before where 1
was for CFQ_WEIGHT_DEFAULT and higher weight would result in smaller
scaling factor.
While this shifts the global scale of vdisktime a bit, it doesn't
change the relative relationships among cfqgs and the scheduling
result isn't different.
cfq_group_notify_queue_add uses fixed CFQ_IDLE_DELAY when appending
new cfqg to the service tree. The specific value of CFQ_IDLE_DELAY
didn't have any relevance to vdisktime before and is unlikely to cause
any visible behavior difference now especially as the scale shift
isn't that large.
As the new scheme now makes proper distinction between cfqg->weight
and ->leaf_weight, reverse the weight aliasing for root cfqgs. For
root, both weights are now mapped to ->leaf_weight instead of the
other way around.
Because we're still using cfqg_flat_parent(), this patch shouldn't
change the scheduling behavior in any noticeable way.
v2: Beefed up comments on vfraction as requested by Vivek.
Signed-off-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
block/cfq-iosched.c | 107 +++++++++++++++++++++++++++++++++++++---------------
1 file changed, 77 insertions(+), 30 deletions(-)
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 7701c3f..b24acf6 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -237,6 +237,18 @@ struct cfq_group {
unsigned int children_weight;
/*
+ * vfraction is the fraction of vdisktime that the tasks in this
+ * cfqg are entitled to. This is determined by compounding the
+ * ratios walking up from this cfqg to the root.
+ *
+ * It is in fixed point w/ CFQ_SERVICE_SHIFT and the sum of all
+ * vfractions on a service tree is approximately 1. The sum may
+ * deviate a bit due to rounding errors and fluctuations caused by
+ * cfqgs entering and leaving the service tree.
+ */
+ unsigned int vfraction;
+
+ /*
* There are two weights - (internal) weight is the weight of this
* cfqg against the sibling cfqgs. leaf_weight is the wight of
* this cfqg against the child cfqgs. For the root cfqg, both
@@ -891,13 +903,27 @@ cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
return cfq_prio_slice(cfqd, cfq_cfqq_sync(cfqq), cfqq->ioprio);
}
-static inline u64 cfq_scale_slice(unsigned long delta, struct cfq_group *cfqg)
+/**
+ * cfqg_scale_charge - scale disk time charge according to cfqg weight
+ * @charge: disk time being charged
+ * @vfraction: vfraction of the cfqg, fixed point w/ CFQ_SERVICE_SHIFT
+ *
+ * Scale @charge according to @vfraction, which is in range (0, 1]. The
+ * scaling is inversely proportional.
+ *
+ * scaled = charge / vfraction
+ *
+ * The result is also in fixed point w/ CFQ_SERVICE_SHIFT.
+ */
+static inline u64 cfqg_scale_charge(unsigned long charge,
+ unsigned int vfraction)
{
- u64 d = delta << CFQ_SERVICE_SHIFT;
+ u64 c = charge << CFQ_SERVICE_SHIFT; /* make it fixed point */
- d = d * CFQ_WEIGHT_DEFAULT;
- do_div(d, cfqg->weight);
- return d;
+ /* charge / vfraction */
+ c <<= CFQ_SERVICE_SHIFT;
+ do_div(c, vfraction);
+ return c;
}
static inline u64 max_vdisktime(u64 min_vdisktime, u64 vdisktime)
@@ -1237,7 +1263,9 @@ cfq_update_group_weight(struct cfq_group *cfqg)
static void
cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
{
+ unsigned int vfr = 1 << CFQ_SERVICE_SHIFT; /* start with 1 */
struct cfq_group *pos = cfqg;
+ struct cfq_group *parent;
bool propagate;
/* add to the service tree */
@@ -1248,22 +1276,34 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
st->total_weight += cfqg->weight;
/*
- * Activate @cfqg and propagate activation upwards until we meet an
- * already activated node or reach root.
+ * Activate @cfqg and calculate the portion of vfraction @cfqg is
+ * entitled to. vfraction is calculated by walking the tree
+ * towards the root calculating the fraction it has at each level.
+ * The compounded ratio is how much vfraction @cfqg owns.
+ *
+ * Start with the proportion tasks in this cfqg has against active
+ * children cfqgs - its leaf_weight against children_weight.
*/
propagate = !pos->nr_active++;
pos->children_weight += pos->leaf_weight;
+ vfr = vfr * pos->leaf_weight / pos->children_weight;
- while (propagate) {
- struct cfq_group *parent = cfqg_flat_parent(pos);
-
- if (!parent)
- break;
-
- propagate = !parent->nr_active++;
- parent->children_weight += pos->weight;
+ /*
+ * Compound ->weight walking up the tree. Both activation and
+ * vfraction calculation are done in the same loop. Propagation
+ * stops once an already activated node is met. vfraction
+ * calculation should always continue to the root.
+ */
+ while ((parent = cfqg_flat_parent(pos))) {
+ if (propagate) {
+ propagate = !parent->nr_active++;
+ parent->children_weight += pos->weight;
+ }
+ vfr = vfr * pos->weight / parent->children_weight;
pos = parent;
}
+
+ cfqg->vfraction = max_t(unsigned, vfr, 1);
}
static void
@@ -1309,6 +1349,7 @@ cfq_group_service_tree_del(struct cfq_rb_root *st, struct cfq_group *cfqg)
/* @pos has 0 nr_active at this point */
WARN_ON_ONCE(pos->children_weight);
+ pos->vfraction = 0;
if (!parent)
break;
@@ -1381,6 +1422,7 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg,
unsigned int used_sl, charge, unaccounted_sl = 0;
int nr_sync = cfqg->nr_cfqq - cfqg_busy_async_queues(cfqd, cfqg)
- cfqg->service_tree_idle.count;
+ unsigned int vfr;
BUG_ON(nr_sync < 0);
used_sl = charge = cfq_cfqq_slice_usage(cfqq, &unaccounted_sl);
@@ -1390,10 +1432,15 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg,
else if (!cfq_cfqq_sync(cfqq) && !nr_sync)
charge = cfqq->allocated_slice;
- /* Can't update vdisktime while group is on service tree */
+ /*
+ * Can't update vdisktime while on service tree and cfqg->vfraction
+ * is valid only while on it. Cache vfr, leave the service tree,
+ * update vdisktime and go back on. The re-addition to the tree
+ * will also update the weights as necessary.
+ */
+ vfr = cfqg->vfraction;
cfq_group_service_tree_del(st, cfqg);
- cfqg->vdisktime += cfq_scale_slice(charge, cfqg);
- /* If a new weight was requested, update now, off tree */
+ cfqg->vdisktime += cfqg_scale_charge(charge, vfr);
cfq_group_service_tree_add(st, cfqg);
/* This group is being expired. Save the context */
@@ -1669,44 +1716,44 @@ static int cfqg_print_avg_queue_size(struct cgroup *cgrp, struct cftype *cft,
#endif /* CONFIG_DEBUG_BLK_CGROUP */
static struct cftype cfq_blkcg_files[] = {
+ /* on root, weight is mapped to leaf_weight */
{
.name = "weight_device",
- .read_seq_string = cfqg_print_weight_device,
- .write_string = cfqg_set_weight_device,
+ .flags = CFTYPE_ONLY_ON_ROOT,
+ .read_seq_string = cfqg_print_leaf_weight_device,
+ .write_string = cfqg_set_leaf_weight_device,
.max_write_len = 256,
},
{
.name = "weight",
- .read_seq_string = cfq_print_weight,
- .write_u64 = cfq_set_weight,
+ .flags = CFTYPE_ONLY_ON_ROOT,
+ .read_seq_string = cfq_print_leaf_weight,
+ .write_u64 = cfq_set_leaf_weight,
},
- /* on root, leaf_weight is mapped to weight */
+ /* no such mapping necessary for !roots */
{
- .name = "leaf_weight_device",
- .flags = CFTYPE_ONLY_ON_ROOT,
+ .name = "weight_device",
+ .flags = CFTYPE_NOT_ON_ROOT,
.read_seq_string = cfqg_print_weight_device,
.write_string = cfqg_set_weight_device,
.max_write_len = 256,
},
{
- .name = "leaf_weight",
- .flags = CFTYPE_ONLY_ON_ROOT,
+ .name = "weight",
+ .flags = CFTYPE_NOT_ON_ROOT,
.read_seq_string = cfq_print_weight,
.write_u64 = cfq_set_weight,
},
- /* no such mapping necessary for !roots */
{
.name = "leaf_weight_device",
- .flags = CFTYPE_NOT_ON_ROOT,
.read_seq_string = cfqg_print_leaf_weight_device,
.write_string = cfqg_set_leaf_weight_device,
.max_write_len = 256,
},
{
.name = "leaf_weight",
- .flags = CFTYPE_NOT_ON_ROOT,
.read_seq_string = cfq_print_leaf_weight,
.write_u64 = cfq_set_leaf_weight,
},
--
1.8.0.2
next prev parent reply other threads:[~2012-12-28 20:35 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-28 20:35 [PATCHSET] block: implement blkcg hierarchy support in cfq, take#2 Tejun Heo
2012-12-28 20:35 ` [PATCH 11/24] cfq-iosched: add leaf_weight Tejun Heo
[not found] ` <1356726946-26037-12-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-08 15:34 ` Vivek Goyal
[not found] ` <20130108153448.GB29635-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-01-08 17:24 ` Tejun Heo
2012-12-28 20:35 ` [PATCH 12/24] cfq-iosched: implement cfq_group->nr_active and ->children_weight Tejun Heo
[not found] ` <1356726946-26037-13-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-08 15:51 ` Vivek Goyal
2012-12-28 20:35 ` [PATCH 14/24] cfq-iosched: convert cfq_group_slice() to use cfqg->vfraction Tejun Heo
[not found] ` <1356726946-26037-15-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-08 16:42 ` Vivek Goyal
2012-12-28 20:35 ` [PATCH 15/24] cfq-iosched: enable full blkcg hierarchy support Tejun Heo
[not found] ` <1356726946-26037-16-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-07 16:34 ` [PATCH UPDATED " Tejun Heo
[not found] ` <20130107163405.GE3926-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
2013-01-08 14:42 ` Vivek Goyal
[not found] ` <20130108144240.GA29635-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-01-08 17:19 ` Tejun Heo
2012-12-28 20:35 ` [PATCH 16/24] blkcg: add blkg_policy_data->plid Tejun Heo
[not found] ` <1356726946-26037-17-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-08 16:51 ` Vivek Goyal
2012-12-28 20:35 ` [PATCH 19/24] blkcg: implement blkg_[rw]stat_recursive_sum() and blkg_[rw]stat_merge() Tejun Heo
[not found] ` <1356726946-26037-20-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-08 18:03 ` Vivek Goyal
2012-12-28 20:35 ` [PATCH 20/24] block: RCU free request_queue Tejun Heo
[not found] ` <1356726946-26037-21-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-02 18:48 ` Vivek Goyal
[not found] ` <20130102184814.GD4306-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-01-02 20:43 ` Tejun Heo
2013-01-08 18:05 ` Vivek Goyal
[not found] ` <1356726946-26037-1-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2012-12-28 20:35 ` [PATCH 01/24] cfq-iosched: Properly name all references to IO class Tejun Heo
2012-12-28 20:35 ` [PATCH 02/24] cfq-iosched: More renaming to better represent wl_class and wl_type Tejun Heo
2012-12-28 20:35 ` [PATCH 03/24] cfq-iosched: Rename "service_tree" to "st" at some places Tejun Heo
2012-12-28 20:35 ` [PATCH 04/24] cfq-iosched: Rename few functions related to selecting workload Tejun Heo
2012-12-28 20:35 ` [PATCH 05/24] cfq-iosched: Get rid of unnecessary local variable Tejun Heo
2012-12-28 20:35 ` [PATCH 06/24] cfq-iosched: Print sync-noidle information in blktrace messages Tejun Heo
2012-12-28 20:35 ` [PATCH 07/24] blkcg: fix minor bug in blkg_alloc() Tejun Heo
2012-12-28 20:35 ` [PATCH 08/24] blkcg: reorganize blkg_lookup_create() and friends Tejun Heo
2012-12-28 20:35 ` [PATCH 09/24] blkcg: cosmetic updates to blkg_create() Tejun Heo
2012-12-28 20:35 ` [PATCH 10/24] blkcg: make blkcg_gq's hierarchical Tejun Heo
2012-12-28 20:35 ` Tejun Heo [this message]
[not found] ` <1356726946-26037-14-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-08 16:16 ` [PATCH 13/24] cfq-iosched: implement hierarchy-ready cfq_group charge scaling Vivek Goyal
2012-12-28 20:35 ` [PATCH 17/24] blkcg: implement blkcg_policy->on/offline_pd_fn() and blkcg_gq->online Tejun Heo
[not found] ` <1356726946-26037-18-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-02 19:38 ` Vivek Goyal
[not found] ` <20130102193828.GE4306-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-01-02 20:37 ` Tejun Heo
2013-01-08 16:58 ` Vivek Goyal
2012-12-28 20:35 ` [PATCH 18/24] blkcg: s/blkg_rwstat_sum()/blkg_rwstat_total()/ Tejun Heo
[not found] ` <1356726946-26037-19-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-08 16:59 ` Vivek Goyal
2012-12-28 20:35 ` [PATCH 21/24] blkcg: make blkcg_print_blkgs() grab q locks instead of blkcg lock Tejun Heo
[not found] ` <1356726946-26037-22-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-02 19:27 ` Vivek Goyal
[not found] ` <20130102192700.GA9552-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-01-02 20:45 ` Tejun Heo
2013-01-08 18:08 ` Vivek Goyal
2012-12-28 23:18 ` [PATCH 18.5/24] blkcg: export __blkg_prfill_rwstat() take#2 Tejun Heo
2013-01-02 18:20 ` [PATCHSET] block: implement blkcg hierarchy support in cfq, take#2 Vivek Goyal
[not found] ` <20130102182037.GC4306-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-01-07 16:34 ` Tejun Heo
[not found] ` <20130107163437.GF3926-Gd/HAXX7CRxy/B6EtB590w@public.gmane.org>
2013-01-08 18:28 ` Vivek Goyal
2012-12-28 20:35 ` [PATCH 22/24] cfq-iosched: separate out cfqg_stats_reset() from cfq_pd_reset_stats() Tejun Heo
[not found] ` <1356726946-26037-23-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-08 18:09 ` Vivek Goyal
2012-12-28 20:35 ` [PATCH 23/24] cfq-iosched: collect stats from dead cfqgs Tejun Heo
[not found] ` <1356726946-26037-24-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-02 16:24 ` Vivek Goyal
[not found] ` <20130102162415.GA4306-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-01-02 16:30 ` Tejun Heo
[not found] ` <20130102163010.GC11220-9pTldWuhBndy/B6EtB590w@public.gmane.org>
2013-01-02 16:44 ` Vivek Goyal
[not found] ` <20130102164415.GB4306-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-01-02 16:52 ` Tejun Heo
2013-01-08 18:12 ` Vivek Goyal
2012-12-28 20:35 ` [PATCH 24/24] cfq-iosched: add hierarchical cfq_group statistics Tejun Heo
[not found] ` <1356726946-26037-25-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-08 18:27 ` Vivek Goyal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1356726946-26037-14-git-send-email-tj@kernel.org \
--to=tj-dgejt+ai2ygdnm+yrofe0a@public.gmane.org \
--cc=axboe-tSWWG44O7X1aa/9Udqfwiw@public.gmane.org \
--cc=cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
--cc=ctalbott-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=lizefan-hv44wF8Li93QT0dZR+AlfA@public.gmane.org \
--cc=rni-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
--cc=vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).