Skip to content

Commit e71357e

Browse files
committed
cfq-iosched: add leaf_weight
cfq blkcg is about to grow proper hierarchy handling, where a child blkg's weight would nest inside the parent's. This makes tasks in a blkg to compete against both tasks in the sibling blkgs and the tasks of child blkgs. We're gonna use the existing weight as the group weight which decides the blkg's weight against its siblings. This patch introduces a new weight - leaf_weight - which decides the weight of a blkg against the child blkgs. It's named leaf_weight because another way to look at it is that each internal blkg nodes have a hidden child leaf node which contains all its tasks and leaf_weight is the weight of the leaf node and handled the same as the weight of the child blkgs. This patch only adds leaf_weight fields and exposes it to userland. The new weight isn't actually used anywhere yet. Note that cfq-iosched currently offcially supports only single level hierarchy and root blkgs compete with the first level blkgs - ie. root weight is basically being used as leaf_weight. For root blkgs, the two weights are kept in sync for backward compatibility. v2: cfqd->root_group->leaf_weight initialization was missing from cfq_init_queue() causing divide by zero when !CONFIG_CFQ_GROUP_SCHED. Fix it. Reported by Fengguang. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Fengguang Wu <fengguang.wu@intel.com>
1 parent 3c54786 commit e71357e

File tree

3 files changed

+130
-9
lines changed

3 files changed

+130
-9
lines changed

block/blk-cgroup.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626

2727
static DEFINE_MUTEX(blkcg_pol_mutex);
2828

29-
struct blkcg blkcg_root = { .cfq_weight = 2 * CFQ_WEIGHT_DEFAULT };
29+
struct blkcg blkcg_root = { .cfq_weight = 2 * CFQ_WEIGHT_DEFAULT,
30+
.cfq_leaf_weight = 2 * CFQ_WEIGHT_DEFAULT, };
3031
EXPORT_SYMBOL_GPL(blkcg_root);
3132

3233
static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS];
@@ -710,6 +711,7 @@ static struct cgroup_subsys_state *blkcg_css_alloc(struct cgroup *cgroup)
710711
return ERR_PTR(-ENOMEM);
711712

712713
blkcg->cfq_weight = CFQ_WEIGHT_DEFAULT;
714+
blkcg->cfq_leaf_weight = CFQ_WEIGHT_DEFAULT;
713715
blkcg->id = atomic64_inc_return(&id_seq); /* root is 0, start from 1 */
714716
done:
715717
spin_lock_init(&blkcg->lock);

block/blk-cgroup.h

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ struct blkcg {
5454

5555
/* TODO: per-policy storage in blkcg */
5656
unsigned int cfq_weight; /* belongs to cfq */
57+
unsigned int cfq_leaf_weight;
5758
};
5859

