diff options
author | Tejun Heo <tj@kernel.org> | 2013-01-09 11:05:12 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-01-09 11:05:12 -0500 |
commit | f427d909648aa592c9588d0f66b5b457752a0cd1 (patch) | |
tree | d6f91a6d46a1302f0cca6137851f0806364b7965 /block | |
parent | b276a876a014c5fa58a16f247c0933f6c42112e3 (diff) |
blkcg: implement blkcg_policy->on/offline_pd_fn() and blkcg_gq->online
Add two blkcg_policy methods, ->online_pd_fn() and ->offline_pd_fn(),
which are invoked as the policy_data gets activated and deactivated
while holding both blkcg and q locks.
Also, add blkcg_gq->online bool, which is set and cleared as the
blkcg_gq gets activated and deactivated. This flag also is toggled
while holding both blkcg and q locks.
These will be used to implement hierarchical stats.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-cgroup.c | 21 | ||||
-rw-r--r-- | block/blk-cgroup.h | 7 |
2 files changed, 27 insertions, 1 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 3a8de321d1f6..4d625d28e070 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -182,7 +182,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, | |||
182 | struct blkcg_gq *new_blkg) | 182 | struct blkcg_gq *new_blkg) |
183 | { | 183 | { |
184 | struct blkcg_gq *blkg; | 184 | struct blkcg_gq *blkg; |
185 | int ret; | 185 | int i, ret; |
186 | 186 | ||
187 | WARN_ON_ONCE(!rcu_read_lock_held()); | 187 | WARN_ON_ONCE(!rcu_read_lock_held()); |
188 | lockdep_assert_held(q->queue_lock); | 188 | lockdep_assert_held(q->queue_lock); |
@@ -218,7 +218,15 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, | |||
218 | if (likely(!ret)) { | 218 | if (likely(!ret)) { |
219 | hlist_add_head_rcu(&blkg->blkcg_node, &blkcg->blkg_list); | 219 | hlist_add_head_rcu(&blkg->blkcg_node, &blkcg->blkg_list); |
220 | list_add(&blkg->q_node, &q->blkg_list); | 220 | list_add(&blkg->q_node, &q->blkg_list); |
221 | |||
222 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | ||
223 | struct blkcg_policy *pol = blkcg_policy[i]; | ||
224 | |||
225 | if (blkg->pd[i] && pol->pd_online_fn) | ||
226 | pol->pd_online_fn(blkg); | ||
227 | } | ||
221 | } | 228 | } |
229 | blkg->online = true; | ||
222 | spin_unlock(&blkcg->lock); | 230 | spin_unlock(&blkcg->lock); |
223 | 231 | ||
224 | if (!ret) | 232 | if (!ret) |
@@ -291,6 +299,7 @@ EXPORT_SYMBOL_GPL(blkg_lookup_create); | |||
291 | static void blkg_destroy(struct blkcg_gq *blkg) | 299 | static void blkg_destroy(struct blkcg_gq *blkg) |
292 | { | 300 | { |
293 | struct blkcg *blkcg = blkg->blkcg; | 301 | struct blkcg *blkcg = blkg->blkcg; |
302 | int i; | ||
294 | 303 | ||
295 | lockdep_assert_held(blkg->q->queue_lock); | 304 | lockdep_assert_held(blkg->q->queue_lock); |
296 | lockdep_assert_held(&blkcg->lock); | 305 | lockdep_assert_held(&blkcg->lock); |
@@ -299,6 +308,14 @@ static void blkg_destroy(struct blkcg_gq *blkg) | |||
299 | WARN_ON_ONCE(list_empty(&blkg->q_node)); | 308 | WARN_ON_ONCE(list_empty(&blkg->q_node)); |
300 | WARN_ON_ONCE(hlist_unhashed(&blkg->blkcg_node)); | 309 | WARN_ON_ONCE(hlist_unhashed(&blkg->blkcg_node)); |
301 | 310 | ||
311 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | ||
312 | struct blkcg_policy *pol = blkcg_policy[i]; | ||
313 | |||
314 | if (blkg->pd[i] && pol->pd_offline_fn) | ||
315 | pol->pd_offline_fn(blkg); | ||
316 | } | ||
317 | blkg->online = false; | ||
318 | |||
302 | radix_tree_delete(&blkcg->blkg_tree, blkg->q->id); | 319 | radix_tree_delete(&blkcg->blkg_tree, blkg->q->id); |
303 | list_del_init(&blkg->q_node); | 320 | list_del_init(&blkg->q_node); |
304 | hlist_del_init_rcu(&blkg->blkcg_node); | 321 | hlist_del_init_rcu(&blkg->blkcg_node); |
@@ -956,6 +973,8 @@ void blkcg_deactivate_policy(struct request_queue *q, | |||
956 | /* grab blkcg lock too while removing @pd from @blkg */ | 973 | /* grab blkcg lock too while removing @pd from @blkg */ |
957 | spin_lock(&blkg->blkcg->lock); | 974 | spin_lock(&blkg->blkcg->lock); |
958 | 975 | ||
976 | if (pol->pd_offline_fn) | ||
977 | pol->pd_offline_fn(blkg); | ||
959 | if (pol->pd_exit_fn) | 978 | if (pol->pd_exit_fn) |
960 | pol->pd_exit_fn(blkg); | 979 | pol->pd_exit_fn(blkg); |
961 | 980 | ||
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 40f5b9768aac..678e89ed8ecb 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h | |||
@@ -106,12 +106,17 @@ struct blkcg_gq { | |||
106 | /* reference count */ | 106 | /* reference count */ |
107 | int refcnt; | 107 | int refcnt; |
108 | 108 | ||
109 | /* is this blkg online? protected by both blkcg and q locks */ | ||
110 | bool online; | ||
111 | |||
109 | struct blkg_policy_data *pd[BLKCG_MAX_POLS]; | 112 | struct blkg_policy_data *pd[BLKCG_MAX_POLS]; |
110 | 113 | ||
111 | struct rcu_head rcu_head; | 114 | struct rcu_head rcu_head; |
112 | }; | 115 | }; |
113 | 116 | ||
114 | typedef void (blkcg_pol_init_pd_fn)(struct blkcg_gq *blkg); | 117 | typedef void (blkcg_pol_init_pd_fn)(struct blkcg_gq *blkg); |
118 | typedef void (blkcg_pol_online_pd_fn)(struct blkcg_gq *blkg); | ||
119 | typedef void (blkcg_pol_offline_pd_fn)(struct blkcg_gq *blkg); | ||
115 | typedef void (blkcg_pol_exit_pd_fn)(struct blkcg_gq *blkg); | 120 | typedef void (blkcg_pol_exit_pd_fn)(struct blkcg_gq *blkg); |
116 | typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkcg_gq *blkg); | 121 | typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkcg_gq *blkg); |
117 | 122 | ||
@@ -124,6 +129,8 @@ struct blkcg_policy { | |||
124 | 129 | ||
125 | /* operations */ | 130 | /* operations */ |
126 | blkcg_pol_init_pd_fn *pd_init_fn; | 131 | blkcg_pol_init_pd_fn *pd_init_fn; |
132 | blkcg_pol_online_pd_fn *pd_online_fn; | ||
133 | blkcg_pol_offline_pd_fn *pd_offline_fn; | ||
127 | blkcg_pol_exit_pd_fn *pd_exit_fn; | 134 | blkcg_pol_exit_pd_fn *pd_exit_fn; |
128 | blkcg_pol_reset_pd_stats_fn *pd_reset_stats_fn; | 135 | blkcg_pol_reset_pd_stats_fn *pd_reset_stats_fn; |
129 | }; | 136 | }; |