diff options
author | Tejun Heo <tj@kernel.org> | 2013-05-14 16:52:31 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-05-14 16:52:31 -0400 |
commit | db61367038dcd222476881cb09fd54661b3cd508 (patch) | |
tree | 2c13a848bc64d34175ab7abbd0774b816a41f20e /block/blk-cgroup.c | |
parent | aa539cb38f4f1365ad52fed6a857b25f8b4dc06c (diff) |
blkcg: invoke blkcg_policy->pd_init() after parent is linked
Currently, when creating a new blkcg_gq, each policy's pd_init_fn() is
invoked in blkg_alloc() before the parent is linked. This makes it
difficult for policies to perform initializations which are dependent
on the parent.
This patch moves pd_init_fn() invocations to blkg_create() after the
parent blkg is linked where the new blkg is fully initialized. As
this means that blkg_free() can't assume that pd's are initialized,
pd_exit_fn() invocations are moved to __blkg_release(). This
guarantees that pd_exit_fn() is also invoked with fully initialized
blkgs with valid parent pointers.
This will help implementing hierarchy support in blk-throttle.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Diffstat (limited to 'block/blk-cgroup.c')
-rw-r--r-- | block/blk-cgroup.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index b950306838ad..6bbe0a939596 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -51,18 +51,8 @@ static void blkg_free(struct blkcg_gq *blkg) | |||
51 | if (!blkg) | 51 | if (!blkg) |
52 | return; | 52 | return; |
53 | 53 | ||
54 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | 54 | for (i = 0; i < BLKCG_MAX_POLS; i++) |
55 | struct blkcg_policy *pol = blkcg_policy[i]; | 55 | kfree(blkg->pd[i]); |
56 | struct blkg_policy_data *pd = blkg->pd[i]; | ||
57 | |||
58 | if (!pd) | ||
59 | continue; | ||
60 | |||
61 | if (pol && pol->pd_exit_fn) | ||
62 | pol->pd_exit_fn(blkg); | ||
63 | |||
64 | kfree(pd); | ||
65 | } | ||
66 | 56 | ||
67 | blk_exit_rl(&blkg->rl); | 57 | blk_exit_rl(&blkg->rl); |
68 | kfree(blkg); | 58 | kfree(blkg); |
@@ -114,10 +104,6 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q, | |||
114 | blkg->pd[i] = pd; | 104 | blkg->pd[i] = pd; |
115 | pd->blkg = blkg; | 105 | pd->blkg = blkg; |
116 | pd->plid = i; | 106 | pd->plid = i; |
117 | |||
118 | /* invoke per-policy init */ | ||
119 | if (pol->pd_init_fn) | ||
120 | pol->pd_init_fn(blkg); | ||
121 | } | 107 | } |
122 | 108 | ||
123 | return blkg; | 109 | return blkg; |
@@ -214,7 +200,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, | |||
214 | } | 200 | } |
215 | blkg = new_blkg; | 201 | blkg = new_blkg; |
216 | 202 | ||
217 | /* link parent and insert */ | 203 | /* link parent */ |
218 | if (blkcg_parent(blkcg)) { | 204 | if (blkcg_parent(blkcg)) { |
219 | blkg->parent = __blkg_lookup(blkcg_parent(blkcg), q, false); | 205 | blkg->parent = __blkg_lookup(blkcg_parent(blkcg), q, false); |
220 | if (WARN_ON_ONCE(!blkg->parent)) { | 206 | if (WARN_ON_ONCE(!blkg->parent)) { |
@@ -224,6 +210,15 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, | |||
224 | blkg_get(blkg->parent); | 210 | blkg_get(blkg->parent); |
225 | } | 211 | } |
226 | 212 | ||
213 | /* invoke per-policy init */ | ||
214 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | ||
215 | struct blkcg_policy *pol = blkcg_policy[i]; | ||
216 | |||
217 | if (blkg->pd[i] && pol->pd_init_fn) | ||
218 | pol->pd_init_fn(blkg); | ||
219 | } | ||
220 | |||
221 | /* insert */ | ||
227 | spin_lock(&blkcg->lock); | 222 | spin_lock(&blkcg->lock); |
228 | ret = radix_tree_insert(&blkcg->blkg_tree, q->id, blkg); | 223 | ret = radix_tree_insert(&blkcg->blkg_tree, q->id, blkg); |
229 | if (likely(!ret)) { | 224 | if (likely(!ret)) { |
@@ -381,6 +376,16 @@ static void blkg_rcu_free(struct rcu_head *rcu_head) | |||
381 | 376 | ||
382 | void __blkg_release(struct blkcg_gq *blkg) | 377 | void __blkg_release(struct blkcg_gq *blkg) |
383 | { | 378 | { |
379 | int i; | ||
380 | |||
381 | /* tell policies that this one is being freed */ | ||
382 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | ||
383 | struct blkcg_policy *pol = blkcg_policy[i]; | ||
384 | |||
385 | if (blkg->pd[i] && pol->pd_exit_fn) | ||
386 | pol->pd_exit_fn(blkg); | ||
387 | } | ||
388 | |||
384 | /* release the blkcg and parent blkg refs this blkg has been holding */ | 389 | /* release the blkcg and parent blkg refs this blkg has been holding */ |
385 | css_put(&blkg->blkcg->css); | 390 | css_put(&blkg->blkcg->css); |
386 | if (blkg->parent) | 391 | if (blkg->parent) |