aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2015-08-18 17:55:11 -0400
committerJens Axboe <axboe@fb.com>2015-08-18 18:49:16 -0400
commit001bea73e70efdf48a9e00188cf302f6b6aed2bf (patch)
tree73797e7ac03b5e3e4fd9a3dc90c43f89b1ed57e0
parent3e41871046bfe0ba7d122a1f14f0c1db2dca0256 (diff)
blkcg: replace blkcg_policy->pd_size with ->pd_alloc/free_fn() methods
A blkg (blkcg_gq) represents the relationship between a cgroup and request_queue. Each active policy has a pd (blkg_policy_data) on each blkg. The pd's were allocated by blkcg core and each policy could request to allocate extra space at the end by setting blkcg_policy->pd_size larger than the size of pd. This is a bit unusual but was done this way mostly to simplify error handling and all the existing use cases could be handled this way; however, this is becoming too restrictive now that percpu memory can be allocated without blocking. This introduces two new mandatory blkcg_policy methods - pd_alloc_fn() and pd_free_fn() - which are used to allocate and release pd for a given policy. As pd allocation is now done from policy side, it can simply allocate a larger area which embeds pd at the beginning. This change makes ->pd_size pointless. Removed. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--block/blk-cgroup.c21
-rw-r--r--block/blk-throttle.c13
-rw-r--r--block/cfq-iosched.c13
-rw-r--r--include/linux/blk-cgroup.h18
4 files changed, 44 insertions, 21 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 4defbbabc0ff..d1bc6099bd1e 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -68,7 +68,8 @@ static void blkg_free(struct blkcg_gq *blkg)
68 return; 68 return;
69 69
70 for (i = 0; i < BLKCG_MAX_POLS; i++) 70 for (i = 0; i < BLKCG_MAX_POLS; i++)
71 kfree(blkg->pd[i]); 71 if (blkg->pd[i])
72 blkcg_policy[i]->pd_free_fn(blkg->pd[i]);
72 73
73 if (blkg->blkcg != &blkcg_root) 74 if (blkg->blkcg != &blkcg_root)
74 blk_exit_rl(&blkg->rl); 75 blk_exit_rl(&blkg->rl);
@@ -114,7 +115,7 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,
114 continue; 115 continue;
115 116
116 /* alloc per-policy data and attach it to blkg */ 117 /* alloc per-policy data and attach it to blkg */
117 pd = kzalloc_node(pol->pd_size, gfp_mask, q->node); 118 pd = pol->pd_alloc_fn(gfp_mask, q->node);
118 if (!pd) 119 if (!pd)
119 goto err_free; 120 goto err_free;
120 121
@@ -1057,7 +1058,7 @@ int blkcg_activate_policy(struct request_queue *q,
1057 blk_queue_bypass_start(q); 1058 blk_queue_bypass_start(q);
1058pd_prealloc: 1059pd_prealloc:
1059 if (!pd_prealloc) { 1060 if (!pd_prealloc) {
1060 pd_prealloc = kzalloc_node(pol->pd_size, GFP_KERNEL, q->node); 1061 pd_prealloc = pol->pd_alloc_fn(GFP_KERNEL, q->node);
1061 if (!pd_prealloc) { 1062 if (!pd_prealloc) {
1062 ret = -ENOMEM; 1063 ret = -ENOMEM;
1063 goto out_bypass_end; 1064 goto out_bypass_end;
@@ -1072,7 +1073,7 @@ pd_prealloc:
1072 if (blkg->pd[pol->plid]) 1073 if (blkg->pd[pol->plid])
1073 continue; 1074 continue;
1074 1075
1075 pd = kzalloc_node(pol->pd_size, GFP_NOWAIT, q->node); 1076 pd = pol->pd_alloc_fn(GFP_NOWAIT, q->node);
1076 if (!pd) 1077 if (!pd)
1077 swap(pd, pd_prealloc); 1078 swap(pd, pd_prealloc);
1078 if (!pd) { 1079 if (!pd) {
@@ -1093,7 +1094,8 @@ pd_prealloc:
1093 spin_unlock_irq(q->queue_lock); 1094 spin_unlock_irq(q->queue_lock);
1094out_bypass_end: 1095out_bypass_end:
1095 blk_queue_bypass_end(q); 1096 blk_queue_bypass_end(q);
1096 kfree(pd_prealloc); 1097 if (pd_prealloc)
1098 pol->pd_free_fn(pd_prealloc);
1097 return ret; 1099 return ret;
1098} 1100}
1099EXPORT_SYMBOL_GPL(blkcg_activate_policy); 1101EXPORT_SYMBOL_GPL(blkcg_activate_policy);
@@ -1128,8 +1130,10 @@ void blkcg_deactivate_policy(struct request_queue *q,
1128 if (pol->pd_exit_fn) 1130 if (pol->pd_exit_fn)
1129 pol->pd_exit_fn(blkg); 1131 pol->pd_exit_fn(blkg);
1130 1132
1131 kfree(blkg->pd[pol->plid]); 1133 if (blkg->pd[pol->plid]) {
1132 blkg->pd[pol->plid] = NULL; 1134 pol->pd_free_fn(blkg->pd[pol->plid]);
1135 blkg->pd[pol->plid] = NULL;
1136 }
1133 1137
1134 spin_unlock(&blkg->blkcg->lock); 1138 spin_unlock(&blkg->blkcg->lock);
1135 } 1139 }
@@ -1151,9 +1155,6 @@ int blkcg_policy_register(struct blkcg_policy *pol)
1151 struct blkcg *blkcg; 1155 struct blkcg *blkcg;
1152 int i, ret; 1156 int i, ret;
1153 1157
1154 if (WARN_ON(pol->pd_size < sizeof(struct blkg_policy_data)))
1155 return -EINVAL;
1156
1157 mutex_lock(&blkcg_pol_register_mutex); 1158 mutex_lock(&blkcg_pol_register_mutex);
1158 mutex_lock(&blkcg_pol_mutex); 1159 mutex_lock(&blkcg_pol_mutex);
1159 1160
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index b23193518ac7..f1dd691c5359 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -403,6 +403,11 @@ static void throtl_service_queue_exit(struct throtl_service_queue *sq)
403 del_timer_sync(&sq->pending_timer); 403 del_timer_sync(&sq->pending_timer);
404} 404}
405 405
406static struct blkg_policy_data *throtl_pd_alloc(gfp_t gfp, int node)
407{
408 return kzalloc_node(sizeof(struct throtl_grp), gfp, node);
409}
410
406static void throtl_pd_init(struct blkcg_gq *blkg) 411static void throtl_pd_init(struct blkcg_gq *blkg)
407{ 412{
408 struct throtl_grp *tg = blkg_to_tg(blkg); 413 struct throtl_grp *tg = blkg_to_tg(blkg);
@@ -493,6 +498,11 @@ static void throtl_pd_exit(struct blkcg_gq *blkg)
493 throtl_service_queue_exit(&tg->service_queue); 498 throtl_service_queue_exit(&tg->service_queue);
494} 499}
495 500
501static void throtl_pd_free(struct blkg_policy_data *pd)
502{
503 kfree(pd);
504}
505
496static void throtl_pd_reset_stats(struct blkcg_gq *blkg) 506static void throtl_pd_reset_stats(struct blkcg_gq *blkg)
497{ 507{
498 struct throtl_grp *tg = blkg_to_tg(blkg); 508 struct throtl_grp *tg = blkg_to_tg(blkg);
@@ -1468,12 +1478,13 @@ static void throtl_shutdown_wq(struct request_queue *q)
1468} 1478}
1469 1479
1470static struct blkcg_policy blkcg_policy_throtl = { 1480static struct blkcg_policy blkcg_policy_throtl = {
1471 .pd_size = sizeof(struct throtl_grp),
1472 .cftypes = throtl_files, 1481 .cftypes = throtl_files,
1473 1482
1483 .pd_alloc_fn = throtl_pd_alloc,
1474 .pd_init_fn = throtl_pd_init, 1484 .pd_init_fn = throtl_pd_init,
1475 .pd_online_fn = throtl_pd_online, 1485 .pd_online_fn = throtl_pd_online,
1476 .pd_exit_fn = throtl_pd_exit, 1486 .pd_exit_fn = throtl_pd_exit,
1487 .pd_free_fn = throtl_pd_free,
1477 .pd_reset_stats_fn = throtl_pd_reset_stats, 1488 .pd_reset_stats_fn = throtl_pd_reset_stats,
1478}; 1489};
1479 1490
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 9c9ec7cc9f99..69ce2883099e 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1582,6 +1582,11 @@ static void cfq_cpd_init(const struct blkcg *blkcg)
1582 } 1582 }
1583} 1583}
1584 1584
1585static struct blkg_policy_data *cfq_pd_alloc(gfp_t gfp, int node)
1586{
1587 return kzalloc_node(sizeof(struct cfq_group), gfp, node);
1588}
1589
1585static void cfq_pd_init(struct blkcg_gq *blkg) 1590static void cfq_pd_init(struct blkcg_gq *blkg)
1586{ 1591{
1587 struct cfq_group *cfqg = blkg_to_cfqg(blkg); 1592 struct cfq_group *cfqg = blkg_to_cfqg(blkg);
@@ -1618,6 +1623,11 @@ static void cfq_pd_offline(struct blkcg_gq *blkg)
1618 cfqg_stats_xfer_dead(cfqg); 1623 cfqg_stats_xfer_dead(cfqg);
1619} 1624}
1620 1625
1626static void cfq_pd_free(struct blkg_policy_data *pd)
1627{
1628 return kfree(pd);
1629}
1630
1621/* offset delta from cfqg->stats to cfqg->dead_stats */ 1631/* offset delta from cfqg->stats to cfqg->dead_stats */
1622static const int dead_stats_off_delta = offsetof(struct cfq_group, dead_stats) - 1632static const int dead_stats_off_delta = offsetof(struct cfq_group, dead_stats) -
1623 offsetof(struct cfq_group, stats); 1633 offsetof(struct cfq_group, stats);
@@ -4633,13 +4643,14 @@ static struct elevator_type iosched_cfq = {
4633 4643
4634#ifdef CONFIG_CFQ_GROUP_IOSCHED 4644#ifdef CONFIG_CFQ_GROUP_IOSCHED
4635static struct blkcg_policy blkcg_policy_cfq = { 4645static struct blkcg_policy blkcg_policy_cfq = {
4636 .pd_size = sizeof(struct cfq_group),
4637 .cpd_size = sizeof(struct cfq_group_data), 4646 .cpd_size = sizeof(struct cfq_group_data),
4638 .cftypes = cfq_blkcg_files, 4647 .cftypes = cfq_blkcg_files,
4639 4648
4640 .cpd_init_fn = cfq_cpd_init, 4649 .cpd_init_fn = cfq_cpd_init,
4650 .pd_alloc_fn = cfq_pd_alloc,
4641 .pd_init_fn = cfq_pd_init, 4651 .pd_init_fn = cfq_pd_init,
4642 .pd_offline_fn = cfq_pd_offline, 4652 .pd_offline_fn = cfq_pd_offline,
4653 .pd_free_fn = cfq_pd_free,
4643 .pd_reset_stats_fn = cfq_pd_reset_stats, 4654 .pd_reset_stats_fn = cfq_pd_reset_stats,
4644}; 4655};
4645#endif 4656#endif
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
index db822880242a..bd173ea360ce 100644
--- a/include/linux/blk-cgroup.h
+++ b/include/linux/blk-cgroup.h
@@ -68,13 +68,11 @@ struct blkg_rwstat {
68 * request_queue (q). This is used by blkcg policies which need to track 68 * request_queue (q). This is used by blkcg policies which need to track
69 * information per blkcg - q pair. 69 * information per blkcg - q pair.
70 * 70 *
71 * There can be multiple active blkcg policies and each has its private 71 * There can be multiple active blkcg policies and each blkg:policy pair is
72 * data on each blkg, the size of which is determined by 72 * represented by a blkg_policy_data which is allocated and freed by each
73 * blkcg_policy->pd_size. blkcg core allocates and frees such areas 73 * policy's pd_alloc/free_fn() methods. A policy can allocate private data
74 * together with blkg and invokes pd_init/exit_fn() methods. 74 * area by allocating larger data structure which embeds blkg_policy_data
75 * 75 * at the beginning.
76 * Such private data must embed struct blkg_policy_data (pd) at the
77 * beginning and pd_size can't be smaller than pd.
78 */ 76 */
79struct blkg_policy_data { 77struct blkg_policy_data {
80 /* the blkg and policy id this per-policy data belongs to */ 78 /* the blkg and policy id this per-policy data belongs to */
@@ -126,16 +124,16 @@ struct blkcg_gq {
126}; 124};
127 125
128typedef void (blkcg_pol_init_cpd_fn)(const struct blkcg *blkcg); 126typedef void (blkcg_pol_init_cpd_fn)(const struct blkcg *blkcg);
127typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, int node);
129typedef void (blkcg_pol_init_pd_fn)(struct blkcg_gq *blkg); 128typedef void (blkcg_pol_init_pd_fn)(struct blkcg_gq *blkg);
130typedef void (blkcg_pol_online_pd_fn)(struct blkcg_gq *blkg); 129typedef void (blkcg_pol_online_pd_fn)(struct blkcg_gq *blkg);
131typedef void (blkcg_pol_offline_pd_fn)(struct blkcg_gq *blkg); 130typedef void (blkcg_pol_offline_pd_fn)(struct blkcg_gq *blkg);
132typedef void (blkcg_pol_exit_pd_fn)(struct blkcg_gq *blkg); 131typedef void (blkcg_pol_exit_pd_fn)(struct blkcg_gq *blkg);
132typedef void (blkcg_pol_free_pd_fn)(struct blkg_policy_data *pd);
133typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkcg_gq *blkg); 133typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkcg_gq *blkg);
134 134
135struct blkcg_policy { 135struct blkcg_policy {
136 int plid; 136 int plid;
137 /* policy specific private data size */
138 size_t pd_size;
139 /* policy specific per-blkcg data size */ 137 /* policy specific per-blkcg data size */
140 size_t cpd_size; 138 size_t cpd_size;
141 /* cgroup files for the policy */ 139 /* cgroup files for the policy */
@@ -143,10 +141,12 @@ struct blkcg_policy {
143 141
144 /* operations */ 142 /* operations */
145 blkcg_pol_init_cpd_fn *cpd_init_fn; 143 blkcg_pol_init_cpd_fn *cpd_init_fn;
144 blkcg_pol_alloc_pd_fn *pd_alloc_fn;
146 blkcg_pol_init_pd_fn *pd_init_fn; 145 blkcg_pol_init_pd_fn *pd_init_fn;
147 blkcg_pol_online_pd_fn *pd_online_fn; 146 blkcg_pol_online_pd_fn *pd_online_fn;
148 blkcg_pol_offline_pd_fn *pd_offline_fn; 147 blkcg_pol_offline_pd_fn *pd_offline_fn;
149 blkcg_pol_exit_pd_fn *pd_exit_fn; 148 blkcg_pol_exit_pd_fn *pd_exit_fn;
149 blkcg_pol_free_pd_fn *pd_free_fn;
150 blkcg_pol_reset_pd_stats_fn *pd_reset_stats_fn; 150 blkcg_pol_reset_pd_stats_fn *pd_reset_stats_fn;
151}; 151};
152 152