summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorJan Kara <jack@suse.com>2016-01-12 10:24:19 -0500
committerJens Axboe <axboe@fb.com>2016-02-04 11:50:43 -0500
commit3984aa55204e2c3f423a70b013c44c64261788df (patch)
tree3a780ca008fdb70a06ddc8983cfaee289a3b3219 /block
parenta257ae3e482e1cbd5fc573efeef5a73bffe09757 (diff)
cfq-iosched: Allow parent cgroup to preempt its child
Currently we don't allow sync workload of one cgroup to preempt sync workload of any other cgroup. This is because we want to achieve service separation between cgroups. However in cases where cgroup preempting is ancestor of the current cgroup, there is no need of separation and idling introduces unnecessary overhead. This hurts for example the case when workload is isolated within a cgroup but journalling threads are in root cgroup. Simple way to demostrate the issue is using: dbench4 -c /usr/share/dbench4/client.txt -t 10 -D /mnt 1 on ext4 filesystem on plain SATA drive (mounted with barrier=0 to make difference more visible). When all processes are in the root cgroup, reported throughput is 153.132 MB/sec. When dbench process gets its own blkio cgroup, reported throughput drops to 26.1006 MB/sec. Fix the problem by making check in cfq_should_preempt() more benevolent and allow preemption by ancestor cgroup. This improves the throughput reported by dbench4 to 48.9106 MB/sec. Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jan Kara <jack@suse.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r--block/cfq-iosched.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 98569c2f373e..e3c591dd8f19 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -632,6 +632,13 @@ static inline struct cfq_group *cfqg_parent(struct cfq_group *cfqg)
632 return pblkg ? blkg_to_cfqg(pblkg) : NULL; 632 return pblkg ? blkg_to_cfqg(pblkg) : NULL;
633} 633}
634 634
635static inline bool cfqg_is_descendant(struct cfq_group *cfqg,
636 struct cfq_group *ancestor)
637{
638 return cgroup_is_descendant(cfqg_to_blkg(cfqg)->blkcg->css.cgroup,
639 cfqg_to_blkg(ancestor)->blkcg->css.cgroup);
640}
641
635static inline void cfqg_get(struct cfq_group *cfqg) 642static inline void cfqg_get(struct cfq_group *cfqg)
636{ 643{
637 return blkg_get(cfqg_to_blkg(cfqg)); 644 return blkg_get(cfqg_to_blkg(cfqg));
@@ -758,6 +765,11 @@ static void cfqg_stats_xfer_dead(struct cfq_group *cfqg)
758#else /* CONFIG_CFQ_GROUP_IOSCHED */ 765#else /* CONFIG_CFQ_GROUP_IOSCHED */
759 766
760static inline struct cfq_group *cfqg_parent(struct cfq_group *cfqg) { return NULL; } 767static inline struct cfq_group *cfqg_parent(struct cfq_group *cfqg) { return NULL; }
768static inline bool cfqg_is_descendant(struct cfq_group *cfqg,
769 struct cfq_group *ancestor)
770{
771 return true;
772}
761static inline void cfqg_get(struct cfq_group *cfqg) { } 773static inline void cfqg_get(struct cfq_group *cfqg) { }
762static inline void cfqg_put(struct cfq_group *cfqg) { } 774static inline void cfqg_put(struct cfq_group *cfqg) { }
763 775
@@ -3953,7 +3965,12 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
3953 if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq)) 3965 if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq))
3954 return true; 3966 return true;
3955 3967
3956 if (new_cfqq->cfqg != cfqq->cfqg) 3968 /*
3969 * Treat ancestors of current cgroup the same way as current cgroup.
3970 * For anybody else we disallow preemption to guarantee service
3971 * fairness among cgroups.
3972 */
3973 if (!cfqg_is_descendant(cfqq->cfqg, new_cfqq->cfqg))
3957 return false; 3974 return false;
3958 3975
3959 if (cfq_slice_used(cfqq)) 3976 if (cfq_slice_used(cfqq))