Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 309197
b: refs/heads/master
c: 72e06c2
h: refs/heads/master
i:
  309195: 64f0a47
v: v3
  • Loading branch information
Tejun Heo authored and Jens Axboe committed Mar 6, 2012
1 parent 3e67004 commit b098035
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6ecf23afab13c39d3bb0e2d826d0984b0dd53733
refs/heads/master: 72e06c255181537d0b3e1f657a9ed81655d745b1
34 changes: 33 additions & 1 deletion trunk/block/blk-cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
#include <linux/err.h>
#include <linux/blkdev.h>
#include <linux/slab.h>
#include "blk-cgroup.h"
#include <linux/genhd.h>
#include <linux/delay.h>
#include "blk-cgroup.h"

#define MAX_KEY_LEN 100

Expand Down Expand Up @@ -546,6 +547,37 @@ struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key)
}
EXPORT_SYMBOL_GPL(blkiocg_lookup_group);

void blkg_destroy_all(struct request_queue *q)
{
struct blkio_policy_type *pol;

while (true) {
bool done = true;

spin_lock(&blkio_list_lock);
spin_lock_irq(q->queue_lock);

/*
* clear_queue_fn() might return with non-empty group list
* if it raced cgroup removal and lost. cgroup removal is
* guaranteed to make forward progress and retrying after a
* while is enough. This ugliness is scheduled to be
* removed after locking update.
*/
list_for_each_entry(pol, &blkio_list, list)
if (!pol->ops.blkio_clear_queue_fn(q))
done = false;

spin_unlock_irq(q->queue_lock);
spin_unlock(&blkio_list_lock);

if (done)
break;

msleep(10); /* just some random duration I like */
}
}

static void blkio_reset_stats_cpu(struct blkio_group *blkg)
{
struct blkio_group_stats_cpu *stats_cpu;
Expand Down
5 changes: 4 additions & 1 deletion trunk/block/blk-cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ extern unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg,
dev_t dev);

typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg);

