diff options
author | Tejun Heo <tj@kernel.org> | 2012-03-05 16:15:00 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-03-06 15:27:22 -0500 |
commit | 72e06c255181537d0b3e1f657a9ed81655d745b1 (patch) | |
tree | eb656df2ad23a7709b4e9fe58f1dabdc32be9ae9 /block/cfq-iosched.c | |
parent | 6ecf23afab13c39d3bb0e2d826d0984b0dd53733 (diff) |
blkcg: shoot down blkio_groups on elevator switch
Elevator switch may involve changes to blkcg policies. Implement
shoot down of blkio_groups.
Combined with the previous bypass updates, the end goal is updating
blkcg core such that it can ensure that blkcg's being affected become
quiescent and don't have any per-blkg data hanging around before
commencing any policy updates. Until queues are made aware of the
policies that applies to them, as an interim step, all per-policy blkg
data will be shot down.
* blk-throtl doesn't need this change as it can't be disabled for a
live queue; however, update it anyway as the scheduled blkg
unification requires this behavior change. This means that
blk-throtl configuration will be unnecessarily lost over elevator
switch. This oddity will be removed after blkcg learns to associate
individual policies with request_queues.
* blk-throtl dosen't shoot down root_tg. This is to ease transition.
Unified blkg will always have persistent root group and not shooting
down root_tg for now eases transition to that point by avoiding
having to update td->root_tg and is safe as blk-throtl can never be
disabled
-v2: Vivek pointed out that group list is not guaranteed to be empty
on return from clear function if it raced cgroup removal and
lost. Fix it by waiting a bit and retrying. This kludge will
soon be removed once locking is updated such that blkg is never
in limbo state between blkcg and request_queue locks.
blk-throtl no longer shoots down root_tg to avoid breaking
td->root_tg.
Also, Nest queue_lock inside blkio_list_lock not the other way
around to avoid introduce possible deadlock via blkcg lock.
-v3: blkcg_clear_queue() repositioned and renamed to
blkg_destroy_all() to increase consistency with later changes.
cfq_clear_queue() updated to check q->elevator before
dereferencing it to avoid NULL dereference on not fully
initialized queues (used by later change).
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 72680a6715fc..61693d3404d0 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -1225,10 +1225,11 @@ static void cfq_destroy_cfqg(struct cfq_data *cfqd, struct cfq_group *cfqg) | |||
1225 | cfq_put_cfqg(cfqg); | 1225 | cfq_put_cfqg(cfqg); |
1226 | } | 1226 | } |
1227 | 1227 | ||
1228 | static void cfq_release_cfq_groups(struct cfq_data *cfqd) | 1228 | static bool cfq_release_cfq_groups(struct cfq_data *cfqd) |
1229 | { | 1229 | { |
1230 | struct hlist_node *pos, *n; | 1230 | struct hlist_node *pos, *n; |
1231 | struct cfq_group *cfqg; | 1231 | struct cfq_group *cfqg; |
1232 | bool empty = true; | ||
1232 | 1233 | ||
1233 | hlist_for_each_entry_safe(cfqg, pos, n, &cfqd->cfqg_list, cfqd_node) { | 1234 | hlist_for_each_entry_safe(cfqg, pos, n, &cfqd->cfqg_list, cfqd_node) { |
1234 | /* | 1235 | /* |
@@ -1238,7 +1239,10 @@ static void cfq_release_cfq_groups(struct cfq_data *cfqd) | |||
1238 | */ | 1239 | */ |
1239 | if (!cfq_blkiocg_del_blkio_group(&cfqg->blkg)) | 1240 | if (!cfq_blkiocg_del_blkio_group(&cfqg->blkg)) |
1240 | cfq_destroy_cfqg(cfqd, cfqg); | 1241 | cfq_destroy_cfqg(cfqd, cfqg); |
1242 | else | ||
1243 | empty = false; | ||
1241 | } | 1244 | } |
1245 | return empty; | ||
1242 | } | 1246 | } |
1243 | 1247 | ||
1244 | /* | 1248 | /* |
@@ -1265,6 +1269,19 @@ static void cfq_unlink_blkio_group(void *key, struct blkio_group *blkg) | |||
1265 | spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); | 1269 | spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); |
1266 | } | 1270 | } |
1267 | 1271 | ||
1272 | static struct elevator_type iosched_cfq; | ||
1273 | |||
1274 | static bool cfq_clear_queue(struct request_queue *q) | ||
1275 | { | ||
1276 | lockdep_assert_held(q->queue_lock); | ||
1277 | |||
1278 | /* shoot down blkgs iff the current elevator is cfq */ | ||
1279 | if (!q->elevator || q->elevator->type != &iosched_cfq) | ||
1280 | return true; | ||
1281 | |||
1282 | return cfq_release_cfq_groups(q->elevator->elevator_data); | ||
1283 | } | ||
1284 | |||
1268 | #else /* GROUP_IOSCHED */ | 1285 | #else /* GROUP_IOSCHED */ |
1269 | static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd) | 1286 | static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd) |
1270 | { | 1287 | { |
@@ -3875,6 +3892,7 @@ static struct elevator_type iosched_cfq = { | |||
3875 | static struct blkio_policy_type blkio_policy_cfq = { | 3892 | static struct blkio_policy_type blkio_policy_cfq = { |
3876 | .ops = { | 3893 | .ops = { |
3877 | .blkio_unlink_group_fn = cfq_unlink_blkio_group, | 3894 | .blkio_unlink_group_fn = cfq_unlink_blkio_group, |
3895 | .blkio_clear_queue_fn = cfq_clear_queue, | ||
3878 | .blkio_update_group_weight_fn = cfq_update_blkio_group_weight, | 3896 | .blkio_update_group_weight_fn = cfq_update_blkio_group_weight, |
3879 | }, | 3897 | }, |
3880 | .plid = BLKIO_POLICY_PROP, | 3898 | .plid = BLKIO_POLICY_PROP, |