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/blk-cgroup.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/blk-cgroup.c')
-rw-r--r-- | block/blk-cgroup.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 970a717a056f..159aef59589f 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -17,8 +17,9 @@ | |||
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/blkdev.h> | 18 | #include <linux/blkdev.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include "blk-cgroup.h" | ||
21 | #include <linux/genhd.h> | 20 | #include <linux/genhd.h> |
21 | #include <linux/delay.h> | ||
22 | #include "blk-cgroup.h" | ||
22 | 23 | ||
23 | #define MAX_KEY_LEN 100 | 24 | #define MAX_KEY_LEN 100 |
24 | 25 | ||
@@ -546,6 +547,37 @@ struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key) | |||
546 | } | 547 | } |
547 | EXPORT_SYMBOL_GPL(blkiocg_lookup_group); | 548 | EXPORT_SYMBOL_GPL(blkiocg_lookup_group); |
548 | 549 | ||
550 | void blkg_destroy_all(struct request_queue *q) | ||
551 | { | ||
552 | struct blkio_policy_type *pol; | ||
553 | |||
554 | while (true) { | ||
555 | bool done = true; | ||
556 | |||
557 | spin_lock(&blkio_list_lock); | ||
558 | spin_lock_irq(q->queue_lock); | ||
559 | |||
560 | /* | ||
561 | * clear_queue_fn() might return with non-empty group list | ||
562 | * if it raced cgroup removal and lost. cgroup removal is | ||
563 | * guaranteed to make forward progress and retrying after a | ||
564 | * while is enough. This ugliness is scheduled to be | ||
565 | * removed after locking update. | ||
566 | */ | ||
567 | list_for_each_entry(pol, &blkio_list, list) | ||
568 | if (!pol->ops.blkio_clear_queue_fn(q)) | ||
569 | done = false; | ||
570 | |||
571 | spin_unlock_irq(q->queue_lock); | ||
572 | spin_unlock(&blkio_list_lock); | ||
573 | |||
574 | if (done) | ||
575 | break; | ||
576 | |||
577 | msleep(10); /* just some random duration I like */ | ||
578 | } | ||
579 | } | ||
580 | |||
549 | static void blkio_reset_stats_cpu(struct blkio_group *blkg) | 581 | static void blkio_reset_stats_cpu(struct blkio_group *blkg) |
550 | { | 582 | { |
551 | struct blkio_group_stats_cpu *stats_cpu; | 583 | struct blkio_group_stats_cpu *stats_cpu; |