aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c125
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
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 */
@@ -446,16 +460,6 @@ CFQ_CFQQ_FNS(deep);
446CFQ_CFQQ_FNS(wait_busy); 460CFQ_CFQQ_FNS(wait_busy);
447#undef CFQ_CFQQ_FNS 461#undef CFQ_CFQQ_FNS
448 462
449static 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
454static 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
607static 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
612static 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
618static inline struct blkcg_gq *cfqg_to_blkg(struct cfq_group *cfqg)
619{
620 return pd_to_blkg(&cfqg->pd);
621}
622
603static struct blkcg_policy blkcg_policy_cfq; 623static struct blkcg_policy blkcg_policy_cfq;
604 624
605static inline struct cfq_group *blkg_to_cfqg(struct blkcg_gq *blkg) 625static 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
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,27 @@ 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 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
1680static int cfq_print_leaf_weight(struct seq_file *sf, void *v) 1727static 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
1771err:
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
1826out:
1759 spin_unlock_irq(&blkcg->lock); 1827 spin_unlock_irq(&blkcg->lock);
1760 return 0; 1828 return ret;
1761} 1829}
1762 1830
1763static int cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, 1831static 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
4548static 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
4604static struct blkcg_policy blkcg_policy_cfq = { 4685static 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,