aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-01-09 11:05:12 -0500
committerTejun Heo <tj@kernel.org>2013-01-09 11:05:12 -0500
commitf427d909648aa592c9588d0f66b5b457752a0cd1 (patch)
treed6f91a6d46a1302f0cca6137851f0806364b7965 /block
parentb276a876a014c5fa58a16f247c0933f6c42112e3 (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.c21
-rw-r--r--block/blk-cgroup.h7
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);
291static void blkg_destroy(struct blkcg_gq *blkg) 299static 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
114typedef void (blkcg_pol_init_pd_fn)(struct blkcg_gq *blkg); 117typedef void (blkcg_pol_init_pd_fn)(struct blkcg_gq *blkg);
118typedef void (blkcg_pol_online_pd_fn)(struct blkcg_gq *blkg);
119typedef void (blkcg_pol_offline_pd_fn)(struct blkcg_gq *blkg);
115typedef void (blkcg_pol_exit_pd_fn)(struct blkcg_gq *blkg); 120typedef void (blkcg_pol_exit_pd_fn)(struct blkcg_gq *blkg);
116typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkcg_gq *blkg); 121typedef 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};