aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
authorArianna Avanzini <avanzini.arianna@gmail.com>2015-06-05 17:38:42 -0400
committerJens Axboe <axboe@fb.com>2015-06-07 10:10:08 -0400
commite48453c386f39ca9ea29e9df6efef78f56746af0 (patch)
treeb8aab51e5a1bb48f872640712e1f79ef09271438 /block/cfq-iosched.c
parent41c0126b3f22ef36b97b3c38b8f29569848a5ce2 (diff)
block, cgroup: implement policy-specific per-blkcg data
The block IO (blkio) controller enables the block layer to provide service guarantees in a hierarchical fashion. Specifically, service guarantees are provided by registered request-accounting policies. As of now, a proportional-share and a throttling policy are available. They are implemented, respectively, by the CFQ I/O scheduler and the blk-throttle subsystem. Unfortunately, as for adding new policies, the current implementation of the block IO controller is only halfway ready to allow new policies to be plugged in. This commit provides a solution to make the block IO controller fully ready to handle new policies. In what follows, we first describe briefly the current state, and then list the changes made by this commit. The throttling policy does not need any per-cgroup information to perform its task. In contrast, the proportional share policy uses, for each cgroup, both the weight assigned by the user to the cgroup, and a set of dynamically- computed weights, one for each device. The first, user-defined weight is stored in the blkcg data structure: the block IO controller allocates a private blkcg data structure for each cgroup in the blkio cgroups hierarchy (regardless of which policy is active). In other words, the block IO controller internally mirrors the blkio cgroups with private blkcg data structures. On the other hand, for each cgroup and device, the corresponding dynamically- computed weight is maintained in the following, different way. For each device, the block IO controller keeps a private blkcg_gq structure for each cgroup in blkio. In other words, block IO also keeps one private mirror copy of the blkio cgroups hierarchy for each device, made of blkcg_gq structures. Each blkcg_gq structure keeps per-policy information in a generic array of dynamically-allocated 'dedicated' data structures, one for each registered policy (so currently the array contains two elements). To be inserted into the generic array, each dedicated data structure embeds a generic blkg_policy_data structure. Consider now the array contained in the blkcg_gq structure corresponding to a given pair of cgroup and device: one of the elements of the array contains the dedicated data structure for the proportional-share policy, and this dedicated data structure contains the dynamically-computed weight for that pair of cgroup and device. The generic strategy adopted for storing per-policy data in blkcg_gq structures is already capable of handling new policies, whereas the one adopted with blkcg structures is not, because per-policy data are hard-coded in the blkcg structures themselves (currently only data related to the proportional- share policy). This commit addresses the above issues through the following changes: . It generalizes blkcg structures so that per-policy data are stored in the same way as in blkcg_gq structures. Specifically, it lets also the blkcg structure store per-policy data in a generic array of dynamically-allocated dedicated data structures. We will refer to these data structures as blkcg dedicated data structures, to distinguish them from the dedicated data structures inserted in the generic arrays kept by blkcg_gq structures. To allow blkcg dedicated data structures to be inserted in the generic array inside a blkcg structure, this commit also introduces a new blkcg_policy_data structure, which is the equivalent of blkg_policy_data for blkcg dedicated data structures. . It adds to the blkcg_policy structure, i.e., to the descriptor of a policy, a cpd_size field and a cpd_init field, to be initialized by the policy with, respectively, the size of the blkcg dedicated data structures, and the address of a constructor function for blkcg dedicated data structures. . It moves the CFQ-specific fields embedded in the blkcg data structure (i.e., the fields related to the proportional-share policy), into a new blkcg dedicated data structure called cfq_group_data. Signed-off-by: Paolo Valente <paolo.valente@unimore.it> Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com> Acked-by: Tejun Heo <tj@kernel.org> Cc: Jens Axboe <axboe@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c70
1 files changed, 60 insertions, 10 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 402be0139122..c808ad87652d 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -67,6 +67,11 @@ static struct kmem_cache *cfq_pool;
67#define sample_valid(samples) ((samples) > 80) 67#define sample_valid(samples) ((samples) > 80)
68#define rb_entry_cfqg(node) rb_entry((node), struct cfq_group, rb_node) 68#define rb_entry_cfqg(node) rb_entry((node), struct cfq_group, rb_node)
69 69
70/* blkio-related constants */
71#define CFQ_WEIGHT_MIN 10
72#define CFQ_WEIGHT_MAX 1000
73#define CFQ_WEIGHT_DEFAULT 500
74
70struct cfq_ttime { 75struct cfq_ttime {
71 unsigned long last_end_request; 76 unsigned long last_end_request;
72 77
@@ -212,6 +217,15 @@ struct cfqg_stats {
212#endif /* CONFIG_CFQ_GROUP_IOSCHED */ 217#endif /* CONFIG_CFQ_GROUP_IOSCHED */
213}; 218};
214 219
220/* Per-cgroup data */
221struct cfq_group_data {
222 /* must be the first member */
223 struct blkcg_policy_data pd;
224
225 unsigned int weight;
226 unsigned int leaf_weight;
227};
228
215/* This is per cgroup per device grouping structure */ 229/* This is per cgroup per device grouping structure */
216struct cfq_group { 230struct cfq_group {
217 /* must be the first member */ 231 /* must be the first member */
@@ -451,6 +465,12 @@ static inline struct cfq_group *pd_to_cfqg(struct blkg_policy_data *pd)
451 return pd ? container_of(pd, struct cfq_group, pd) : NULL; 465 return pd ? container_of(pd, struct cfq_group, pd) : NULL;
452} 466}
453 467
468static struct cfq_group_data
469*cpd_to_cfqgd(struct blkcg_policy_data *cpd)
470{
471 return cpd ? container_of(cpd, struct cfq_group_data, pd) : NULL;
472}
473
454static inline struct blkcg_gq *cfqg_to_blkg(struct cfq_group *cfqg) 474static inline struct blkcg_gq *cfqg_to_blkg(struct cfq_group *cfqg)
455{ 475{
456 return pd_to_blkg(&cfqg->pd); 476 return pd_to_blkg(&cfqg->pd);
@@ -607,6 +627,11 @@ static inline struct cfq_group *blkg_to_cfqg(struct blkcg_gq *blkg)
607 return pd_to_cfqg(blkg_to_pd(blkg, &blkcg_policy_cfq)); 627 return pd_to_cfqg(blkg_to_pd(blkg, &blkcg_policy_cfq));
608} 628}
609 629
630static struct cfq_group_data *blkcg_to_cfqgd(struct blkcg *blkcg)
631{
632 return cpd_to_cfqgd(blkcg_to_cpd(blkcg, &blkcg_policy_cfq));
633}
634
610static inline struct cfq_group *cfqg_parent(struct cfq_group *cfqg) 635static inline struct cfq_group *cfqg_parent(struct cfq_group *cfqg)
611{ 636{
612 struct blkcg_gq *pblkg = cfqg_to_blkg(cfqg)->parent; 637 struct blkcg_gq *pblkg = cfqg_to_blkg(cfqg)->parent;
@@ -1544,13 +1569,28 @@ static void cfqg_stats_init(struct cfqg_stats *stats)
1544#endif 1569#endif
1545} 1570}
1546 1571
1572static void cfq_cpd_init(const struct blkcg *blkcg)
1573{
1574 struct cfq_group_data *cgd =
1575 cpd_to_cfqgd(blkcg->pd[blkcg_policy_cfq.plid]);
1576
1577 if (blkcg == &blkcg_root) {
1578 cgd->weight = 2 * CFQ_WEIGHT_DEFAULT;
1579 cgd->leaf_weight = 2 * CFQ_WEIGHT_DEFAULT;
1580 } else {
1581 cgd->weight = CFQ_WEIGHT_DEFAULT;
1582 cgd->leaf_weight = CFQ_WEIGHT_DEFAULT;
1583 }
1584}
1585
1547static void cfq_pd_init(struct blkcg_gq *blkg) 1586static void cfq_pd_init(struct blkcg_gq *blkg)
1548{ 1587{
1549 struct cfq_group *cfqg = blkg_to_cfqg(blkg); 1588 struct cfq_group *cfqg = blkg_to_cfqg(blkg);
1589 struct cfq_group_data *cgd = blkcg_to_cfqgd(blkg->blkcg);
1550 1590
1551 cfq_init_cfqg_base(cfqg); 1591 cfq_init_cfqg_base(cfqg);
1552 cfqg->weight = blkg->blkcg->cfq_weight; 1592 cfqg->weight = cgd->weight;
1553 cfqg->leaf_weight = blkg->blkcg->cfq_leaf_weight; 1593 cfqg->leaf_weight = cgd->leaf_weight;
1554 cfqg_stats_init(&cfqg->stats); 1594 cfqg_stats_init(&cfqg->stats);
1555 cfqg_stats_init(&cfqg->dead_stats); 1595 cfqg_stats_init(&cfqg->dead_stats);
1556} 1596}
@@ -1673,13 +1713,17 @@ static int cfqg_print_leaf_weight_device(struct seq_file *sf, void *v)
1673 1713
1674static int cfq_print_weight(struct seq_file *sf, void *v) 1714static int cfq_print_weight(struct seq_file *sf, void *v)
1675{ 1715{
1676 seq_printf(sf, "%u\n", css_to_blkcg(seq_css(sf))->cfq_weight); 1716 struct blkcg *blkcg = css_to_blkcg(seq_css(sf));
1717
1718 seq_printf(sf, "%u\n", blkcg_to_cfqgd(blkcg)->weight);
1677 return 0; 1719 return 0;
1678} 1720}
1679 1721
1680static int cfq_print_leaf_weight(struct seq_file *sf, void *v) 1722static int cfq_print_leaf_weight(struct seq_file *sf, void *v)
1681{ 1723{
1682 seq_printf(sf, "%u\n", css_to_blkcg(seq_css(sf))->cfq_leaf_weight); 1724 struct blkcg *blkcg = css_to_blkcg(seq_css(sf));
1725
1726 seq_printf(sf, "%u\n", blkcg_to_cfqgd(blkcg)->leaf_weight);
1683 return 0; 1727 return 0;
1684} 1728}
1685 1729
@@ -1690,6 +1734,7 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of,
1690 struct blkcg *blkcg = css_to_blkcg(of_css(of)); 1734 struct blkcg *blkcg = css_to_blkcg(of_css(of));
1691 struct blkg_conf_ctx ctx; 1735 struct blkg_conf_ctx ctx;
1692 struct cfq_group *cfqg; 1736 struct cfq_group *cfqg;
1737 struct cfq_group_data *cfqgd;
1693 int ret; 1738 int ret;
1694 1739
1695 ret = blkg_conf_prep(blkcg, &blkcg_policy_cfq, buf, &ctx); 1740 ret = blkg_conf_prep(blkcg, &blkcg_policy_cfq, buf, &ctx);
@@ -1698,13 +1743,14 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of,
1698 1743
1699 ret = -EINVAL; 1744 ret = -EINVAL;
1700 cfqg = blkg_to_cfqg(ctx.blkg); 1745 cfqg = blkg_to_cfqg(ctx.blkg);
1746 cfqgd = blkcg_to_cfqgd(blkcg);
1701 if (!ctx.v || (ctx.v >= CFQ_WEIGHT_MIN && ctx.v <= CFQ_WEIGHT_MAX)) { 1747 if (!ctx.v || (ctx.v >= CFQ_WEIGHT_MIN && ctx.v <= CFQ_WEIGHT_MAX)) {
1702 if (!is_leaf_weight) { 1748 if (!is_leaf_weight) {
1703 cfqg->dev_weight = ctx.v; 1749 cfqg->dev_weight = ctx.v;
1704 cfqg->new_weight = ctx.v ?: blkcg->cfq_weight; 1750 cfqg->new_weight = ctx.v ?: cfqgd->weight;
1705 } else { 1751 } else {
1706 cfqg->dev_leaf_weight = ctx.v; 1752 cfqg->dev_leaf_weight = ctx.v;
1707 cfqg->new_leaf_weight = ctx.v ?: blkcg->cfq_leaf_weight; 1753 cfqg->new_leaf_weight = ctx.v ?: cfqgd->leaf_weight;
1708 } 1754 }
1709 ret = 0; 1755 ret = 0;
1710 } 1756 }
@@ -1730,16 +1776,18 @@ static int __cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft,
1730{ 1776{
1731 struct blkcg *blkcg = css_to_blkcg(css); 1777 struct blkcg *blkcg = css_to_blkcg(css);
1732 struct blkcg_gq *blkg; 1778 struct blkcg_gq *blkg;
1779 struct cfq_group_data *cfqgd;
1733 1780
1734 if (val < CFQ_WEIGHT_MIN || val > CFQ_WEIGHT_MAX) 1781 if (val < CFQ_WEIGHT_MIN || val > CFQ_WEIGHT_MAX)
1735 return -EINVAL; 1782 return -EINVAL;
1736 1783
1737 spin_lock_irq(&blkcg->lock); 1784 spin_lock_irq(&blkcg->lock);
1785 cfqgd = blkcg_to_cfqgd(blkcg);
1738 1786
1739 if (!is_leaf_weight) 1787 if (!is_leaf_weight)
1740 blkcg->cfq_weight = val; 1788 cfqgd->weight = val;
1741 else 1789 else
1742 blkcg->cfq_leaf_weight = val; 1790 cfqgd->leaf_weight = val;
1743 1791
1744 hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) { 1792 hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
1745 struct cfq_group *cfqg = blkg_to_cfqg(blkg); 1793 struct cfq_group *cfqg = blkg_to_cfqg(blkg);
@@ -1749,10 +1797,10 @@ static int __cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft,
1749 1797
1750 if (!is_leaf_weight) { 1798 if (!is_leaf_weight) {
1751 if (!cfqg->dev_weight) 1799 if (!cfqg->dev_weight)
1752 cfqg->new_weight = blkcg->cfq_weight; 1800 cfqg->new_weight = cfqgd->weight;
1753 } else { 1801 } else {
1754 if (!cfqg->dev_leaf_weight) 1802 if (!cfqg->dev_leaf_weight)
1755 cfqg->new_leaf_weight = blkcg->cfq_leaf_weight; 1803 cfqg->new_leaf_weight = cfqgd->leaf_weight;
1756 } 1804 }
1757 } 1805 }
1758 1806
@@ -4603,8 +4651,10 @@ static struct elevator_type iosched_cfq = {
4603#ifdef CONFIG_CFQ_GROUP_IOSCHED 4651#ifdef CONFIG_CFQ_GROUP_IOSCHED
4604static struct blkcg_policy blkcg_policy_cfq = { 4652static struct blkcg_policy blkcg_policy_cfq = {
4605 .pd_size = sizeof(struct cfq_group), 4653 .pd_size = sizeof(struct cfq_group),
4654 .cpd_size = sizeof(struct cfq_group_data),
4606 .cftypes = cfq_blkcg_files, 4655 .cftypes = cfq_blkcg_files,
4607 4656
4657 .cpd_init_fn = cfq_cpd_init,
4608 .pd_init_fn = cfq_pd_init, 4658 .pd_init_fn = cfq_pd_init,
4609 .pd_offline_fn = cfq_pd_offline, 4659 .pd_offline_fn = cfq_pd_offline,
4610 .pd_reset_stats_fn = cfq_pd_reset_stats, 4660 .pd_reset_stats_fn = cfq_pd_reset_stats,