@@ -223,10 +223,21 @@ struct cfq_group {
223
223
224
224
/* group service_tree key */
225
225
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
+ */
226
233
unsigned int weight ;
227
234
unsigned int new_weight ;
228
235
unsigned int dev_weight ;
229
236
237
+ unsigned int leaf_weight ;
238
+ unsigned int new_leaf_weight ;
239
+ unsigned int dev_leaf_weight ;
240
+
230
241
/* number of cfqq currently on this group */
231
242
int nr_cfqq ;
232
243
@@ -1182,10 +1193,16 @@ static void
1182
1193
cfq_update_group_weight (struct cfq_group * cfqg )
1183
1194
{
1184
1195
BUG_ON (!RB_EMPTY_NODE (& cfqg -> rb_node ));
1196
+
1185
1197
if (cfqg -> new_weight ) {
1186
1198
cfqg -> weight = cfqg -> new_weight ;
1187
1199
cfqg -> new_weight = 0 ;
1188
1200
}
1201
+
1202
+ if (cfqg -> new_leaf_weight ) {
1203
+ cfqg -> leaf_weight = cfqg -> new_leaf_weight ;
1204
+ cfqg -> new_leaf_weight = 0 ;
1205
+ }
1189
1206
}
1190
1207
1191
1208
static void
@@ -1348,6 +1365,7 @@ static void cfq_pd_init(struct blkcg_gq *blkg)
1348
1365
1349
1366
cfq_init_cfqg_base (cfqg );
1350
1367
cfqg -> weight = blkg -> blkcg -> cfq_weight ;
1368
+ cfqg -> leaf_weight = blkg -> blkcg -> cfq_leaf_weight ;
1351
1369
}
1352
1370
1353
1371
/*
@@ -1404,15 +1422,43 @@ static int cfqg_print_weight_device(struct cgroup *cgrp, struct cftype *cft,
1404
1422
return 0 ;
1405
1423
}
1406
1424
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
+
1407
1445
static int cfq_print_weight (struct cgroup * cgrp , struct cftype * cft ,
1408
1446
struct seq_file * sf )
1409
1447
{
1410
1448
seq_printf (sf , "%u\n" , cgroup_to_blkcg (cgrp )-> cfq_weight );
1411
1449
return 0 ;
1412
1450
}
1413
1451
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 )
1416
1462
{
1417
1463
struct blkcg * blkcg = cgroup_to_blkcg (cgrp );
1418
1464
struct blkg_conf_ctx ctx ;
@@ -1426,16 +1472,34 @@ static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft,
1426
1472
ret = - EINVAL ;
1427
1473
cfqg = blkg_to_cfqg (ctx .blkg );
1428
1474
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
+ }
1431
1482
ret = 0 ;
1432
1483
}
1433
1484
1434
1485
blkg_conf_finish (& ctx );
1435
1486
return ret ;
1436
1487
}
1437
1488
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 )
1439
1503
{
1440
1504
struct blkcg * blkcg = cgroup_to_blkcg (cgrp );
1441
1505
struct blkcg_gq * blkg ;
@@ -1445,19 +1509,41 @@ static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val)
1445
1509
return - EINVAL ;
1446
1510
1447
1511
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 ;
1449
1517
1450
1518
hlist_for_each_entry (blkg , n , & blkcg -> blkg_list , blkcg_node ) {
1451
1519
struct cfq_group * cfqg = blkg_to_cfqg (blkg );
1452
1520
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
+ }
1455
1531
}
1456
1532
1457
1533
spin_unlock_irq (& blkcg -> lock );
1458
1534
return 0 ;
1459
1535
}
1460
1536
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
+
1461
1547
static int cfqg_print_stat (struct cgroup * cgrp , struct cftype * cft ,
1462
1548
struct seq_file * sf )
1463
1549
{
@@ -1518,6 +1604,37 @@ static struct cftype cfq_blkcg_files[] = {
1518
1604
.read_seq_string = cfq_print_weight ,
1519
1605
.write_u64 = cfq_set_weight ,
1520
1606
},
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
+
1521
1638
{
1522
1639
.name = "time" ,
1523
1640
.private = offsetof(struct cfq_group , stats .time ),
@@ -3992,6 +4109,7 @@ static int cfq_init_queue(struct request_queue *q)
3992
4109
cfq_init_cfqg_base (cfqd -> root_group );
3993
4110
#endif
3994
4111
cfqd -> root_group -> weight = 2 * CFQ_WEIGHT_DEFAULT ;
4112
+ cfqd -> root_group -> leaf_weight = 2 * CFQ_WEIGHT_DEFAULT ;
3995
4113
3996
4114
/*
3997
4115
* Not strictly needed (since RB_ROOT just clears the node and we
0 commit comments