diff options
author | Tejun Heo <tj@kernel.org> | 2015-08-18 17:55:09 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-08-18 18:49:16 -0400 |
commit | 4c55f4f9ad3001ac1fefdd8d8ca7641d18558e23 (patch) | |
tree | 66be4a0f4881ba200b7e31e9f0efac8912ab0f21 /block | |
parent | bc915e61cde25d0b429f536cec9e83039bf23504 (diff) |
blkcg: restructure blkg_policy_data allocation in blkcg_activate_policy()
When a policy gets activated, it needs to allocate and install its
policy data on all existing blkg's (blkcg_gq's). Because blkg
iteration is protected by a spinlock, it currently counts the total
number of blkg's in the system, allocates the matching number of
policy data on a list and installs them during a single iteration.
This can be simplified by using speculative GFP_NOWAIT allocations
while iterating and falling back to a preallocated policy data on
failure. If the preallocated one has already been consumed, it
releases the lock, preallocate with GFP_KERNEL and then restarts the
iteration. This can be a bit more expensive than before but policy
activation is a very cold path and shouldn't matter.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-cgroup.c | 55 |
1 files changed, 21 insertions, 34 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index f91a4e09e0c9..9e9b0df339ee 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -1047,65 +1047,52 @@ EXPORT_SYMBOL_GPL(blkio_cgrp_subsys); | |||
1047 | int blkcg_activate_policy(struct request_queue *q, | 1047 | int blkcg_activate_policy(struct request_queue *q, |
1048 | const struct blkcg_policy *pol) | 1048 | const struct blkcg_policy *pol) |
1049 | { | 1049 | { |
1050 | LIST_HEAD(pds); | 1050 | struct blkg_policy_data *pd_prealloc = NULL; |
1051 | struct blkcg_gq *blkg; | 1051 | struct blkcg_gq *blkg; |
1052 | struct blkg_policy_data *pd, *nd; | 1052 | int ret; |
1053 | int cnt = 0, ret; | ||
1054 | 1053 | ||
1055 | if (blkcg_policy_enabled(q, pol)) | 1054 | if (blkcg_policy_enabled(q, pol)) |
1056 | return 0; | 1055 | return 0; |
1057 | 1056 | ||
1058 | /* count and allocate policy_data for all existing blkgs */ | ||
1059 | blk_queue_bypass_start(q); | 1057 | blk_queue_bypass_start(q); |
1060 | spin_lock_irq(q->queue_lock); | 1058 | pd_prealloc: |
1061 | list_for_each_entry(blkg, &q->blkg_list, q_node) | 1059 | if (!pd_prealloc) { |
1062 | cnt++; | 1060 | pd_prealloc = kzalloc_node(pol->pd_size, GFP_KERNEL, q->node); |
1063 | spin_unlock_irq(q->queue_lock); | 1061 | if (!pd_prealloc) { |
1064 | |||
1065 | /* allocate per-blkg policy data for all existing blkgs */ | ||
1066 | while (cnt--) { | ||
1067 | pd = kzalloc_node(pol->pd_size, GFP_KERNEL, q->node); | ||
1068 | if (!pd) { | ||
1069 | ret = -ENOMEM; | 1062 | ret = -ENOMEM; |
1070 | goto out_free; | 1063 | goto out_bypass_end; |
1071 | } | 1064 | } |
1072 | list_add_tail(&pd->alloc_node, &pds); | ||
1073 | } | 1065 | } |
1074 | 1066 | ||
1075 | /* | ||
1076 | * Install the allocated pds and cpds. With @q bypassing, no new blkg | ||
1077 | * should have been created while the queue lock was dropped. | ||
1078 | */ | ||
1079 | spin_lock_irq(q->queue_lock); | 1067 | spin_lock_irq(q->queue_lock); |
1080 | 1068 | ||
1081 | list_for_each_entry(blkg, &q->blkg_list, q_node) { | 1069 | list_for_each_entry(blkg, &q->blkg_list, q_node) { |
1082 | if (WARN_ON(list_empty(&pds))) { | 1070 | struct blkg_policy_data *pd; |
1083 | /* umm... this shouldn't happen, just abort */ | ||
1084 | ret = -ENOMEM; | ||
1085 | goto out_unlock; | ||
1086 | } | ||
1087 | pd = list_first_entry(&pds, struct blkg_policy_data, alloc_node); | ||
1088 | list_del_init(&pd->alloc_node); | ||
1089 | 1071 | ||
1090 | /* grab blkcg lock too while installing @pd on @blkg */ | 1072 | if (blkg->pd[pol->plid]) |
1091 | spin_lock(&blkg->blkcg->lock); | 1073 | continue; |
1074 | |||
1075 | pd = kzalloc_node(pol->pd_size, GFP_NOWAIT, q->node); | ||
1076 | if (!pd) | ||
1077 | swap(pd, pd_prealloc); | ||
1078 | if (!pd) { | ||
1079 | spin_unlock_irq(q->queue_lock); | ||
1080 | goto pd_prealloc; | ||
1081 | } | ||
1092 | 1082 | ||
1093 | blkg->pd[pol->plid] = pd; | 1083 | blkg->pd[pol->plid] = pd; |
1094 | pd->blkg = blkg; | 1084 | pd->blkg = blkg; |
1095 | pd->plid = pol->plid; | 1085 | pd->plid = pol->plid; |
1096 | pol->pd_init_fn(blkg); | 1086 | pol->pd_init_fn(blkg); |
1097 | |||
1098 | spin_unlock(&blkg->blkcg->lock); | ||
1099 | } | 1087 | } |
1100 | 1088 | ||
1101 | __set_bit(pol->plid, q->blkcg_pols); | 1089 | __set_bit(pol->plid, q->blkcg_pols); |
1102 | ret = 0; | 1090 | ret = 0; |
1103 | out_unlock: | 1091 | |
1104 | spin_unlock_irq(q->queue_lock); | 1092 | spin_unlock_irq(q->queue_lock); |
1105 | out_free: | 1093 | out_bypass_end: |
1106 | blk_queue_bypass_end(q); | 1094 | blk_queue_bypass_end(q); |
1107 | list_for_each_entry_safe(pd, nd, &pds, alloc_node) | 1095 | kfree(pd_prealloc); |
1108 | kfree(pd); | ||
1109 | return ret; | 1096 | return ret; |
1110 | } | 1097 | } |
1111 | EXPORT_SYMBOL_GPL(blkcg_activate_policy); | 1098 | EXPORT_SYMBOL_GPL(blkcg_activate_policy); |