blkcg: use CGROUP_WEIGHT_* scale for io.weight on the unified hierarchy
cgroup is trying to make interface consistent across different controllers. For weight based resource control, the knob should have the range [1, 10000] and default to 100. This patch updates cfq-iosched so that the weight range conforms. The internal calculations have enough range and the widening of the weight range shouldn't cause any problem. * blkcg_policy->cpd_bind_fn() is added. If present, this is invoked when blkcg is attached to a hierarchy. * cfq_cpd_init() is updated to use the new default value on the unified hierarchy. * cfq_cpd_bind() callback is implemented to clear per-blkg configs and apply the default config matching the hierarchy type. * cfqd->root_group->[leaf_]weight initialization in cfq_init_queue() is moved into !CONFIG_CFQ_GROUP_IOSCHED block. cfq_cpd_bind() is now responsible for initializing the initial weights when blkcg is enabled. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Arianna Avanzini <avanzini.arianna@gmail.com> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
parent
3ecca62931
commit
69d7fde590
4 changed files with 64 additions and 16 deletions
|
@ -464,7 +464,7 @@ may be specified in any order and not all pairs have to be specified.
|
||||||
|
|
||||||
The weight setting, currently only available and effective if
|
The weight setting, currently only available and effective if
|
||||||
cfq-iosched is in use for the target device. The weight is
|
cfq-iosched is in use for the target device. The weight is
|
||||||
between 10 and 1000 and defaults to 500. The first line
|
between 1 and 10000 and defaults to 100. The first line
|
||||||
always contains the default weight in the following format to
|
always contains the default weight in the following format to
|
||||||
use when per-device setting is missing.
|
use when per-device setting is missing.
|
||||||
|
|
||||||
|
|
|
@ -1143,11 +1143,32 @@ static int blkcg_can_attach(struct cgroup_subsys_state *css,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void blkcg_bind(struct cgroup_subsys_state *root_css)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
mutex_lock(&blkcg_pol_mutex);
|
||||||
|
|
||||||
|
for (i = 0; i < BLKCG_MAX_POLS; i++) {
|
||||||
|
struct blkcg_policy *pol = blkcg_policy[i];
|
||||||
|
struct blkcg *blkcg;
|
||||||
|
|
||||||
|
if (!pol || !pol->cpd_bind_fn)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node)
|
||||||
|
if (blkcg->cpd[pol->plid])
|
||||||
|
pol->cpd_bind_fn(blkcg->cpd[pol->plid]);
|
||||||
|
}
|
||||||
|
mutex_unlock(&blkcg_pol_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
struct cgroup_subsys io_cgrp_subsys = {
|
struct cgroup_subsys io_cgrp_subsys = {
|
||||||
.css_alloc = blkcg_css_alloc,
|
.css_alloc = blkcg_css_alloc,
|
||||||
.css_offline = blkcg_css_offline,
|
.css_offline = blkcg_css_offline,
|
||||||
.css_free = blkcg_css_free,
|
.css_free = blkcg_css_free,
|
||||||
.can_attach = blkcg_can_attach,
|
.can_attach = blkcg_can_attach,
|
||||||
|
.bind = blkcg_bind,
|
||||||
.dfl_cftypes = blkcg_files,
|
.dfl_cftypes = blkcg_files,
|
||||||
.legacy_cftypes = blkcg_legacy_files,
|
.legacy_cftypes = blkcg_legacy_files,
|
||||||
.legacy_name = "blkio",
|
.legacy_name = "blkio",
|
||||||
|
|
|
@ -1522,6 +1522,9 @@ static void cfq_init_cfqg_base(struct cfq_group *cfqg)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CFQ_GROUP_IOSCHED
|
#ifdef CONFIG_CFQ_GROUP_IOSCHED
|
||||||
|
static int __cfq_set_weight(struct cgroup_subsys_state *css, u64 val,
|
||||||
|
bool on_dfl, bool reset_dev, bool is_leaf_weight);
|
||||||
|
|
||||||
static void cfqg_stats_exit(struct cfqg_stats *stats)
|
static void cfqg_stats_exit(struct cfqg_stats *stats)
|
||||||
{
|
{
|
||||||
blkg_rwstat_exit(&stats->merged);
|
blkg_rwstat_exit(&stats->merged);
|
||||||
|
@ -1578,14 +1581,14 @@ static struct blkcg_policy_data *cfq_cpd_alloc(gfp_t gfp)
|
||||||
static void cfq_cpd_init(struct blkcg_policy_data *cpd)
|
static void cfq_cpd_init(struct blkcg_policy_data *cpd)
|
||||||
{
|
{
|
||||||
struct cfq_group_data *cgd = cpd_to_cfqgd(cpd);
|
struct cfq_group_data *cgd = cpd_to_cfqgd(cpd);
|
||||||
|
unsigned int weight = cgroup_on_dfl(blkcg_root.css.cgroup) ?
|
||||||
|
CGROUP_WEIGHT_DFL : CFQ_WEIGHT_LEGACY_DFL;
|
||||||
|
|
||||||
if (cpd_to_blkcg(cpd) == &blkcg_root) {
|
if (cpd_to_blkcg(cpd) == &blkcg_root)
|
||||||
cgd->weight = 2 * CFQ_WEIGHT_LEGACY_DFL;
|
weight *= 2;
|
||||||
cgd->leaf_weight = 2 * CFQ_WEIGHT_LEGACY_DFL;
|
|
||||||
} else {
|
cgd->weight = weight;
|
||||||
cgd->weight = CFQ_WEIGHT_LEGACY_DFL;
|
cgd->leaf_weight = weight;
|
||||||
cgd->leaf_weight = CFQ_WEIGHT_LEGACY_DFL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cfq_cpd_free(struct blkcg_policy_data *cpd)
|
static void cfq_cpd_free(struct blkcg_policy_data *cpd)
|
||||||
|
@ -1593,6 +1596,19 @@ static void cfq_cpd_free(struct blkcg_policy_data *cpd)
|
||||||
kfree(cpd_to_cfqgd(cpd));
|
kfree(cpd_to_cfqgd(cpd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cfq_cpd_bind(struct blkcg_policy_data *cpd)
|
||||||
|
{
|
||||||
|
struct blkcg *blkcg = cpd_to_blkcg(cpd);
|
||||||
|
bool on_dfl = cgroup_on_dfl(blkcg_root.css.cgroup);
|
||||||
|
unsigned int weight = on_dfl ? CGROUP_WEIGHT_DFL : CFQ_WEIGHT_LEGACY_DFL;
|
||||||
|
|
||||||
|
if (blkcg == &blkcg_root)
|
||||||
|
weight *= 2;
|
||||||
|
|
||||||
|
WARN_ON_ONCE(__cfq_set_weight(&blkcg->css, weight, on_dfl, true, false));
|
||||||
|
WARN_ON_ONCE(__cfq_set_weight(&blkcg->css, weight, on_dfl, true, true));
|
||||||
|
}
|
||||||
|
|
||||||
static struct blkg_policy_data *cfq_pd_alloc(gfp_t gfp, int node)
|
static struct blkg_policy_data *cfq_pd_alloc(gfp_t gfp, int node)
|
||||||
{
|
{
|
||||||
struct cfq_group *cfqg;
|
struct cfq_group *cfqg;
|
||||||
|
@ -1742,6 +1758,8 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of,
|
||||||
char *buf, size_t nbytes, loff_t off,
|
char *buf, size_t nbytes, loff_t off,
|
||||||
bool on_dfl, bool is_leaf_weight)
|
bool on_dfl, bool is_leaf_weight)
|
||||||
{
|
{
|
||||||
|
unsigned int min = on_dfl ? CGROUP_WEIGHT_MIN : CFQ_WEIGHT_LEGACY_MIN;
|
||||||
|
unsigned int max = on_dfl ? CGROUP_WEIGHT_MAX : CFQ_WEIGHT_LEGACY_MAX;
|
||||||
struct blkcg *blkcg = css_to_blkcg(of_css(of));
|
struct blkcg *blkcg = css_to_blkcg(of_css(of));
|
||||||
struct blkg_conf_ctx ctx;
|
struct blkg_conf_ctx ctx;
|
||||||
struct cfq_group *cfqg;
|
struct cfq_group *cfqg;
|
||||||
|
@ -1769,7 +1787,7 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of,
|
||||||
cfqgd = blkcg_to_cfqgd(blkcg);
|
cfqgd = blkcg_to_cfqgd(blkcg);
|
||||||
|
|
||||||
ret = -ERANGE;
|
ret = -ERANGE;
|
||||||
if (!v || (v >= CFQ_WEIGHT_LEGACY_MIN && v <= CFQ_WEIGHT_LEGACY_MAX)) {
|
if (!v || (v >= min && v <= max)) {
|
||||||
if (!is_leaf_weight) {
|
if (!is_leaf_weight) {
|
||||||
cfqg->dev_weight = v;
|
cfqg->dev_weight = v;
|
||||||
cfqg->new_weight = v ?: cfqgd->weight;
|
cfqg->new_weight = v ?: cfqgd->weight;
|
||||||
|
@ -1797,15 +1815,17 @@ static ssize_t cfqg_set_leaf_weight_device(struct kernfs_open_file *of,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __cfq_set_weight(struct cgroup_subsys_state *css, u64 val,
|
static int __cfq_set_weight(struct cgroup_subsys_state *css, u64 val,
|
||||||
bool is_leaf_weight)
|
bool on_dfl, bool reset_dev, bool is_leaf_weight)
|
||||||
{
|
{
|
||||||
|
unsigned int min = on_dfl ? CGROUP_WEIGHT_MIN : CFQ_WEIGHT_LEGACY_MIN;
|
||||||
|
unsigned int max = on_dfl ? CGROUP_WEIGHT_MAX : CFQ_WEIGHT_LEGACY_MAX;
|
||||||
struct blkcg *blkcg = css_to_blkcg(css);
|
struct blkcg *blkcg = css_to_blkcg(css);
|
||||||
struct blkcg_gq *blkg;
|
struct blkcg_gq *blkg;
|
||||||
struct cfq_group_data *cfqgd;
|
struct cfq_group_data *cfqgd;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (val < CFQ_WEIGHT_LEGACY_MIN || val > CFQ_WEIGHT_LEGACY_MAX)
|
if (val < min || val > max)
|
||||||
return -EINVAL;
|
return -ERANGE;
|
||||||
|
|
||||||
spin_lock_irq(&blkcg->lock);
|
spin_lock_irq(&blkcg->lock);
|
||||||
cfqgd = blkcg_to_cfqgd(blkcg);
|
cfqgd = blkcg_to_cfqgd(blkcg);
|
||||||
|
@ -1826,9 +1846,13 @@ static int __cfq_set_weight(struct cgroup_subsys_state *css, u64 val,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!is_leaf_weight) {
|
if (!is_leaf_weight) {
|
||||||
|
if (reset_dev)
|
||||||
|
cfqg->dev_weight = 0;
|
||||||
if (!cfqg->dev_weight)
|
if (!cfqg->dev_weight)
|
||||||
cfqg->new_weight = cfqgd->weight;
|
cfqg->new_weight = cfqgd->weight;
|
||||||
} else {
|
} else {
|
||||||
|
if (reset_dev)
|
||||||
|
cfqg->dev_leaf_weight = 0;
|
||||||
if (!cfqg->dev_leaf_weight)
|
if (!cfqg->dev_leaf_weight)
|
||||||
cfqg->new_leaf_weight = cfqgd->leaf_weight;
|
cfqg->new_leaf_weight = cfqgd->leaf_weight;
|
||||||
}
|
}
|
||||||
|
@ -1842,13 +1866,13 @@ static int __cfq_set_weight(struct cgroup_subsys_state *css, u64 val,
|
||||||
static int cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft,
|
static int cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft,
|
||||||
u64 val)
|
u64 val)
|
||||||
{
|
{
|
||||||
return __cfq_set_weight(css, val, false);
|
return __cfq_set_weight(css, val, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cfq_set_leaf_weight(struct cgroup_subsys_state *css,
|
static int cfq_set_leaf_weight(struct cgroup_subsys_state *css,
|
||||||
struct cftype *cft, u64 val)
|
struct cftype *cft, u64 val)
|
||||||
{
|
{
|
||||||
return __cfq_set_weight(css, val, true);
|
return __cfq_set_weight(css, val, false, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cfqg_print_stat(struct seq_file *sf, void *v)
|
static int cfqg_print_stat(struct seq_file *sf, void *v)
|
||||||
|
@ -2135,7 +2159,7 @@ static ssize_t cfq_set_weight_on_dfl(struct kernfs_open_file *of,
|
||||||
/* "WEIGHT" or "default WEIGHT" sets the default weight */
|
/* "WEIGHT" or "default WEIGHT" sets the default weight */
|
||||||
v = simple_strtoull(buf, &endp, 0);
|
v = simple_strtoull(buf, &endp, 0);
|
||||||
if (*endp == '\0' || sscanf(buf, "default %llu", &v) == 1) {
|
if (*endp == '\0' || sscanf(buf, "default %llu", &v) == 1) {
|
||||||
ret = __cfq_set_weight(of_css(of), v, false);
|
ret = __cfq_set_weight(of_css(of), v, true, false, false);
|
||||||
return ret ?: nbytes;
|
return ret ?: nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4512,9 +4536,9 @@ static int cfq_init_queue(struct request_queue *q, struct elevator_type *e)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
cfq_init_cfqg_base(cfqd->root_group);
|
cfq_init_cfqg_base(cfqd->root_group);
|
||||||
#endif
|
|
||||||
cfqd->root_group->weight = 2 * CFQ_WEIGHT_LEGACY_DFL;
|
cfqd->root_group->weight = 2 * CFQ_WEIGHT_LEGACY_DFL;
|
||||||
cfqd->root_group->leaf_weight = 2 * CFQ_WEIGHT_LEGACY_DFL;
|
cfqd->root_group->leaf_weight = 2 * CFQ_WEIGHT_LEGACY_DFL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Not strictly needed (since RB_ROOT just clears the node and we
|
* Not strictly needed (since RB_ROOT just clears the node and we
|
||||||
|
@ -4715,6 +4739,7 @@ static struct blkcg_policy blkcg_policy_cfq = {
|
||||||
.cpd_alloc_fn = cfq_cpd_alloc,
|
.cpd_alloc_fn = cfq_cpd_alloc,
|
||||||
.cpd_init_fn = cfq_cpd_init,
|
.cpd_init_fn = cfq_cpd_init,
|
||||||
.cpd_free_fn = cfq_cpd_free,
|
.cpd_free_fn = cfq_cpd_free,
|
||||||
|
.cpd_bind_fn = cfq_cpd_bind,
|
||||||
|
|
||||||
.pd_alloc_fn = cfq_pd_alloc,
|
.pd_alloc_fn = cfq_pd_alloc,
|
||||||
.pd_init_fn = cfq_pd_init,
|
.pd_init_fn = cfq_pd_init,
|
||||||
|
|
|
@ -138,6 +138,7 @@ struct blkcg_gq {
|
||||||
typedef struct blkcg_policy_data *(blkcg_pol_alloc_cpd_fn)(gfp_t gfp);
|
typedef struct blkcg_policy_data *(blkcg_pol_alloc_cpd_fn)(gfp_t gfp);
|
||||||
typedef void (blkcg_pol_init_cpd_fn)(struct blkcg_policy_data *cpd);
|
typedef void (blkcg_pol_init_cpd_fn)(struct blkcg_policy_data *cpd);
|
||||||
typedef void (blkcg_pol_free_cpd_fn)(struct blkcg_policy_data *cpd);
|
typedef void (blkcg_pol_free_cpd_fn)(struct blkcg_policy_data *cpd);
|
||||||
|
typedef void (blkcg_pol_bind_cpd_fn)(struct blkcg_policy_data *cpd);
|
||||||
typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, int node);
|
typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, int node);
|
||||||
typedef void (blkcg_pol_init_pd_fn)(struct blkg_policy_data *pd);
|
typedef void (blkcg_pol_init_pd_fn)(struct blkg_policy_data *pd);
|
||||||
typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd);
|
typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd);
|
||||||
|
@ -155,6 +156,7 @@ struct blkcg_policy {
|
||||||
blkcg_pol_alloc_cpd_fn *cpd_alloc_fn;
|
blkcg_pol_alloc_cpd_fn *cpd_alloc_fn;
|
||||||
blkcg_pol_init_cpd_fn *cpd_init_fn;
|
blkcg_pol_init_cpd_fn *cpd_init_fn;
|
||||||
blkcg_pol_free_cpd_fn *cpd_free_fn;
|
blkcg_pol_free_cpd_fn *cpd_free_fn;
|
||||||
|
blkcg_pol_bind_cpd_fn *cpd_bind_fn;
|
||||||
|
|
||||||
blkcg_pol_alloc_pd_fn *pd_alloc_fn;
|
blkcg_pol_alloc_pd_fn *pd_alloc_fn;
|
||||||
blkcg_pol_init_pd_fn *pd_init_fn;
|
blkcg_pol_init_pd_fn *pd_init_fn;
|
||||||
|
|
Loading…
Reference in a new issue