typedef bool (blkio_clear_queue_fn)(struct request_queue *q);
typedef void (blkio_update_group_weight_fn) (void *key,
struct blkio_group *blkg, unsigned int weight);
typedef void (blkio_update_group_read_bps_fn) (void * key,
Expand All @@ -217,6 +217,7 @@ typedef void (blkio_update_group_write_iops_fn) (void *key,

struct blkio_policy_ops {
blkio_unlink_group_fn *blkio_unlink_group_fn;
blkio_clear_queue_fn *blkio_clear_queue_fn;
blkio_update_group_weight_fn *blkio_update_group_weight_fn;
blkio_update_group_read_bps_fn *blkio_update_group_read_bps_fn;
blkio_update_group_write_bps_fn *blkio_update_group_write_bps_fn;
Expand All @@ -233,6 +234,7 @@ struct blkio_policy_type {
/* Blkio controller policy registration */
extern void blkio_policy_register(struct blkio_policy_type *);
extern void blkio_policy_unregister(struct blkio_policy_type *);
extern void blkg_destroy_all(struct request_queue *q);

static inline char *blkg_path(struct blkio_group *blkg)
{
Expand All @@ -249,6 +251,7 @@ struct blkio_policy_type {

static inline void blkio_policy_register(struct blkio_policy_type *blkiop) { }
static inline void blkio_policy_unregister(struct blkio_policy_type *blkiop) { }
static inline void blkg_destroy_all(struct request_queue *q) { }

static inline char *blkg_path(struct blkio_group *blkg) { return NULL; }

Expand Down
27 changes: 25 additions & 2 deletions trunk/block/blk-throttle.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,20 +989,28 @@ throtl_destroy_tg(struct throtl_data *td, struct throtl_grp *tg)
td->nr_undestroyed_grps--;
}

static void throtl_release_tgs(struct throtl_data *td)
static bool throtl_release_tgs(struct throtl_data *td, bool release_root)
{
struct hlist_node *pos, *n;
struct throtl_grp *tg;
bool empty = true;

hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
/* skip root? */
if (!release_root && tg == td->root_tg)
continue;

/*
* If cgroup removal path got to blk_group first and removed
* it from cgroup list, then it will take care of destroying
* cfqg also.
*/
if (!blkiocg_del_blkio_group(&tg->blkg))
throtl_destroy_tg(td, tg);
else
empty = false;
}
return empty;
}

/*
Expand All @@ -1029,6 +1037,20 @@ void throtl_unlink_blkio_group(void *key, struct blkio_group *blkg)
spin_unlock_irqrestore(td->queue->queue_lock, flags);
}

static bool throtl_clear_queue(struct request_queue *q)
{
lockdep_assert_held(q->queue_lock);

/*
* Clear tgs but leave the root one alone. This is necessary
* because root_tg is expected to be persistent and safe because
* blk-throtl can never be disabled while @q is alive. This is a
* kludge to prepare for unified blkg. This whole function will be
* removed soon.
*/
return throtl_release_tgs(q->td, false);
}

static void throtl_update_blkio_group_common(struct throtl_data *td,
struct throtl_grp *tg)
{
Expand Down Expand Up @@ -1097,6 +1119,7 @@ static void throtl_shutdown_wq(struct request_queue *q)
static struct blkio_policy_type blkio_policy_throtl = {
.ops = {
.blkio_unlink_group_fn = throtl_unlink_blkio_group,
.blkio_clear_queue_fn = throtl_clear_queue,
.blkio_update_group_read_bps_fn =
throtl_update_blkio_group_read_bps,
.blkio_update_group_write_bps_fn =
Expand Down Expand Up @@ -1282,7 +1305,7 @@ void blk_throtl_exit(struct request_queue *q)
throtl_shutdown_wq(q);

spin_lock_irq(q->queue_lock);
throtl_release_tgs(td);
throtl_release_tgs(td, true);

/* If there are other groups */
if (td->nr_undestroyed_grps > 0)
Expand Down
20 changes: 19 additions & 1 deletion trunk/block/cfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -1225,10 +1225,11 @@ static void cfq_destroy_cfqg(struct cfq_data *cfqd, struct cfq_group *cfqg)
cfq_put_cfqg(cfqg);
}

static void cfq_release_cfq_groups(struct cfq_data *cfqd)
static bool cfq_release_cfq_groups(struct cfq_data *cfqd)
{
struct hlist_node *pos, *n;
struct cfq_group *cfqg;
bool empty = true;

hlist_for_each_entry_safe(cfqg, pos, n, &cfqd->cfqg_list, cfqd_node) {
/*
Expand All @@ -1238,7 +1239,10 @@ static void cfq_release_cfq_groups(struct cfq_data *cfqd)
*/
if (!cfq_blkiocg_del_blkio_group(&cfqg->blkg))
cfq_destroy_cfqg(cfqd, cfqg);
else
empty = false;
}
return empty;
}

/*
Expand All @@ -1265,6 +1269,19 @@ static void cfq_unlink_blkio_group(void *key, struct blkio_group *blkg)
spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
}

static struct elevator_type iosched_cfq;

static bool cfq_clear_queue(struct request_queue *q)
{
lockdep_assert_held(q->queue_lock);

/* shoot down blkgs iff the current elevator is cfq */
if (!q->elevator || q->elevator->type != &iosched_cfq)
return true;

return cfq_release_cfq_groups(q->elevator->elevator_data);
}

#else /* GROUP_IOSCHED */
static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd)
{
Expand Down Expand Up @@ -3875,6 +3892,7 @@ static struct elevator_type iosched_cfq = {
static struct blkio_policy_type blkio_policy_cfq = {
.ops = {
.blkio_unlink_group_fn = cfq_unlink_blkio_group,
.blkio_clear_queue_fn = cfq_clear_queue,
.blkio_update_group_weight_fn = cfq_update_blkio_group_weight,
},
.plid = BLKIO_POLICY_PROP,
Expand Down
3 changes: 3 additions & 0 deletions trunk/block/elevator.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <trace/events/block.h>

#include "blk.h"
#include "blk-cgroup.h"

static DEFINE_SPINLOCK(elv_list_lock);
static LIST_HEAD(elv_list);
Expand Down Expand Up @@ -894,6 +895,8 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
ioc_clear_queue(q);
spin_unlock_irq(q->queue_lock);

blkg_destroy_all(q);

/* allocate, init and register new elevator */
err = -ENOMEM;
q->elevator = elevator_alloc(q, new_e);
Expand Down

0 comments on commit b098035

Please sign in to comment.