Commit 7a4dd281 authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

blkcg: kill the mind-bending blkg->dev

blkg->dev is dev_t recording the device number of the block device for
the associated request_queue.  It is used to identify the associated
block device when printing out configuration or stats.

This is redundant to begin with.  A blkg is an association between a
cgroup and a request_queue and it of course is possible to reach
request_queue from blkg and synchronization conventions are in place
for safe q dereferencing, so this shouldn't be necessary from the
beginning.  Furthermore, it's initialized by sscanf()ing the device
name of backing_dev_info.  The mind boggles.

Anyways, if blkg is visible under rcu lock, we *know* that the
associated request_queue hasn't gone away yet and its bdi is
registered and alive - blkg can't be created for request_queue which
hasn't been fully initialized and it can't go away before blkg is
removed.

Let stat and conf read functions get device name from
blkg->q->backing_dev_info.dev and pass it down to printing functions
and remove blkg->dev.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Cc: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 4bfd482e
...@@ -662,10 +662,10 @@ blkiocg_reset_stats(struct cgroup *cgroup, struct cftype *cftype, u64 val) ...@@ -662,10 +662,10 @@ blkiocg_reset_stats(struct cgroup *cgroup, struct cftype *cftype, u64 val)
return 0; return 0;
} }
static void blkio_get_key_name(enum stat_sub_type type, dev_t dev, char *str, static void blkio_get_key_name(enum stat_sub_type type, const char *dname,
int chars_left, bool diskname_only) char *str, int chars_left, bool diskname_only)
{ {
snprintf(str, chars_left, "%d:%d", MAJOR(dev), MINOR(dev)); snprintf(str, chars_left, "%s", dname);
chars_left -= strlen(str); chars_left -= strlen(str);
if (chars_left <= 0) { if (chars_left <= 0) {
printk(KERN_WARNING printk(KERN_WARNING
...@@ -696,9 +696,9 @@ static void blkio_get_key_name(enum stat_sub_type type, dev_t dev, char *str, ...@@ -696,9 +696,9 @@ static void blkio_get_key_name(enum stat_sub_type type, dev_t dev, char *str,
} }
static uint64_t blkio_fill_stat(char *str, int chars_left, uint64_t val, static uint64_t blkio_fill_stat(char *str, int chars_left, uint64_t val,
struct cgroup_map_cb *cb, dev_t dev) struct cgroup_map_cb *cb, const char *dname)
{ {
blkio_get_key_name(0, dev, str, chars_left, true); blkio_get_key_name(0, dname, str, chars_left, true);
cb->fill(cb, str, val); cb->fill(cb, str, val);
return val; return val;
} }
...@@ -730,7 +730,8 @@ static uint64_t blkio_read_stat_cpu(struct blkio_group *blkg, ...@@ -730,7 +730,8 @@ static uint64_t blkio_read_stat_cpu(struct blkio_group *blkg,
} }
static uint64_t blkio_get_stat_cpu(struct blkio_group *blkg, static uint64_t blkio_get_stat_cpu(struct blkio_group *blkg,
struct cgroup_map_cb *cb, dev_t dev, enum stat_type_cpu type) struct cgroup_map_cb *cb, const char *dname,
enum stat_type_cpu type)
{ {
uint64_t disk_total, val; uint64_t disk_total, val;
char key_str[MAX_KEY_LEN]; char key_str[MAX_KEY_LEN];
...@@ -738,12 +739,14 @@ static uint64_t blkio_get_stat_cpu(struct blkio_group *blkg, ...@@ -738,12 +739,14 @@ static uint64_t blkio_get_stat_cpu(struct blkio_group *blkg,
if (type == BLKIO_STAT_CPU_SECTORS) { if (type == BLKIO_STAT_CPU_SECTORS) {
val = blkio_read_stat_cpu(blkg, type, 0); val = blkio_read_stat_cpu(blkg, type, 0);
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, val, cb, dev); return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, val, cb,
dname);
} }
for (sub_type = BLKIO_STAT_READ; sub_type < BLKIO_STAT_TOTAL; for (sub_type = BLKIO_STAT_READ; sub_type < BLKIO_STAT_TOTAL;
sub_type++) { sub_type++) {
blkio_get_key_name(sub_type, dev, key_str, MAX_KEY_LEN, false); blkio_get_key_name(sub_type, dname, key_str, MAX_KEY_LEN,
false);
val = blkio_read_stat_cpu(blkg, type, sub_type); val = blkio_read_stat_cpu(blkg, type, sub_type);
cb->fill(cb, key_str, val); cb->fill(cb, key_str, val);
} }
...@@ -751,14 +754,16 @@ static uint64_t blkio_get_stat_cpu(struct blkio_group *blkg, ...@@ -751,14 +754,16 @@ static uint64_t blkio_get_stat_cpu(struct blkio_group *blkg,
disk_total = blkio_read_stat_cpu(blkg, type, BLKIO_STAT_READ) + disk_total = blkio_read_stat_cpu(blkg, type, BLKIO_STAT_READ) +
blkio_read_stat_cpu(blkg, type, BLKIO_STAT_WRITE); blkio_read_stat_cpu(blkg, type, BLKIO_STAT_WRITE);
blkio_get_key_name(BLKIO_STAT_TOTAL, dev, key_str, MAX_KEY_LEN, false); blkio_get_key_name(BLKIO_STAT_TOTAL, dname, key_str, MAX_KEY_LEN,
false);
cb->fill(cb, key_str, disk_total); cb->fill(cb, key_str, disk_total);
return disk_total; return disk_total;
} }
/* This should be called with blkg->stats_lock held */ /* This should be called with blkg->stats_lock held */
static uint64_t blkio_get_stat(struct blkio_group *blkg, static uint64_t blkio_get_stat(struct blkio_group *blkg,
struct cgroup_map_cb *cb, dev_t dev, enum stat_type type) struct cgroup_map_cb *cb, const char *dname,
enum stat_type type)
{ {
uint64_t disk_total; uint64_t disk_total;
char key_str[MAX_KEY_LEN]; char key_str[MAX_KEY_LEN];
...@@ -766,11 +771,11 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg, ...@@ -766,11 +771,11 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg,
if (type == BLKIO_STAT_TIME) if (type == BLKIO_STAT_TIME)
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
blkg->stats.time, cb, dev); blkg->stats.time, cb, dname);
#ifdef CONFIG_DEBUG_BLK_CGROUP #ifdef CONFIG_DEBUG_BLK_CGROUP
if (type == BLKIO_STAT_UNACCOUNTED_TIME) if (type == BLKIO_STAT_UNACCOUNTED_TIME)
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
blkg->stats.unaccounted_time, cb, dev); blkg->stats.unaccounted_time, cb, dname);
if (type == BLKIO_STAT_AVG_QUEUE_SIZE) { if (type == BLKIO_STAT_AVG_QUEUE_SIZE) {
uint64_t sum = blkg->stats.avg_queue_size_sum; uint64_t sum = blkg->stats.avg_queue_size_sum;
uint64_t samples = blkg->stats.avg_queue_size_samples; uint64_t samples = blkg->stats.avg_queue_size_samples;
...@@ -778,30 +783,33 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg, ...@@ -778,30 +783,33 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg,
do_div(sum, samples); do_div(sum, samples);
else else
sum = 0; sum = 0;
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, sum, cb, dev); return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
sum, cb, dname);
} }
if (type == BLKIO_STAT_GROUP_WAIT_TIME) if (type == BLKIO_STAT_GROUP_WAIT_TIME)
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
blkg->stats.group_wait_time, cb, dev); blkg->stats.group_wait_time, cb, dname);
if (type == BLKIO_STAT_IDLE_TIME) if (type == BLKIO_STAT_IDLE_TIME)
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
blkg->stats.idle_time, cb, dev); blkg->stats.idle_time, cb, dname);
if (type == BLKIO_STAT_EMPTY_TIME) if (type == BLKIO_STAT_EMPTY_TIME)
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
blkg->stats.empty_time, cb, dev); blkg->stats.empty_time, cb, dname);
if (type == BLKIO_STAT_DEQUEUE) if (type == BLKIO_STAT_DEQUEUE)
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
blkg->stats.dequeue, cb, dev); blkg->stats.dequeue, cb, dname);
#endif #endif
for (sub_type = BLKIO_STAT_READ; sub_type < BLKIO_STAT_TOTAL; for (sub_type = BLKIO_STAT_READ; sub_type < BLKIO_STAT_TOTAL;
sub_type++) { sub_type++) {
blkio_get_key_name(sub_type, dev, key_str, MAX_KEY_LEN, false); blkio_get_key_name(sub_type, dname, key_str, MAX_KEY_LEN,
false);
cb->fill(cb, key_str, blkg->stats.stat_arr[type][sub_type]); cb->fill(cb, key_str, blkg->stats.stat_arr[type][sub_type]);
} }
disk_total = blkg->stats.stat_arr[type][BLKIO_STAT_READ] + disk_total = blkg->stats.stat_arr[type][BLKIO_STAT_READ] +
blkg->stats.stat_arr[type][BLKIO_STAT_WRITE]; blkg->stats.stat_arr[type][BLKIO_STAT_WRITE];
blkio_get_key_name(BLKIO_STAT_TOTAL, dev, key_str, MAX_KEY_LEN, false); blkio_get_key_name(BLKIO_STAT_TOTAL, dname, key_str, MAX_KEY_LEN,
false);
cb->fill(cb, key_str, disk_total); cb->fill(cb, key_str, disk_total);
return disk_total; return disk_total;
} }
...@@ -946,14 +954,15 @@ static int blkiocg_file_write(struct cgroup *cgrp, struct cftype *cft, ...@@ -946,14 +954,15 @@ static int blkiocg_file_write(struct cgroup *cgrp, struct cftype *cft,
static void blkio_print_group_conf(struct cftype *cft, struct blkio_group *blkg, static void blkio_print_group_conf(struct cftype *cft, struct blkio_group *blkg,
struct seq_file *m) struct seq_file *m)
{ {
const char *dname = dev_name(blkg->q->backing_dev_info.dev);
int fileid = BLKIOFILE_ATTR(cft->private); int fileid = BLKIOFILE_ATTR(cft->private);
int rw = WRITE; int rw = WRITE;
switch (blkg->plid) { switch (blkg->plid) {
case BLKIO_POLICY_PROP: case BLKIO_POLICY_PROP:
if (blkg->conf.weight) if (blkg->conf.weight)
seq_printf(m, "%u:%u\t%u\n", MAJOR(blkg->dev), seq_printf(m, "%s\t%u\n",
MINOR(blkg->dev), blkg->conf.weight); dname, blkg->conf.weight);
break; break;
case BLKIO_POLICY_THROTL: case BLKIO_POLICY_THROTL:
switch (fileid) { switch (fileid) {
...@@ -961,19 +970,15 @@ static void blkio_print_group_conf(struct cftype *cft, struct blkio_group *blkg, ...@@ -961,19 +970,15 @@ static void blkio_print_group_conf(struct cftype *cft, struct blkio_group *blkg,
rw = READ; rw = READ;
case BLKIO_THROTL_write_bps_device: case BLKIO_THROTL_write_bps_device:
if (blkg->conf.bps[rw]) if (blkg->conf.bps[rw])
seq_printf(m, "%u:%u\t%llu\n", seq_printf(m, "%s\t%llu\n",
MAJOR(blkg->dev), dname, blkg->conf.bps[rw]);
MINOR(blkg->dev),
blkg->conf.bps[rw]);
break; break;
case BLKIO_THROTL_read_iops_device: case BLKIO_THROTL_read_iops_device:
rw = READ; rw = READ;
case BLKIO_THROTL_write_iops_device: case BLKIO_THROTL_write_iops_device:
if (blkg->conf.iops[rw]) if (blkg->conf.iops[rw])
seq_printf(m, "%u:%u\t%u\n", seq_printf(m, "%s\t%u\n",
MAJOR(blkg->dev), dname, blkg->conf.iops[rw]);
MINOR(blkg->dev),
blkg->conf.iops[rw]);
break; break;
} }
break; break;
...@@ -1044,18 +1049,17 @@ static int blkio_read_blkg_stats(struct blkio_cgroup *blkcg, ...@@ -1044,18 +1049,17 @@ static int blkio_read_blkg_stats(struct blkio_cgroup *blkcg,
rcu_read_lock(); rcu_read_lock();
hlist_for_each_entry_rcu(blkg, n, &blkcg->blkg_list, blkcg_node) { hlist_for_each_entry_rcu(blkg, n, &blkcg->blkg_list, blkcg_node) {
if (blkg->dev) { const char *dname = dev_name(blkg->q->backing_dev_info.dev);
if (BLKIOFILE_POLICY(cft->private) != blkg->plid)
continue; if (BLKIOFILE_POLICY(cft->private) != blkg->plid)
if (pcpu) continue;
cgroup_total += blkio_get_stat_cpu(blkg, cb, if (pcpu)
blkg->dev, type); cgroup_total += blkio_get_stat_cpu(blkg, cb, dname,
else { type);
spin_lock_irq(&blkg->stats_lock); else {
cgroup_total += blkio_get_stat(blkg, cb, spin_lock_irq(&blkg->stats_lock);
blkg->dev, type); cgroup_total += blkio_get_stat(blkg, cb, dname, type);
spin_unlock_irq(&blkg->stats_lock); spin_unlock_irq(&blkg->stats_lock);
}
} }
} }
if (show_total) if (show_total)
......
...@@ -166,8 +166,6 @@ struct blkio_group { ...@@ -166,8 +166,6 @@ struct blkio_group {
unsigned short blkcg_id; unsigned short blkcg_id;
/* Store cgroup path */ /* Store cgroup path */
char path[128]; char path[128];
/* The device MKDEV(major, minor), this group has been created for */
dev_t dev;
/* policy which owns this blk group */ /* policy which owns this blk group */
enum blkio_policy_id plid; enum blkio_policy_id plid;
......
...@@ -212,50 +212,12 @@ static struct blkio_group *throtl_alloc_blkio_group(struct request_queue *q, ...@@ -212,50 +212,12 @@ static struct blkio_group *throtl_alloc_blkio_group(struct request_queue *q,
return &tg->blkg; return &tg->blkg;
} }
static void
__throtl_tg_fill_dev_details(struct throtl_data *td, struct throtl_grp *tg)
{
struct backing_dev_info *bdi = &td->queue->backing_dev_info;
unsigned int major, minor;
if (!tg || tg->blkg.dev)
return;
/*
* Fill in device details for a group which might not have been
* filled at group creation time as queue was being instantiated
* and driver had not attached a device yet
*/
if (bdi->dev && dev_name(bdi->dev)) {
sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
tg->blkg.dev = MKDEV(major, minor);
}
}
/*
* Should be called with without queue lock held. Here queue lock will be
* taken rarely. It will be taken only once during life time of a group
* if need be
*/
static void
throtl_tg_fill_dev_details(struct throtl_data *td, struct throtl_grp *tg)
{
if (!tg || tg->blkg.dev)
return;
spin_lock_irq(td->queue->queue_lock);
__throtl_tg_fill_dev_details(td, tg);
spin_unlock_irq(td->queue->queue_lock);
}
static void throtl_link_blkio_group(struct request_queue *q, static void throtl_link_blkio_group(struct request_queue *q,
struct blkio_group *blkg) struct blkio_group *blkg)
{ {
struct throtl_data *td = q->td; struct throtl_data *td = q->td;
struct throtl_grp *tg = tg_of_blkg(blkg); struct throtl_grp *tg = tg_of_blkg(blkg);
__throtl_tg_fill_dev_details(td, tg);
hlist_add_head(&tg->tg_node, &td->tg_list); hlist_add_head(&tg->tg_node, &td->tg_list);
td->nr_undestroyed_grps++; td->nr_undestroyed_grps++;
} }
...@@ -263,20 +225,14 @@ static void throtl_link_blkio_group(struct request_queue *q, ...@@ -263,20 +225,14 @@ static void throtl_link_blkio_group(struct request_queue *q,
static struct static struct
throtl_grp *throtl_lookup_tg(struct throtl_data *td, struct blkio_cgroup *blkcg) throtl_grp *throtl_lookup_tg(struct throtl_data *td, struct blkio_cgroup *blkcg)
{ {
struct throtl_grp *tg = NULL;
/* /*
* This is the common case when there are no blkio cgroups. * This is the common case when there are no blkio cgroups.
* Avoid lookup in this case * Avoid lookup in this case
*/ */
if (blkcg == &blkio_root_cgroup) if (blkcg == &blkio_root_cgroup)
tg = td->root_tg; return td->root_tg;
else
tg = tg_of_blkg(blkg_lookup(blkcg, td->queue,
BLKIO_POLICY_THROTL));
__throtl_tg_fill_dev_details(td, tg); return tg_of_blkg(blkg_lookup(blkcg, td->queue, BLKIO_POLICY_THROTL));
return tg;
} }
static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td, static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td,
...@@ -303,7 +259,6 @@ static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td, ...@@ -303,7 +259,6 @@ static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td,
tg = td->root_tg; tg = td->root_tg;
} }
__throtl_tg_fill_dev_details(td, tg);
return tg; return tg;
} }
...@@ -1090,8 +1045,6 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) ...@@ -1090,8 +1045,6 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
blkcg = task_blkio_cgroup(current); blkcg = task_blkio_cgroup(current);
tg = throtl_lookup_tg(td, blkcg); tg = throtl_lookup_tg(td, blkcg);
if (tg) { if (tg) {
throtl_tg_fill_dev_details(td, tg);
if (tg_no_rule_group(tg, rw)) { if (tg_no_rule_group(tg, rw)) {
blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size,
rw, rw_is_sync(bio->bi_rw)); rw, rw_is_sync(bio->bi_rw));
......
...@@ -1052,20 +1052,7 @@ static void cfq_link_blkio_group(struct request_queue *q, ...@@ -1052,20 +1052,7 @@ static void cfq_link_blkio_group(struct request_queue *q,
struct blkio_group *blkg) struct blkio_group *blkg)
{ {
struct cfq_data *cfqd = q->elevator->elevator_data; struct cfq_data *cfqd = q->elevator->elevator_data;
struct backing_dev_info *bdi = &q->backing_dev_info;
struct cfq_group *cfqg = cfqg_of_blkg(blkg); struct cfq_group *cfqg = cfqg_of_blkg(blkg);
unsigned int major, minor;
/*
* Add group onto cgroup list. It might happen that bdi->dev is
* not initialized yet. Initialize this new group without major
* and minor info and this info will be filled in once a new thread
* comes for IO.
*/
if (bdi->dev) {
sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
blkg->dev = MKDEV(major, minor);
}
cfqd->nr_blkcg_linked_grps++; cfqd->nr_blkcg_linked_grps++;
...@@ -1104,7 +1091,6 @@ static struct cfq_group *cfq_lookup_create_cfqg(struct cfq_data *cfqd, ...@@ -1104,7 +1091,6 @@ static struct cfq_group *cfq_lookup_create_cfqg(struct cfq_data *cfqd,
struct blkio_cgroup *blkcg) struct blkio_cgroup *blkcg)
{ {
struct request_queue *q = cfqd->queue; struct request_queue *q = cfqd->queue;
struct backing_dev_info *bdi = &q->backing_dev_info;
struct cfq_group *cfqg = NULL; struct cfq_group *cfqg = NULL;
/* avoid lookup for the common case where there's no blkio cgroup */ /* avoid lookup for the common case where there's no blkio cgroup */
...@@ -1118,13 +1104,6 @@ static struct cfq_group *cfq_lookup_create_cfqg(struct cfq_data *cfqd, ...@@ -1118,13 +1104,6 @@ static struct cfq_group *cfq_lookup_create_cfqg(struct cfq_data *cfqd,
cfqg = cfqg_of_blkg(blkg); cfqg = cfqg_of_blkg(blkg);
} }
if (cfqg && !cfqg->blkg.dev && bdi->dev && dev_name(bdi->dev)) {
unsigned int major, minor;
sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
cfqg->blkg.dev = MKDEV(major, minor);
}
return cfqg; return cfqg;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment