diff options
author | Tejun Heo <tj@kernel.org> | 2015-08-18 17:55:11 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-08-18 18:49:16 -0400 |
commit | 001bea73e70efdf48a9e00188cf302f6b6aed2bf (patch) | |
tree | 73797e7ac03b5e3e4fd9a3dc90c43f89b1ed57e0 | |
parent | 3e41871046bfe0ba7d122a1f14f0c1db2dca0256 (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.c | 21 | ||||
-rw-r--r-- | block/blk-throttle.c | 13 | ||||
-rw-r--r-- | block/cfq-iosched.c | 13 | ||||
-rw-r--r-- | include/linux/blk-cgroup.h | 18 |
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); |
1058 | pd_prealloc: | 1059 | pd_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); |
1094 | out_bypass_end: | 1095 | out_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 | } |
1099 | EXPORT_SYMBOL_GPL(blkcg_activate_policy); | 1101 | EXPORT_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 | ||
406 | static 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 | |||
406 | static void throtl_pd_init(struct blkcg_gq *blkg) | 411 | static 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 | ||
501 | static void throtl_pd_free(struct blkg_policy_data *pd) | ||
502 | { | ||
503 | kfree(pd); | ||
504 | } | ||
505 | |||
496 | static void throtl_pd_reset_stats(struct blkcg_gq *blkg) | 506 | static 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 | ||
1470 | static struct blkcg_policy blkcg_policy_throtl = { | 1480 | static 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 | ||
1585 | static 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 | |||
1585 | static void cfq_pd_init(struct blkcg_gq *blkg) | 1590 | static 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 | ||
1626 | static 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 */ |
1622 | static const int dead_stats_off_delta = offsetof(struct cfq_group, dead_stats) - | 1632 | static 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 |
4635 | static struct blkcg_policy blkcg_policy_cfq = { | 4645 | static 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 | */ |
79 | struct blkg_policy_data { | 77 | struct 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 | ||
128 | typedef void (blkcg_pol_init_cpd_fn)(const struct blkcg *blkcg); | 126 | typedef void (blkcg_pol_init_cpd_fn)(const struct blkcg *blkcg); |
127 | typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, int node); | ||
129 | typedef void (blkcg_pol_init_pd_fn)(struct blkcg_gq *blkg); | 128 | typedef void (blkcg_pol_init_pd_fn)(struct blkcg_gq *blkg); |
130 | typedef void (blkcg_pol_online_pd_fn)(struct blkcg_gq *blkg); | 129 | typedef void (blkcg_pol_online_pd_fn)(struct blkcg_gq *blkg); |
131 | typedef void (blkcg_pol_offline_pd_fn)(struct blkcg_gq *blkg); | 130 | typedef void (blkcg_pol_offline_pd_fn)(struct blkcg_gq *blkg); |
132 | typedef void (blkcg_pol_exit_pd_fn)(struct blkcg_gq *blkg); | 131 | typedef void (blkcg_pol_exit_pd_fn)(struct blkcg_gq *blkg); |
132 | typedef void (blkcg_pol_free_pd_fn)(struct blkg_policy_data *pd); | ||
133 | typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkcg_gq *blkg); | 133 | typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkcg_gq *blkg); |
134 | 134 | ||
135 | struct blkcg_policy { | 135 | struct 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 | ||