5960
struct blkg_stat {

block/cfq-iosched.c

+126-8
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,21 @@ struct cfq_group {
223223

224224
/* group service_tree key */
225225
u64 vdisktime;
226+
227+
/*
228+
* There are two weights - (internal) weight is the weight of this
229+
* cfqg against the sibling cfqgs. leaf_weight is the wight of
230+
* this cfqg against the child cfqgs. For the root cfqg, both
231+
* weights are kept in sync for backward compatibility.
232+
*/
226233
unsigned int weight;
227234
unsigned int new_weight;
228235
unsigned int dev_weight;
229236

237+
unsigned int leaf_weight;
238+
unsigned int new_leaf_weight;
239+
unsigned int dev_leaf_weight;
240+
230241
/* number of cfqq currently on this group */
231242
int nr_cfqq;
232243

@@ -1182,10 +1193,16 @@ static void
11821193
cfq_update_group_weight(struct cfq_group *cfqg)
11831194
{
11841195
BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
1196+
11851197
if (cfqg->new_weight) {
11861198
cfqg->weight = cfqg->new_weight;
11871199
cfqg->new_weight = 0;
11881200
}
1201+
1202+
if (cfqg->new_leaf_weight) {
1203+
cfqg->leaf_weight = cfqg->new_leaf_weight;
1204+
cfqg->new_leaf_weight = 0;
1205+
}
11891206
}
11901207

11911208
static void
@@ -1348,6 +1365,7 @@ static void cfq_pd_init(struct blkcg_gq *blkg)
13481365

13491366
cfq_init_cfqg_base(cfqg);
13501367
cfqg->weight = blkg->blkcg->cfq_weight;
1368+
cfqg->leaf_weight = blkg->blkcg->cfq_leaf_weight;
13511369
}
13521370

13531371
/*
@@ -1404,15 +1422,43 @@ static int cfqg_print_weight_device(struct cgroup *cgrp, struct cftype *cft,
14041422
return 0;
14051423
}
14061424

1425+
static u64 cfqg_prfill_leaf_weight_device(struct seq_file *sf,
1426+
struct blkg_policy_data *pd, int off)
1427+
{
1428+
struct cfq_group *cfqg = pd_to_cfqg(pd);
1429+
1430+
if (!cfqg->dev_leaf_weight)
1431+
return 0;
1432+
return __blkg_prfill_u64(sf, pd, cfqg->dev_leaf_weight);
1433+
}
1434+
1435+
static int cfqg_print_leaf_weight_device(struct cgroup *cgrp,
1436+
struct cftype *cft,
1437+
struct seq_file *sf)
1438+
{
1439+
blkcg_print_blkgs(sf, cgroup_to_blkcg(cgrp),
1440+
cfqg_prfill_leaf_weight_device, &blkcg_policy_cfq, 0,
1441+
false);
1442+
return 0;
1443+
}
1444+
14071445
static int cfq_print_weight(struct cgroup *cgrp, struct cftype *cft,
14081446
struct seq_file *sf)
14091447
{
14101448
seq_printf(sf, "%u\n", cgroup_to_blkcg(cgrp)->cfq_weight);
14111449
return 0;
14121450
}
14131451

1414-
static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft,
1415-
const char *buf)
1452+
static int cfq_print_leaf_weight(struct cgroup *cgrp, struct cftype *cft,
1453+
struct seq_file *sf)
1454+
{
1455+
seq_printf(sf, "%u\n",
1456+
cgroup_to_blkcg(cgrp)->cfq_leaf_weight);
1457+
return 0;
1458+
}
1459+
1460+
static int __cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft,
1461+
const char *buf, bool is_leaf_weight)
14161462
{
14171463
struct blkcg *blkcg = cgroup_to_blkcg(cgrp);
14181464
struct blkg_conf_ctx ctx;
@@ -1426,16 +1472,34 @@ static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft,
14261472
ret = -EINVAL;
14271473
cfqg = blkg_to_cfqg(ctx.blkg);
14281474
if (!ctx.v || (ctx.v >= CFQ_WEIGHT_MIN && ctx.v <= CFQ_WEIGHT_MAX)) {
1429-
cfqg->dev_weight = ctx.v;
1430-
cfqg->new_weight = cfqg->dev_weight ?: blkcg->cfq_weight;
1475+
if (!is_leaf_weight) {
1476+
cfqg->dev_weight = ctx.v;
1477+
cfqg->new_weight = ctx.v ?: blkcg->cfq_weight;
1478+
} else {
1479+
cfqg->dev_leaf_weight = ctx.v;
1480+
cfqg->new_leaf_weight = ctx.v ?: blkcg->cfq_leaf_weight;
1481+
}
14311482
ret = 0;
14321483
}
14331484

14341485
blkg_conf_finish(&ctx);
14351486
return ret;
14361487
}
14371488

1438-
static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val)
1489+
static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft,
1490+
const char *buf)
1491+
{
1492+
return __cfqg_set_weight_device(cgrp, cft, buf, false);
1493+
}
1494+
1495+
static int cfqg_set_leaf_weight_device(struct cgroup *cgrp, struct cftype *cft,
1496+
const char *buf)
1497+
{
1498+
return __cfqg_set_weight_device(cgrp, cft, buf, true);
1499+
}
1500+
1501+
static int __cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val,
1502+
bool is_leaf_weight)
14391503
{
14401504
struct blkcg *blkcg = cgroup_to_blkcg(cgrp);
14411505
struct blkcg_gq *blkg;
@@ -1445,19 +1509,41 @@ static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val)
14451509
return -EINVAL;
14461510

14471511
spin_lock_irq(&blkcg->lock);
1448-
blkcg->cfq_weight = (unsigned int)val;
1512+
1513+
if (!is_leaf_weight)
1514+
blkcg->cfq_weight = val;
1515+
else
1516+
blkcg->cfq_leaf_weight = val;
14491517

14501518
hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
14511519
struct cfq_group *cfqg = blkg_to_cfqg(blkg);
14521520

1453-
if (cfqg && !cfqg->dev_weight)
1454-
cfqg->new_weight = blkcg->cfq_weight;
1521+
if (!cfqg)
1522+
continue;
1523+
1524+
if (!is_leaf_weight) {
1525+
if (!cfqg->dev_weight)
1526+
cfqg->new_weight = blkcg->cfq_weight;
1527+
} else {
1528+
if (!cfqg->dev_leaf_weight)
1529+
cfqg->new_leaf_weight = blkcg->cfq_leaf_weight;
1530+
}
14551531
}
14561532

14571533
spin_unlock_irq(&blkcg->lock);
14581534
return 0;
14591535
}
14601536

1537+
static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val)
1538+
{
1539+
return __cfq_set_weight(cgrp, cft, val, false);
1540+
}
1541+
1542+
static int cfq_set_leaf_weight(struct cgroup *cgrp, struct cftype *cft, u64 val)
1543+
{
1544+
return __cfq_set_weight(cgrp, cft, val, true);
1545+
}
1546+
14611547
static int cfqg_print_stat(struct cgroup *cgrp, struct cftype *cft,
14621548
struct seq_file *sf)
14631549
{
@@ -1518,6 +1604,37 @@ static struct cftype cfq_blkcg_files[] = {
15181604
.read_seq_string = cfq_print_weight,
15191605
.write_u64 = cfq_set_weight,
15201606
},
1607+
1608+
/* on root, leaf_weight is mapped to weight */
1609+
{
1610+
.name = "leaf_weight_device",
1611+
.flags = CFTYPE_ONLY_ON_ROOT,
1612+
.read_seq_string = cfqg_print_weight_device,
1613+
.write_string = cfqg_set_weight_device,
1614+
.max_write_len = 256,
1615+
},
1616+
{
1617+
.name = "leaf_weight",
1618+
.flags = CFTYPE_ONLY_ON_ROOT,
1619+
.read_seq_string = cfq_print_weight,
1620+
.write_u64 = cfq_set_weight,
1621+
},
1622+
1623+
/* no such mapping necessary for !roots */
1624+
{
1625+
.name = "leaf_weight_device",
1626+
.flags = CFTYPE_NOT_ON_ROOT,
1627+
.read_seq_string = cfqg_print_leaf_weight_device,
1628+
.write_string = cfqg_set_leaf_weight_device,
1629+
.max_write_len = 256,
1630+
},
1631+
{
1632+
.name = "leaf_weight",
1633+
.flags = CFTYPE_NOT_ON_ROOT,
1634+
.read_seq_string = cfq_print_leaf_weight,
1635+
.write_u64 = cfq_set_leaf_weight,
1636+
},
1637+
15211638
{
15221639
.name = "time",
15231640
.private = offsetof(struct cfq_group, stats.time),
@@ -3992,6 +4109,7 @@ static int cfq_init_queue(struct request_queue *q)
39924109
cfq_init_cfqg_base(cfqd->root_group);
39934110
#endif
39944111
cfqd->root_group->weight = 2 * CFQ_WEIGHT_DEFAULT;
4112+
cfqd->root_group->leaf_weight = 2 * CFQ_WEIGHT_DEFAULT;
39954113

39964114
/*
39974115
* Not strictly needed (since RB_ROOT just clears the node and we

0 commit comments

Comments
 (0)