diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 125 |
1 files changed, 104 insertions, 21 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 5da8e6e9ab4b..d8ad45ccd8fa 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 */ |
@@ -446,16 +460,6 @@ CFQ_CFQQ_FNS(deep); | |||
446 | CFQ_CFQQ_FNS(wait_busy); | 460 | CFQ_CFQQ_FNS(wait_busy); |
447 | #undef CFQ_CFQQ_FNS | 461 | #undef CFQ_CFQQ_FNS |
448 | 462 | ||
449 | static inline struct cfq_group *pd_to_cfqg(struct blkg_policy_data *pd) | ||
450 | { | ||
451 | return pd ? container_of(pd, struct cfq_group, pd) : NULL; | ||
452 | } | ||
453 | |||
454 | static inline struct blkcg_gq *cfqg_to_blkg(struct cfq_group *cfqg) | ||
455 | { | ||
456 | return pd_to_blkg(&cfqg->pd); | ||
457 | } | ||
458 | |||
459 | #if defined(CONFIG_CFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP) | 463 | #if defined(CONFIG_CFQ_GROUP_IOSCHED) && defined(CONFIG_DEBUG_BLK_CGROUP) |
460 | 464 | ||
461 | /* cfqg stats flags */ | 465 | /* cfqg stats flags */ |
@@ -600,6 +604,22 @@ static inline void cfqg_stats_update_avg_queue_size(struct cfq_group *cfqg) { } | |||
600 | 604 | ||
601 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | 605 | #ifdef CONFIG_CFQ_GROUP_IOSCHED |
602 | 606 | ||
607 | static inline struct cfq_group *pd_to_cfqg(struct blkg_policy_data *pd) | ||
608 | { | ||
609 | return pd ? container_of(pd, struct cfq_group, pd) : NULL; | ||
610 | } | ||
611 | |||
612 | static struct cfq_group_data | ||
613 | *cpd_to_cfqgd(struct blkcg_policy_data *cpd) | ||
614 | { | ||
615 | return cpd ? container_of(cpd, struct cfq_group_data, pd) : NULL; | ||
616 | } | ||
617 | |||
618 | static inline struct blkcg_gq *cfqg_to_blkg(struct cfq_group *cfqg) | ||
619 | { | ||
620 | return pd_to_blkg(&cfqg->pd); | ||
621 | } | ||
622 | |||
603 | static struct blkcg_policy blkcg_policy_cfq; | 623 | static struct blkcg_policy blkcg_policy_cfq; |
604 | 624 | ||
605 | static inline struct cfq_group *blkg_to_cfqg(struct blkcg_gq *blkg) | 625 | static inline struct cfq_group *blkg_to_cfqg(struct blkcg_gq *blkg) |
@@ -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,27 @@ 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 | struct cfq_group_data *cgd = blkcg_to_cfqgd(blkcg); | ||
1718 | unsigned int val = 0; | ||
1719 | |||
1720 | if (cgd) | ||
1721 | val = cgd->weight; | ||
1722 | |||
1723 | seq_printf(sf, "%u\n", val); | ||
1677 | return 0; | 1724 | return 0; |
1678 | } | 1725 | } |
1679 | 1726 | ||
1680 | static int cfq_print_leaf_weight(struct seq_file *sf, void *v) | 1727 | static int cfq_print_leaf_weight(struct seq_file *sf, void *v) |
1681 | { | 1728 | { |
1682 | seq_printf(sf, "%u\n", css_to_blkcg(seq_css(sf))->cfq_leaf_weight); | 1729 | struct blkcg *blkcg = css_to_blkcg(seq_css(sf)); |
1730 | struct cfq_group_data *cgd = blkcg_to_cfqgd(blkcg); | ||
1731 | unsigned int val = 0; | ||
1732 | |||
1733 | if (cgd) | ||
1734 | val = cgd->leaf_weight; | ||
1735 | |||
1736 | seq_printf(sf, "%u\n", val); | ||
1683 | return 0; | 1737 | return 0; |
1684 | } | 1738 | } |
1685 | 1739 | ||
@@ -1690,6 +1744,7 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of, | |||
1690 | struct blkcg *blkcg = css_to_blkcg(of_css(of)); | 1744 | struct blkcg *blkcg = css_to_blkcg(of_css(of)); |
1691 | struct blkg_conf_ctx ctx; | 1745 | struct blkg_conf_ctx ctx; |
1692 | struct cfq_group *cfqg; | 1746 | struct cfq_group *cfqg; |
1747 | struct cfq_group_data *cfqgd; | ||
1693 | int ret; | 1748 | int ret; |
1694 | 1749 | ||
1695 | ret = blkg_conf_prep(blkcg, &blkcg_policy_cfq, buf, &ctx); | 1750 | ret = blkg_conf_prep(blkcg, &blkcg_policy_cfq, buf, &ctx); |
@@ -1698,17 +1753,22 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of, | |||
1698 | 1753 | ||
1699 | ret = -EINVAL; | 1754 | ret = -EINVAL; |
1700 | cfqg = blkg_to_cfqg(ctx.blkg); | 1755 | cfqg = blkg_to_cfqg(ctx.blkg); |
1756 | cfqgd = blkcg_to_cfqgd(blkcg); | ||
1757 | if (!cfqg || !cfqgd) | ||
1758 | goto err; | ||
1759 | |||
1701 | if (!ctx.v || (ctx.v >= CFQ_WEIGHT_MIN && ctx.v <= CFQ_WEIGHT_MAX)) { | 1760 | if (!ctx.v || (ctx.v >= CFQ_WEIGHT_MIN && ctx.v <= CFQ_WEIGHT_MAX)) { |
1702 | if (!is_leaf_weight) { | 1761 | if (!is_leaf_weight) { |
1703 | cfqg->dev_weight = ctx.v; | 1762 | cfqg->dev_weight = ctx.v; |
1704 | cfqg->new_weight = ctx.v ?: blkcg->cfq_weight; | 1763 | cfqg->new_weight = ctx.v ?: cfqgd->weight; |
1705 | } else { | 1764 | } else { |
1706 | cfqg->dev_leaf_weight = ctx.v; | 1765 | cfqg->dev_leaf_weight = ctx.v; |
1707 | cfqg->new_leaf_weight = ctx.v ?: blkcg->cfq_leaf_weight; | 1766 | cfqg->new_leaf_weight = ctx.v ?: cfqgd->leaf_weight; |
1708 | } | 1767 | } |
1709 | ret = 0; | 1768 | ret = 0; |
1710 | } | 1769 | } |
1711 | 1770 | ||
1771 | err: | ||
1712 | blkg_conf_finish(&ctx); | 1772 | blkg_conf_finish(&ctx); |
1713 | return ret ?: nbytes; | 1773 | return ret ?: nbytes; |
1714 | } | 1774 | } |
@@ -1730,16 +1790,23 @@ static int __cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, | |||
1730 | { | 1790 | { |
1731 | struct blkcg *blkcg = css_to_blkcg(css); | 1791 | struct blkcg *blkcg = css_to_blkcg(css); |
1732 | struct blkcg_gq *blkg; | 1792 | struct blkcg_gq *blkg; |
1793 | struct cfq_group_data *cfqgd; | ||
1794 | int ret = 0; | ||
1733 | 1795 | ||
1734 | if (val < CFQ_WEIGHT_MIN || val > CFQ_WEIGHT_MAX) | 1796 | if (val < CFQ_WEIGHT_MIN || val > CFQ_WEIGHT_MAX) |
1735 | return -EINVAL; | 1797 | return -EINVAL; |
1736 | 1798 | ||
1737 | spin_lock_irq(&blkcg->lock); | 1799 | spin_lock_irq(&blkcg->lock); |
1800 | cfqgd = blkcg_to_cfqgd(blkcg); | ||
1801 | if (!cfqgd) { | ||
1802 | ret = -EINVAL; | ||
1803 | goto out; | ||
1804 | } | ||
1738 | 1805 | ||
1739 | if (!is_leaf_weight) | 1806 | if (!is_leaf_weight) |
1740 | blkcg->cfq_weight = val; | 1807 | cfqgd->weight = val; |
1741 | else | 1808 | else |
1742 | blkcg->cfq_leaf_weight = val; | 1809 | cfqgd->leaf_weight = val; |
1743 | 1810 | ||
1744 | hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) { | 1811 | hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) { |
1745 | struct cfq_group *cfqg = blkg_to_cfqg(blkg); | 1812 | struct cfq_group *cfqg = blkg_to_cfqg(blkg); |
@@ -1749,15 +1816,16 @@ static int __cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, | |||
1749 | 1816 | ||
1750 | if (!is_leaf_weight) { | 1817 | if (!is_leaf_weight) { |
1751 | if (!cfqg->dev_weight) | 1818 | if (!cfqg->dev_weight) |
1752 | cfqg->new_weight = blkcg->cfq_weight; | 1819 | cfqg->new_weight = cfqgd->weight; |
1753 | } else { | 1820 | } else { |
1754 | if (!cfqg->dev_leaf_weight) | 1821 | if (!cfqg->dev_leaf_weight) |
1755 | cfqg->new_leaf_weight = blkcg->cfq_leaf_weight; | 1822 | cfqg->new_leaf_weight = cfqgd->leaf_weight; |
1756 | } | 1823 | } |
1757 | } | 1824 | } |
1758 | 1825 | ||
1826 | out: | ||
1759 | spin_unlock_irq(&blkcg->lock); | 1827 | spin_unlock_irq(&blkcg->lock); |
1760 | return 0; | 1828 | return ret; |
1761 | } | 1829 | } |
1762 | 1830 | ||
1763 | static int cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, | 1831 | static int cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, |
@@ -4477,6 +4545,18 @@ out_free: | |||
4477 | return ret; | 4545 | return ret; |
4478 | } | 4546 | } |
4479 | 4547 | ||
4548 | static void cfq_registered_queue(struct request_queue *q) | ||
4549 | { | ||
4550 | struct elevator_queue *e = q->elevator; | ||
4551 | struct cfq_data *cfqd = e->elevator_data; | ||
4552 | |||
4553 | /* | ||
4554 | * Default to IOPS mode with no idling for SSDs | ||
4555 | */ | ||
4556 | if (blk_queue_nonrot(q)) | ||
4557 | cfqd->cfq_slice_idle = 0; | ||
4558 | } | ||
4559 | |||
4480 | /* | 4560 | /* |
4481 | * sysfs parts below --> | 4561 | * sysfs parts below --> |
4482 | */ | 4562 | */ |
@@ -4592,6 +4672,7 @@ static struct elevator_type iosched_cfq = { | |||
4592 | .elevator_may_queue_fn = cfq_may_queue, | 4672 | .elevator_may_queue_fn = cfq_may_queue, |
4593 | .elevator_init_fn = cfq_init_queue, | 4673 | .elevator_init_fn = cfq_init_queue, |
4594 | .elevator_exit_fn = cfq_exit_queue, | 4674 | .elevator_exit_fn = cfq_exit_queue, |
4675 | .elevator_registered_fn = cfq_registered_queue, | ||
4595 | }, | 4676 | }, |
4596 | .icq_size = sizeof(struct cfq_io_cq), | 4677 | .icq_size = sizeof(struct cfq_io_cq), |
4597 | .icq_align = __alignof__(struct cfq_io_cq), | 4678 | .icq_align = __alignof__(struct cfq_io_cq), |
@@ -4603,8 +4684,10 @@ static struct elevator_type iosched_cfq = { | |||
4603 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | 4684 | #ifdef CONFIG_CFQ_GROUP_IOSCHED |
4604 | static struct blkcg_policy blkcg_policy_cfq = { | 4685 | static struct blkcg_policy blkcg_policy_cfq = { |
4605 | .pd_size = sizeof(struct cfq_group), | 4686 | .pd_size = sizeof(struct cfq_group), |
4687 | .cpd_size = sizeof(struct cfq_group_data), | ||
4606 | .cftypes = cfq_blkcg_files, | 4688 | .cftypes = cfq_blkcg_files, |
4607 | 4689 | ||
4690 | .cpd_init_fn = cfq_cpd_init, | ||
4608 | .pd_init_fn = cfq_pd_init, | 4691 | .pd_init_fn = cfq_pd_init, |
4609 | .pd_offline_fn = cfq_pd_offline, | 4692 | .pd_offline_fn = cfq_pd_offline, |
4610 | .pd_reset_stats_fn = cfq_pd_reset_stats, | 4693 | .pd_reset_stats_fn = cfq_pd_reset_stats, |