]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - block/cfq-iosched.c
block, cgroup: implement policy-specific per-blkcg data
[mirror_ubuntu-bionic-kernel.git] / block / cfq-iosched.c
index 402be013912203a80df8b6560cec565b78aa8d28..c808ad87652d2818f7770cc6abd59f02110ab4c8 100644 (file)
@@ -67,6 +67,11 @@ static struct kmem_cache *cfq_pool;
 #define sample_valid(samples)  ((samples) > 80)
 #define rb_entry_cfqg(node)    rb_entry((node), struct cfq_group, rb_node)
 
+/* blkio-related constants */
+#define CFQ_WEIGHT_MIN          10
+#define CFQ_WEIGHT_MAX          1000
+#define CFQ_WEIGHT_DEFAULT      500
+
 struct cfq_ttime {
        unsigned long last_end_request;
 
@@ -212,6 +217,15 @@ struct cfqg_stats {
 #endif /* CONFIG_CFQ_GROUP_IOSCHED */
 };
 
+/* Per-cgroup data */
+struct cfq_group_data {
+       /* must be the first member */
+       struct blkcg_policy_data pd;
+
+       unsigned int weight;
+       unsigned int leaf_weight;
+};
+
 /* This is per cgroup per device grouping structure */
 struct cfq_group {
        /* must be the first member */
@@ -451,6 +465,12 @@ static inline struct cfq_group *pd_to_cfqg(struct blkg_policy_data *pd)
        return pd ? container_of(pd, struct cfq_group, pd) : NULL;
 }
 
+static struct cfq_group_data
+*cpd_to_cfqgd(struct blkcg_policy_data *cpd)
+{
+       return cpd ? container_of(cpd, struct cfq_group_data, pd) : NULL;
+}
+
 static inline struct blkcg_gq *cfqg_to_blkg(struct cfq_group *cfqg)
 {
        return pd_to_blkg(&cfqg->pd);
@@ -607,6 +627,11 @@ static inline struct cfq_group *blkg_to_cfqg(struct blkcg_gq *blkg)
        return pd_to_cfqg(blkg_to_pd(blkg, &blkcg_policy_cfq));
 }
 
+static struct cfq_group_data *blkcg_to_cfqgd(struct blkcg *blkcg)
+{
+       return cpd_to_cfqgd(blkcg_to_cpd(blkcg, &blkcg_policy_cfq));
+}
+
 static inline struct cfq_group *cfqg_parent(struct cfq_group *cfqg)
 {
        struct blkcg_gq *pblkg = cfqg_to_blkg(cfqg)->parent;
@@ -1544,13 +1569,28 @@ static void cfqg_stats_init(struct cfqg_stats *stats)
 #endif
 }
 
+static void cfq_cpd_init(const struct blkcg *blkcg)
+{
+       struct cfq_group_data *cgd =
+               cpd_to_cfqgd(blkcg->pd[blkcg_policy_cfq.plid]);
+
+       if (blkcg == &blkcg_root) {
+               cgd->weight = 2 * CFQ_WEIGHT_DEFAULT;
+               cgd->leaf_weight = 2 * CFQ_WEIGHT_DEFAULT;
+       } else {
+               cgd->weight = CFQ_WEIGHT_DEFAULT;
+               cgd->leaf_weight = CFQ_WEIGHT_DEFAULT;
+       }
+}
+
 static void cfq_pd_init(struct blkcg_gq *blkg)
 {
        struct cfq_group *cfqg = blkg_to_cfqg(blkg);
+       struct cfq_group_data *cgd = blkcg_to_cfqgd(blkg->blkcg);
 
        cfq_init_cfqg_base(cfqg);
-       cfqg->weight = blkg->blkcg->cfq_weight;
-       cfqg->leaf_weight = blkg->blkcg->cfq_leaf_weight;
+       cfqg->weight = cgd->weight;
+       cfqg->leaf_weight = cgd->leaf_weight;
        cfqg_stats_init(&cfqg->stats);
        cfqg_stats_init(&cfqg->dead_stats);
 }
@@ -1673,13 +1713,17 @@ static int cfqg_print_leaf_weight_device(struct seq_file *sf, void *v)
 
 static int cfq_print_weight(struct seq_file *sf, void *v)
 {
-       seq_printf(sf, "%u\n", css_to_blkcg(seq_css(sf))->cfq_weight);
+       struct blkcg *blkcg = css_to_blkcg(seq_css(sf));
+
+       seq_printf(sf, "%u\n", blkcg_to_cfqgd(blkcg)->weight);
        return 0;
 }
 
 static int cfq_print_leaf_weight(struct seq_file *sf, void *v)
 {
-       seq_printf(sf, "%u\n", css_to_blkcg(seq_css(sf))->cfq_leaf_weight);
+       struct blkcg *blkcg = css_to_blkcg(seq_css(sf));
+
+       seq_printf(sf, "%u\n", blkcg_to_cfqgd(blkcg)->leaf_weight);
        return 0;
 }
 
@@ -1690,6 +1734,7 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of,
        struct blkcg *blkcg = css_to_blkcg(of_css(of));
        struct blkg_conf_ctx ctx;
        struct cfq_group *cfqg;
+       struct cfq_group_data *cfqgd;
        int ret;
 
        ret = blkg_conf_prep(blkcg, &blkcg_policy_cfq, buf, &ctx);
@@ -1698,13 +1743,14 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of,
 
        ret = -EINVAL;
        cfqg = blkg_to_cfqg(ctx.blkg);
+       cfqgd = blkcg_to_cfqgd(blkcg);
        if (!ctx.v || (ctx.v >= CFQ_WEIGHT_MIN && ctx.v <= CFQ_WEIGHT_MAX)) {
                if (!is_leaf_weight) {
                        cfqg->dev_weight = ctx.v;
-                       cfqg->new_weight = ctx.v ?: blkcg->cfq_weight;
+                       cfqg->new_weight = ctx.v ?: cfqgd->weight;
                } else {
                        cfqg->dev_leaf_weight = ctx.v;
-                       cfqg->new_leaf_weight = ctx.v ?: blkcg->cfq_leaf_weight;
+                       cfqg->new_leaf_weight = ctx.v ?: cfqgd->leaf_weight;
                }
                ret = 0;
        }
@@ -1730,16 +1776,18 @@ static int __cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft,
 {
        struct blkcg *blkcg = css_to_blkcg(css);
        struct blkcg_gq *blkg;
+       struct cfq_group_data *cfqgd;
 
        if (val < CFQ_WEIGHT_MIN || val > CFQ_WEIGHT_MAX)
                return -EINVAL;
 
        spin_lock_irq(&blkcg->lock);
+       cfqgd = blkcg_to_cfqgd(blkcg);
 
        if (!is_leaf_weight)
-               blkcg->cfq_weight = val;
+               cfqgd->weight = val;
        else
-               blkcg->cfq_leaf_weight = val;
+               cfqgd->leaf_weight = val;
 
        hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
                struct cfq_group *cfqg = blkg_to_cfqg(blkg);
@@ -1749,10 +1797,10 @@ static int __cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft,
 
                if (!is_leaf_weight) {
                        if (!cfqg->dev_weight)
-                               cfqg->new_weight = blkcg->cfq_weight;
+                               cfqg->new_weight = cfqgd->weight;
                } else {
                        if (!cfqg->dev_leaf_weight)
-                               cfqg->new_leaf_weight = blkcg->cfq_leaf_weight;
+                               cfqg->new_leaf_weight = cfqgd->leaf_weight;
                }
        }
 
@@ -4603,8 +4651,10 @@ static struct elevator_type iosched_cfq = {
 #ifdef CONFIG_CFQ_GROUP_IOSCHED
 static struct blkcg_policy blkcg_policy_cfq = {
        .pd_size                = sizeof(struct cfq_group),
+       .cpd_size               = sizeof(struct cfq_group_data),
        .cftypes                = cfq_blkcg_files,
 
+       .cpd_init_fn            = cfq_cpd_init,
        .pd_init_fn             = cfq_pd_init,
        .pd_offline_fn          = cfq_pd_offline,
        .pd_reset_stats_fn      = cfq_pd_reset_stats,