diff options
author | Tejun Heo <tj@kernel.org> | 2015-08-18 17:55:36 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-08-18 18:49:36 -0400 |
commit | 69d7fde5909b614114343974cfc52cb8ff30b544 (patch) | |
tree | 231d68d331b286767109c616823781ed030ecb2b | |
parent | 3ecca62931ee6a30822a1ab7299bc8b8a21e5288 (diff) |
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>
-rw-r--r-- | Documentation/cgroups/unified-hierarchy.txt | 2 | ||||
-rw-r--r-- | block/blk-cgroup.c | 21 | ||||
-rw-r--r-- | block/cfq-iosched.c | 55 | ||||
-rw-r--r-- | include/linux/blk-cgroup.h | 2 |
4 files changed, 64 insertions, 16 deletions
diff --git a/Documentation/cgroups/unified-hierarchy.txt b/Documentation/cgroups/unified-hierarchy.txt index bd1ce15d5178..e0975c2cf03d 100644 --- a/Documentation/cgroups/unified-hierarchy.txt +++ b/Documentation/cgroups/unified-hierarchy.txt | |||
@@ -464,7 +464,7 @@ may be specified in any order and not all pairs have to be specified. | |||
464 | 464 | ||
465 | The weight setting, currently only available and effective if | 465 | The weight setting, currently only available and effective if |
466 | cfq-iosched is in use for the target device. The weight is | 466 | cfq-iosched is in use for the target device. The weight is |
467 | between 10 and 1000 and defaults to 500. The first line | 467 | between 1 and 10000 and defaults to 100. The first line |
468 | always contains the default weight in the following format to | 468 | always contains the default weight in the following format to |
469 | use when per-device setting is missing. | 469 | use when per-device setting is missing. |
470 | 470 | ||
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 88bdb73bd5e0..ac8370cb2515 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -1143,11 +1143,32 @@ static int blkcg_can_attach(struct cgroup_subsys_state *css, | |||
1143 | return ret; | 1143 | return ret; |
1144 | } | 1144 | } |
1145 | 1145 | ||
1146 | static void blkcg_bind(struct cgroup_subsys_state *root_css) | ||
1147 | { | ||
1148 | int i; | ||
1149 | |||
1150 | mutex_lock(&blkcg_pol_mutex); | ||
1151 | |||
1152 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | ||
1153 | struct blkcg_policy *pol = blkcg_policy[i]; | ||
1154 | struct blkcg *blkcg; | ||
1155 | |||
1156 | if (!pol || !pol->cpd_bind_fn) | ||
1157 | continue; | ||
1158 | |||
1159 | list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) | ||
1160 | if (blkcg->cpd[pol->plid]) | ||
1161 | pol->cpd_bind_fn(blkcg->cpd[pol->plid]); | ||
1162 | } | ||
1163 | mutex_unlock(&blkcg_pol_mutex); | ||
1164 | } | ||
1165 | |||
1146 | struct cgroup_subsys io_cgrp_subsys = { | 1166 | struct cgroup_subsys io_cgrp_subsys = { |
1147 | .css_alloc = blkcg_css_alloc, | 1167 | .css_alloc = blkcg_css_alloc, |
1148 | .css_offline = blkcg_css_offline, | 1168 | .css_offline = blkcg_css_offline, |
1149 | .css_free = blkcg_css_free, | 1169 | .css_free = blkcg_css_free, |
1150 | .can_attach = blkcg_can_attach, | 1170 | .can_attach = blkcg_can_attach, |
1171 | .bind = blkcg_bind, | ||
1151 | .dfl_cftypes = blkcg_files, | 1172 | .dfl_cftypes = blkcg_files, |
1152 | .legacy_cftypes = blkcg_legacy_files, | 1173 | .legacy_cftypes = blkcg_legacy_files, |
1153 | .legacy_name = "blkio", | 1174 | .legacy_name = "blkio", |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 0fe721eaff28..04de88463a98 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -1522,6 +1522,9 @@ static void cfq_init_cfqg_base(struct cfq_group *cfqg) | |||
1522 | } | 1522 | } |
1523 | 1523 | ||
1524 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | 1524 | #ifdef CONFIG_CFQ_GROUP_IOSCHED |
1525 | static int __cfq_set_weight(struct cgroup_subsys_state *css, u64 val, | ||
1526 | bool on_dfl, bool reset_dev, bool is_leaf_weight); | ||
1527 | |||
1525 | static void cfqg_stats_exit(struct cfqg_stats *stats) | 1528 | static void cfqg_stats_exit(struct cfqg_stats *stats) |
1526 | { | 1529 | { |
1527 | blkg_rwstat_exit(&stats->merged); | 1530 | blkg_rwstat_exit(&stats->merged); |
@@ -1578,14 +1581,14 @@ static struct blkcg_policy_data *cfq_cpd_alloc(gfp_t gfp) | |||
1578 | static void cfq_cpd_init(struct blkcg_policy_data *cpd) | 1581 | static void cfq_cpd_init(struct blkcg_policy_data *cpd) |
1579 | { | 1582 | { |
1580 | struct cfq_group_data *cgd = cpd_to_cfqgd(cpd); | 1583 | struct cfq_group_data *cgd = cpd_to_cfqgd(cpd); |
1584 | unsigned int weight = cgroup_on_dfl(blkcg_root.css.cgroup) ? | ||
1585 | CGROUP_WEIGHT_DFL : CFQ_WEIGHT_LEGACY_DFL; | ||
1581 | 1586 | ||
1582 | if (cpd_to_blkcg(cpd) == &blkcg_root) { | 1587 | if (cpd_to_blkcg(cpd) == &blkcg_root) |
1583 | cgd->weight = 2 * CFQ_WEIGHT_LEGACY_DFL; | 1588 | weight *= 2; |
1584 | cgd->leaf_weight = 2 * CFQ_WEIGHT_LEGACY_DFL; | 1589 | |
1585 | } else { | 1590 | cgd->weight = weight; |
1586 | cgd->weight = CFQ_WEIGHT_LEGACY_DFL; | 1591 | cgd->leaf_weight = weight; |
1587 | cgd->leaf_weight = CFQ_WEIGHT_LEGACY_DFL; | ||
1588 | } | ||
1589 | } | 1592 | } |
1590 | 1593 | ||
1591 | static void cfq_cpd_free(struct blkcg_policy_data *cpd) | 1594 | static void cfq_cpd_free(struct blkcg_policy_data *cpd) |
@@ -1593,6 +1596,19 @@ static void cfq_cpd_free(struct blkcg_policy_data *cpd) | |||
1593 | kfree(cpd_to_cfqgd(cpd)); | 1596 | kfree(cpd_to_cfqgd(cpd)); |
1594 | } | 1597 | } |
1595 | 1598 | ||
1599 | static void cfq_cpd_bind(struct blkcg_policy_data *cpd) | ||
1600 | { | ||
1601 | struct blkcg *blkcg = cpd_to_blkcg(cpd); | ||
1602 | bool on_dfl = cgroup_on_dfl(blkcg_root.css.cgroup); | ||
1603 | unsigned int weight = on_dfl ? CGROUP_WEIGHT_DFL : CFQ_WEIGHT_LEGACY_DFL; | ||
1604 | |||
1605 | if (blkcg == &blkcg_root) | ||
1606 | weight *= 2; | ||
1607 | |||
1608 | WARN_ON_ONCE(__cfq_set_weight(&blkcg->css, weight, on_dfl, true, false)); | ||
1609 | WARN_ON_ONCE(__cfq_set_weight(&blkcg->css, weight, on_dfl, true, true)); | ||
1610 | } | ||
1611 | |||
1596 | static struct blkg_policy_data *cfq_pd_alloc(gfp_t gfp, int node) | 1612 | static struct blkg_policy_data *cfq_pd_alloc(gfp_t gfp, int node) |
1597 | { | 1613 | { |
1598 | struct cfq_group *cfqg; | 1614 | struct cfq_group *cfqg; |
@@ -1742,6 +1758,8 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of, | |||
1742 | char *buf, size_t nbytes, loff_t off, | 1758 | char *buf, size_t nbytes, loff_t off, |
1743 | bool on_dfl, bool is_leaf_weight) | 1759 | bool on_dfl, bool is_leaf_weight) |
1744 | { | 1760 | { |
1761 | unsigned int min = on_dfl ? CGROUP_WEIGHT_MIN : CFQ_WEIGHT_LEGACY_MIN; | ||
1762 | unsigned int max = on_dfl ? CGROUP_WEIGHT_MAX : CFQ_WEIGHT_LEGACY_MAX; | ||
1745 | struct blkcg *blkcg = css_to_blkcg(of_css(of)); | 1763 | struct blkcg *blkcg = css_to_blkcg(of_css(of)); |
1746 | struct blkg_conf_ctx ctx; | 1764 | struct blkg_conf_ctx ctx; |
1747 | struct cfq_group *cfqg; | 1765 | struct cfq_group *cfqg; |
@@ -1769,7 +1787,7 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of, | |||
1769 | cfqgd = blkcg_to_cfqgd(blkcg); | 1787 | cfqgd = blkcg_to_cfqgd(blkcg); |
1770 | 1788 | ||
1771 | ret = -ERANGE; | 1789 | ret = -ERANGE; |
1772 | if (!v || (v >= CFQ_WEIGHT_LEGACY_MIN && v <= CFQ_WEIGHT_LEGACY_MAX)) { | 1790 | if (!v || (v >= min && v <= max)) { |
1773 | if (!is_leaf_weight) { | 1791 | if (!is_leaf_weight) { |
1774 | cfqg->dev_weight = v; | 1792 | cfqg->dev_weight = v; |
1775 | cfqg->new_weight = v ?: cfqgd->weight; | 1793 | cfqg->new_weight = v ?: cfqgd->weight; |
@@ -1797,15 +1815,17 @@ static ssize_t cfqg_set_leaf_weight_device(struct kernfs_open_file *of, | |||
1797 | } | 1815 | } |
1798 | 1816 | ||
1799 | static int __cfq_set_weight(struct cgroup_subsys_state *css, u64 val, | 1817 | static int __cfq_set_weight(struct cgroup_subsys_state *css, u64 val, |
1800 | bool is_leaf_weight) | 1818 | bool on_dfl, bool reset_dev, bool is_leaf_weight) |
1801 | { | 1819 | { |
1820 | unsigned int min = on_dfl ? CGROUP_WEIGHT_MIN : CFQ_WEIGHT_LEGACY_MIN; | ||
1821 | unsigned int max = on_dfl ? CGROUP_WEIGHT_MAX : CFQ_WEIGHT_LEGACY_MAX; | ||
1802 | struct blkcg *blkcg = css_to_blkcg(css); | 1822 | struct blkcg *blkcg = css_to_blkcg(css); |
1803 | struct blkcg_gq *blkg; | 1823 | struct blkcg_gq *blkg; |
1804 | struct cfq_group_data *cfqgd; | 1824 | struct cfq_group_data *cfqgd; |
1805 | int ret = 0; | 1825 | int ret = 0; |
1806 | 1826 | ||
1807 | if (val < CFQ_WEIGHT_LEGACY_MIN || val > CFQ_WEIGHT_LEGACY_MAX) | 1827 | if (val < min || val > max) |
1808 | return -EINVAL; | 1828 | return -ERANGE; |
1809 | 1829 | ||
1810 | spin_lock_irq(&blkcg->lock); | 1830 | spin_lock_irq(&blkcg->lock); |
1811 | cfqgd = blkcg_to_cfqgd(blkcg); | 1831 | cfqgd = blkcg_to_cfqgd(blkcg); |
@@ -1826,9 +1846,13 @@ static int __cfq_set_weight(struct cgroup_subsys_state *css, u64 val, | |||
1826 | continue; | 1846 | continue; |
1827 | 1847 | ||
1828 | if (!is_leaf_weight) { | 1848 | if (!is_leaf_weight) { |
1849 | if (reset_dev) | ||
1850 | cfqg->dev_weight = 0; | ||
1829 | if (!cfqg->dev_weight) | 1851 | if (!cfqg->dev_weight) |
1830 | cfqg->new_weight = cfqgd->weight; | 1852 | cfqg->new_weight = cfqgd->weight; |
1831 | } else { | 1853 | } else { |
1854 | if (reset_dev) | ||
1855 | cfqg->dev_leaf_weight = 0; | ||
1832 | if (!cfqg->dev_leaf_weight) | 1856 | if (!cfqg->dev_leaf_weight) |
1833 | cfqg->new_leaf_weight = cfqgd->leaf_weight; | 1857 | cfqg->new_leaf_weight = cfqgd->leaf_weight; |
1834 | } | 1858 | } |
@@ -1842,13 +1866,13 @@ out: | |||
1842 | static int cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, | 1866 | static int cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, |
1843 | u64 val) | 1867 | u64 val) |
1844 | { | 1868 | { |
1845 | return __cfq_set_weight(css, val, false); | 1869 | return __cfq_set_weight(css, val, false, false, false); |
1846 | } | 1870 | } |
1847 | 1871 | ||
1848 | static int cfq_set_leaf_weight(struct cgroup_subsys_state *css, | 1872 | static int cfq_set_leaf_weight(struct cgroup_subsys_state *css, |
1849 | struct cftype *cft, u64 val) | 1873 | struct cftype *cft, u64 val) |
1850 | { | 1874 | { |
1851 | return __cfq_set_weight(css, val, true); | 1875 | return __cfq_set_weight(css, val, false, false, true); |
1852 | } | 1876 | } |
1853 | 1877 | ||
1854 | static int cfqg_print_stat(struct seq_file *sf, void *v) | 1878 | 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, | |||
2135 | /* "WEIGHT" or "default WEIGHT" sets the default weight */ | 2159 | /* "WEIGHT" or "default WEIGHT" sets the default weight */ |
2136 | v = simple_strtoull(buf, &endp, 0); | 2160 | v = simple_strtoull(buf, &endp, 0); |
2137 | if (*endp == '\0' || sscanf(buf, "default %llu", &v) == 1) { | 2161 | if (*endp == '\0' || sscanf(buf, "default %llu", &v) == 1) { |
2138 | ret = __cfq_set_weight(of_css(of), v, false); | 2162 | ret = __cfq_set_weight(of_css(of), v, true, false, false); |
2139 | return ret ?: nbytes; | 2163 | return ret ?: nbytes; |
2140 | } | 2164 | } |
2141 | 2165 | ||
@@ -4512,9 +4536,9 @@ static int cfq_init_queue(struct request_queue *q, struct elevator_type *e) | |||
4512 | goto out_free; | 4536 | goto out_free; |
4513 | 4537 | ||
4514 | cfq_init_cfqg_base(cfqd->root_group); | 4538 | cfq_init_cfqg_base(cfqd->root_group); |
4515 | #endif | ||
4516 | cfqd->root_group->weight = 2 * CFQ_WEIGHT_LEGACY_DFL; | 4539 | cfqd->root_group->weight = 2 * CFQ_WEIGHT_LEGACY_DFL; |
4517 | cfqd->root_group->leaf_weight = 2 * CFQ_WEIGHT_LEGACY_DFL; | 4540 | cfqd->root_group->leaf_weight = 2 * CFQ_WEIGHT_LEGACY_DFL; |
4541 | #endif | ||
4518 | 4542 | ||
4519 | /* | 4543 | /* |
4520 | * Not strictly needed (since RB_ROOT just clears the node and we | 4544 | * Not strictly needed (since RB_ROOT just clears the node and we |
@@ -4715,6 +4739,7 @@ static struct blkcg_policy blkcg_policy_cfq = { | |||
4715 | .cpd_alloc_fn = cfq_cpd_alloc, | 4739 | .cpd_alloc_fn = cfq_cpd_alloc, |
4716 | .cpd_init_fn = cfq_cpd_init, | 4740 | .cpd_init_fn = cfq_cpd_init, |
4717 | .cpd_free_fn = cfq_cpd_free, | 4741 | .cpd_free_fn = cfq_cpd_free, |
4742 | .cpd_bind_fn = cfq_cpd_bind, | ||
4718 | 4743 | ||
4719 | .pd_alloc_fn = cfq_pd_alloc, | 4744 | .pd_alloc_fn = cfq_pd_alloc, |
4720 | .pd_init_fn = cfq_pd_init, | 4745 | .pd_init_fn = cfq_pd_init, |
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index 9a7c4bd45fff..0a5cc7a1109b 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h | |||
@@ -138,6 +138,7 @@ struct blkcg_gq { | |||
138 | typedef struct blkcg_policy_data *(blkcg_pol_alloc_cpd_fn)(gfp_t gfp); | 138 | typedef struct blkcg_policy_data *(blkcg_pol_alloc_cpd_fn)(gfp_t gfp); |
139 | typedef void (blkcg_pol_init_cpd_fn)(struct blkcg_policy_data *cpd); | 139 | typedef void (blkcg_pol_init_cpd_fn)(struct blkcg_policy_data *cpd); |
140 | typedef void (blkcg_pol_free_cpd_fn)(struct blkcg_policy_data *cpd); | 140 | typedef void (blkcg_pol_free_cpd_fn)(struct blkcg_policy_data *cpd); |
141 | typedef void (blkcg_pol_bind_cpd_fn)(struct blkcg_policy_data *cpd); | ||
141 | typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, int node); | 142 | typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, int node); |
142 | typedef void (blkcg_pol_init_pd_fn)(struct blkg_policy_data *pd); | 143 | typedef void (blkcg_pol_init_pd_fn)(struct blkg_policy_data *pd); |
143 | typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd); | 144 | typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd); |
@@ -155,6 +156,7 @@ struct blkcg_policy { | |||
155 | blkcg_pol_alloc_cpd_fn *cpd_alloc_fn; | 156 | blkcg_pol_alloc_cpd_fn *cpd_alloc_fn; |
156 | blkcg_pol_init_cpd_fn *cpd_init_fn; | 157 | blkcg_pol_init_cpd_fn *cpd_init_fn; |
157 | blkcg_pol_free_cpd_fn *cpd_free_fn; | 158 | blkcg_pol_free_cpd_fn *cpd_free_fn; |
159 | blkcg_pol_bind_cpd_fn *cpd_bind_fn; | ||
158 | 160 | ||
159 | blkcg_pol_alloc_pd_fn *pd_alloc_fn; | 161 | blkcg_pol_alloc_pd_fn *pd_alloc_fn; |
160 | blkcg_pol_init_pd_fn *pd_init_fn; | 162 | blkcg_pol_init_pd_fn *pd_init_fn; |