diff options
author | Tejun Heo <tj@kernel.org> | 2015-08-18 17:55:16 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-08-18 18:49:17 -0400 |
commit | e4a9bde9589fdc51283755cdd75d47b27ca7c6fb (patch) | |
tree | cc26b9cdba09e6571342f16182cafee5e82852b0 | |
parent | 814376483e7d85b69a70634633f1f9d01c6ee0cf (diff) |
blkcg: replace blkcg_policy->cpd_size with ->cpd_alloc/free_fn() methods
Each active policy has a cpd (blkcg_policy_data) on each blkcg. The
cpd's were allocated by blkcg core and each policy could request to
allocate extra space at the end by setting blkcg_policy->cpd_size
larger than the size of cpd.
This is a bit unusual but blkg (blkcg_gq) policy data used to be
handled this way too so it made sense to be consistent; however, blkg
policy data switched to alloc/free callbacks.
This patch makes similar changes to cpd handling.
blkcg_policy->cpd_alloc/free_fn() are added to replace ->cpd_size. As
cpd allocation is now done from policy side, it can simply allocate a
larger area which embeds cpd at the beginning.
As ->cpd_alloc_fn() may be able to perform all necessary
initializations, this patch makes ->cpd_init_fn() optional.
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-- | block/blk-cgroup.c | 39 | ||||
-rw-r--r-- | block/cfq-iosched.c | 19 | ||||
-rw-r--r-- | include/linux/blk-cgroup.h | 17 |
3 files changed, 52 insertions, 23 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 247c42c8c83b..2b4354b6b5de 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -817,11 +817,15 @@ static void blkcg_css_free(struct cgroup_subsys_state *css) | |||
817 | int i; | 817 | int i; |
818 | 818 | ||
819 | mutex_lock(&blkcg_pol_mutex); | 819 | mutex_lock(&blkcg_pol_mutex); |
820 | |||
820 | list_del(&blkcg->all_blkcgs_node); | 821 | list_del(&blkcg->all_blkcgs_node); |
821 | mutex_unlock(&blkcg_pol_mutex); | ||
822 | 822 | ||
823 | for (i = 0; i < BLKCG_MAX_POLS; i++) | 823 | for (i = 0; i < BLKCG_MAX_POLS; i++) |
824 | kfree(blkcg->cpd[i]); | 824 | if (blkcg->cpd[i]) |
825 | blkcg_policy[i]->cpd_free_fn(blkcg->cpd[i]); | ||
826 | |||
827 | mutex_unlock(&blkcg_pol_mutex); | ||
828 | |||
825 | kfree(blkcg); | 829 | kfree(blkcg); |
826 | } | 830 | } |
827 | 831 | ||
@@ -854,11 +858,10 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css) | |||
854 | * check if the policy requires any specific per-cgroup | 858 | * check if the policy requires any specific per-cgroup |
855 | * data: if it does, allocate and initialize it. | 859 | * data: if it does, allocate and initialize it. |
856 | */ | 860 | */ |
857 | if (!pol || !pol->cpd_size) | 861 | if (!pol || !pol->cpd_alloc_fn) |
858 | continue; | 862 | continue; |
859 | 863 | ||
860 | BUG_ON(blkcg->cpd[i]); | 864 | cpd = pol->cpd_alloc_fn(GFP_KERNEL); |
861 | cpd = kzalloc(pol->cpd_size, GFP_KERNEL); | ||
862 | if (!cpd) { | 865 | if (!cpd) { |
863 | ret = ERR_PTR(-ENOMEM); | 866 | ret = ERR_PTR(-ENOMEM); |
864 | goto free_pd_blkcg; | 867 | goto free_pd_blkcg; |
@@ -866,7 +869,8 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css) | |||
866 | blkcg->cpd[i] = cpd; | 869 | blkcg->cpd[i] = cpd; |
867 | cpd->blkcg = blkcg; | 870 | cpd->blkcg = blkcg; |
868 | cpd->plid = i; | 871 | cpd->plid = i; |
869 | pol->cpd_init_fn(cpd); | 872 | if (pol->cpd_init_fn) |
873 | pol->cpd_init_fn(cpd); | ||
870 | } | 874 | } |
871 | 875 | ||
872 | spin_lock_init(&blkcg->lock); | 876 | spin_lock_init(&blkcg->lock); |
@@ -882,7 +886,8 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css) | |||
882 | 886 | ||
883 | free_pd_blkcg: | 887 | free_pd_blkcg: |
884 | for (i--; i >= 0; i--) | 888 | for (i--; i >= 0; i--) |
885 | kfree(blkcg->cpd[i]); | 889 | if (blkcg->cpd[i]) |
890 | blkcg_policy[i]->cpd_free_fn(blkcg->cpd[i]); | ||
886 | free_blkcg: | 891 | free_blkcg: |
887 | kfree(blkcg); | 892 | kfree(blkcg); |
888 | mutex_unlock(&blkcg_pol_mutex); | 893 | mutex_unlock(&blkcg_pol_mutex); |
@@ -1159,11 +1164,11 @@ int blkcg_policy_register(struct blkcg_policy *pol) | |||
1159 | blkcg_policy[pol->plid] = pol; | 1164 | blkcg_policy[pol->plid] = pol; |
1160 | 1165 | ||
1161 | /* allocate and install cpd's */ | 1166 | /* allocate and install cpd's */ |
1162 | if (pol->cpd_size) { | 1167 | if (pol->cpd_alloc_fn) { |
1163 | list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) { | 1168 | list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) { |
1164 | struct blkcg_policy_data *cpd; | 1169 | struct blkcg_policy_data *cpd; |
1165 | 1170 | ||
1166 | cpd = kzalloc(pol->cpd_size, GFP_KERNEL); | 1171 | cpd = pol->cpd_alloc_fn(GFP_KERNEL); |
1167 | if (!cpd) { | 1172 | if (!cpd) { |
1168 | mutex_unlock(&blkcg_pol_mutex); | 1173 | mutex_unlock(&blkcg_pol_mutex); |
1169 | goto err_free_cpds; | 1174 | goto err_free_cpds; |
@@ -1186,10 +1191,12 @@ int blkcg_policy_register(struct blkcg_policy *pol) | |||
1186 | return 0; | 1191 | return 0; |
1187 | 1192 | ||
1188 | err_free_cpds: | 1193 | err_free_cpds: |
1189 | if (pol->cpd_size) { | 1194 | if (pol->cpd_alloc_fn) { |
1190 | list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) { | 1195 | list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) { |
1191 | kfree(blkcg->cpd[pol->plid]); | 1196 | if (blkcg->cpd[pol->plid]) { |
1192 | blkcg->cpd[pol->plid] = NULL; | 1197 | pol->cpd_free_fn(blkcg->cpd[pol->plid]); |
1198 | blkcg->cpd[pol->plid] = NULL; | ||
1199 | } | ||
1193 | } | 1200 | } |
1194 | } | 1201 | } |
1195 | blkcg_policy[pol->plid] = NULL; | 1202 | blkcg_policy[pol->plid] = NULL; |
@@ -1222,10 +1229,12 @@ void blkcg_policy_unregister(struct blkcg_policy *pol) | |||
1222 | /* remove cpds and unregister */ | 1229 | /* remove cpds and unregister */ |
1223 | mutex_lock(&blkcg_pol_mutex); | 1230 | mutex_lock(&blkcg_pol_mutex); |
1224 | 1231 | ||
1225 | if (pol->cpd_size) { | 1232 | if (pol->cpd_alloc_fn) { |
1226 | list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) { | 1233 | list_for_each_entry(blkcg, &all_blkcgs, all_blkcgs_node) { |
1227 | kfree(blkcg->cpd[pol->plid]); | 1234 | if (blkcg->cpd[pol->plid]) { |
1228 | blkcg->cpd[pol->plid] = NULL; | 1235 | pol->cpd_free_fn(blkcg->cpd[pol->plid]); |
1236 | blkcg->cpd[pol->plid] = NULL; | ||
1237 | } | ||
1229 | } | 1238 | } |
1230 | } | 1239 | } |
1231 | blkcg_policy[pol->plid] = NULL; | 1240 | blkcg_policy[pol->plid] = NULL; |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index dd6ea9ee6245..a4429b366820 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -1568,6 +1568,16 @@ static void cfqg_stats_init(struct cfqg_stats *stats) | |||
1568 | #endif | 1568 | #endif |
1569 | } | 1569 | } |
1570 | 1570 | ||
1571 | static struct blkcg_policy_data *cfq_cpd_alloc(gfp_t gfp) | ||
1572 | { | ||
1573 | struct cfq_group_data *cgd; | ||
1574 | |||
1575 | cgd = kzalloc(sizeof(*cgd), GFP_KERNEL); | ||
1576 | if (!cgd) | ||
1577 | return NULL; | ||
1578 | return &cgd->cpd; | ||
1579 | } | ||
1580 | |||
1571 | static void cfq_cpd_init(struct blkcg_policy_data *cpd) | 1581 | static void cfq_cpd_init(struct blkcg_policy_data *cpd) |
1572 | { | 1582 | { |
1573 | struct cfq_group_data *cgd = cpd_to_cfqgd(cpd); | 1583 | struct cfq_group_data *cgd = cpd_to_cfqgd(cpd); |
@@ -1581,6 +1591,11 @@ static void cfq_cpd_init(struct blkcg_policy_data *cpd) | |||
1581 | } | 1591 | } |
1582 | } | 1592 | } |
1583 | 1593 | ||
1594 | static void cfq_cpd_free(struct blkcg_policy_data *cpd) | ||
1595 | { | ||
1596 | kfree(cpd_to_cfqgd(cpd)); | ||
1597 | } | ||
1598 | |||
1584 | static struct blkg_policy_data *cfq_pd_alloc(gfp_t gfp, int node) | 1599 | static struct blkg_policy_data *cfq_pd_alloc(gfp_t gfp, int node) |
1585 | { | 1600 | { |
1586 | struct cfq_group *cfqg; | 1601 | struct cfq_group *cfqg; |
@@ -4649,10 +4664,12 @@ static struct elevator_type iosched_cfq = { | |||
4649 | 4664 | ||
4650 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | 4665 | #ifdef CONFIG_CFQ_GROUP_IOSCHED |
4651 | static struct blkcg_policy blkcg_policy_cfq = { | 4666 | static struct blkcg_policy blkcg_policy_cfq = { |
4652 | .cpd_size = sizeof(struct cfq_group_data), | ||
4653 | .cftypes = cfq_blkcg_files, | 4667 | .cftypes = cfq_blkcg_files, |
4654 | 4668 | ||
4669 | .cpd_alloc_fn = cfq_cpd_alloc, | ||
4655 | .cpd_init_fn = cfq_cpd_init, | 4670 | .cpd_init_fn = cfq_cpd_init, |
4671 | .cpd_free_fn = cfq_cpd_free, | ||
4672 | |||
4656 | .pd_alloc_fn = cfq_pd_alloc, | 4673 | .pd_alloc_fn = cfq_pd_alloc, |
4657 | .pd_init_fn = cfq_pd_init, | 4674 | .pd_init_fn = cfq_pd_init, |
4658 | .pd_offline_fn = cfq_pd_offline, | 4675 | .pd_offline_fn = cfq_pd_offline, |
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index 7988d4749fff..15f2382bc723 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h | |||
@@ -81,11 +81,11 @@ struct blkg_policy_data { | |||
81 | }; | 81 | }; |
82 | 82 | ||
83 | /* | 83 | /* |
84 | * Policies that need to keep per-blkcg data which is independent | 84 | * Policies that need to keep per-blkcg data which is independent from any |
85 | * from any request_queue associated to it must specify its size | 85 | * request_queue associated to it should implement cpd_alloc/free_fn() |
86 | * with the cpd_size field of the blkcg_policy structure and | 86 | * methods. A policy can allocate private data area by allocating larger |
87 | * embed a blkcg_policy_data in it. cpd_init() is invoked to let | 87 | * data structure which embeds blkcg_policy_data at the beginning. |
88 | * each policy handle per-blkcg data. | 88 | * cpd_init() is invoked to let each policy handle per-blkcg data. |
89 | */ | 89 | */ |
90 | struct blkcg_policy_data { | 90 | struct blkcg_policy_data { |
91 | /* the blkcg and policy id this per-policy data belongs to */ | 91 | /* the blkcg and policy id this per-policy data belongs to */ |
@@ -124,7 +124,9 @@ struct blkcg_gq { | |||
124 | struct rcu_head rcu_head; | 124 | struct rcu_head rcu_head; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | typedef struct blkcg_policy_data *(blkcg_pol_alloc_cpd_fn)(gfp_t gfp); | ||
127 | typedef void (blkcg_pol_init_cpd_fn)(struct blkcg_policy_data *cpd); | 128 | typedef void (blkcg_pol_init_cpd_fn)(struct blkcg_policy_data *cpd); |
129 | typedef void (blkcg_pol_free_cpd_fn)(struct blkcg_policy_data *cpd); | ||
128 | typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, int node); | 130 | typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, int node); |
129 | typedef void (blkcg_pol_init_pd_fn)(struct blkg_policy_data *pd); | 131 | typedef void (blkcg_pol_init_pd_fn)(struct blkg_policy_data *pd); |
130 | typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd); | 132 | typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd); |
@@ -134,13 +136,14 @@ typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkg_policy_data *pd); | |||
134 | 136 | ||
135 | struct blkcg_policy { | 137 | struct blkcg_policy { |
136 | int plid; | 138 | int plid; |
137 | /* policy specific per-blkcg data size */ | ||
138 | size_t cpd_size; | ||
139 | /* cgroup files for the policy */ | 139 | /* cgroup files for the policy */ |
140 | struct cftype *cftypes; | 140 | struct cftype *cftypes; |
141 | 141 | ||
142 | /* operations */ | 142 | /* operations */ |
143 | blkcg_pol_alloc_cpd_fn *cpd_alloc_fn; | ||
143 | blkcg_pol_init_cpd_fn *cpd_init_fn; | 144 | blkcg_pol_init_cpd_fn *cpd_init_fn; |
145 | blkcg_pol_free_cpd_fn *cpd_free_fn; | ||
146 | |||
144 | blkcg_pol_alloc_pd_fn *pd_alloc_fn; | 147 | blkcg_pol_alloc_pd_fn *pd_alloc_fn; |
145 | blkcg_pol_init_pd_fn *pd_init_fn; | 148 | blkcg_pol_init_pd_fn *pd_init_fn; |
146 | blkcg_pol_online_pd_fn *pd_online_fn; | 149 | blkcg_pol_online_pd_fn *pd_online_fn; |