diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 70 |
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 | |||
70 | struct cfq_ttime { | 75 | struct 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 */ | ||
221 | struct 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 */ |
216 | struct cfq_group { | 230 | struct 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 | ||
468 | static 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 | |||
454 | static inline struct blkcg_gq *cfqg_to_blkg(struct cfq_group *cfqg) | 474 | static 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 | ||
630 | static 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 | |||
610 | static inline struct cfq_group *cfqg_parent(struct cfq_group *cfqg) | 635 | static 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 | ||
1572 | static 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 | |||
1547 | static void cfq_pd_init(struct blkcg_gq *blkg) | 1586 | static 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 | ||
1674 | static int cfq_print_weight(struct seq_file *sf, void *v) | 1714 | static 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 | ||
1680 | static int cfq_print_leaf_weight(struct seq_file *sf, void *v) | 1722 | static 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 |
4604 | static struct blkcg_policy blkcg_policy_cfq = { | 4652 | static 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, |