162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * cgroups support for the BFQ I/O scheduler.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#include <linux/module.h>
662306a36Sopenharmony_ci#include <linux/slab.h>
762306a36Sopenharmony_ci#include <linux/blkdev.h>
862306a36Sopenharmony_ci#include <linux/cgroup.h>
962306a36Sopenharmony_ci#include <linux/ktime.h>
1062306a36Sopenharmony_ci#include <linux/rbtree.h>
1162306a36Sopenharmony_ci#include <linux/ioprio.h>
1262306a36Sopenharmony_ci#include <linux/sbitmap.h>
1362306a36Sopenharmony_ci#include <linux/delay.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include "elevator.h"
1662306a36Sopenharmony_ci#include "bfq-iosched.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG
1962306a36Sopenharmony_cistatic int bfq_stat_init(struct bfq_stat *stat, gfp_t gfp)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	int ret;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	ret = percpu_counter_init(&stat->cpu_cnt, 0, gfp);
2462306a36Sopenharmony_ci	if (ret)
2562306a36Sopenharmony_ci		return ret;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	atomic64_set(&stat->aux_cnt, 0);
2862306a36Sopenharmony_ci	return 0;
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic void bfq_stat_exit(struct bfq_stat *stat)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	percpu_counter_destroy(&stat->cpu_cnt);
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/**
3762306a36Sopenharmony_ci * bfq_stat_add - add a value to a bfq_stat
3862306a36Sopenharmony_ci * @stat: target bfq_stat
3962306a36Sopenharmony_ci * @val: value to add
4062306a36Sopenharmony_ci *
4162306a36Sopenharmony_ci * Add @val to @stat.  The caller must ensure that IRQ on the same CPU
4262306a36Sopenharmony_ci * don't re-enter this function for the same counter.
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_cistatic inline void bfq_stat_add(struct bfq_stat *stat, uint64_t val)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	percpu_counter_add_batch(&stat->cpu_cnt, val, BLKG_STAT_CPU_BATCH);
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/**
5062306a36Sopenharmony_ci * bfq_stat_read - read the current value of a bfq_stat
5162306a36Sopenharmony_ci * @stat: bfq_stat to read
5262306a36Sopenharmony_ci */
5362306a36Sopenharmony_cistatic inline uint64_t bfq_stat_read(struct bfq_stat *stat)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	return percpu_counter_sum_positive(&stat->cpu_cnt);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/**
5962306a36Sopenharmony_ci * bfq_stat_reset - reset a bfq_stat
6062306a36Sopenharmony_ci * @stat: bfq_stat to reset
6162306a36Sopenharmony_ci */
6262306a36Sopenharmony_cistatic inline void bfq_stat_reset(struct bfq_stat *stat)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	percpu_counter_set(&stat->cpu_cnt, 0);
6562306a36Sopenharmony_ci	atomic64_set(&stat->aux_cnt, 0);
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/**
6962306a36Sopenharmony_ci * bfq_stat_add_aux - add a bfq_stat into another's aux count
7062306a36Sopenharmony_ci * @to: the destination bfq_stat
7162306a36Sopenharmony_ci * @from: the source
7262306a36Sopenharmony_ci *
7362306a36Sopenharmony_ci * Add @from's count including the aux one to @to's aux count.
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_cistatic inline void bfq_stat_add_aux(struct bfq_stat *to,
7662306a36Sopenharmony_ci				     struct bfq_stat *from)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	atomic64_add(bfq_stat_read(from) + atomic64_read(&from->aux_cnt),
7962306a36Sopenharmony_ci		     &to->aux_cnt);
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/**
8362306a36Sopenharmony_ci * blkg_prfill_stat - prfill callback for bfq_stat
8462306a36Sopenharmony_ci * @sf: seq_file to print to
8562306a36Sopenharmony_ci * @pd: policy private data of interest
8662306a36Sopenharmony_ci * @off: offset to the bfq_stat in @pd
8762306a36Sopenharmony_ci *
8862306a36Sopenharmony_ci * prfill callback for printing a bfq_stat.
8962306a36Sopenharmony_ci */
9062306a36Sopenharmony_cistatic u64 blkg_prfill_stat(struct seq_file *sf, struct blkg_policy_data *pd,
9162306a36Sopenharmony_ci		int off)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	return __blkg_prfill_u64(sf, pd, bfq_stat_read((void *)pd + off));
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* bfqg stats flags */
9762306a36Sopenharmony_cienum bfqg_stats_flags {
9862306a36Sopenharmony_ci	BFQG_stats_waiting = 0,
9962306a36Sopenharmony_ci	BFQG_stats_idling,
10062306a36Sopenharmony_ci	BFQG_stats_empty,
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci#define BFQG_FLAG_FNS(name)						\
10462306a36Sopenharmony_cistatic void bfqg_stats_mark_##name(struct bfqg_stats *stats)	\
10562306a36Sopenharmony_ci{									\
10662306a36Sopenharmony_ci	stats->flags |= (1 << BFQG_stats_##name);			\
10762306a36Sopenharmony_ci}									\
10862306a36Sopenharmony_cistatic void bfqg_stats_clear_##name(struct bfqg_stats *stats)	\
10962306a36Sopenharmony_ci{									\
11062306a36Sopenharmony_ci	stats->flags &= ~(1 << BFQG_stats_##name);			\
11162306a36Sopenharmony_ci}									\
11262306a36Sopenharmony_cistatic int bfqg_stats_##name(struct bfqg_stats *stats)		\
11362306a36Sopenharmony_ci{									\
11462306a36Sopenharmony_ci	return (stats->flags & (1 << BFQG_stats_##name)) != 0;		\
11562306a36Sopenharmony_ci}									\
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ciBFQG_FLAG_FNS(waiting)
11862306a36Sopenharmony_ciBFQG_FLAG_FNS(idling)
11962306a36Sopenharmony_ciBFQG_FLAG_FNS(empty)
12062306a36Sopenharmony_ci#undef BFQG_FLAG_FNS
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci/* This should be called with the scheduler lock held. */
12362306a36Sopenharmony_cistatic void bfqg_stats_update_group_wait_time(struct bfqg_stats *stats)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	u64 now;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (!bfqg_stats_waiting(stats))
12862306a36Sopenharmony_ci		return;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	now = ktime_get_ns();
13162306a36Sopenharmony_ci	if (now > stats->start_group_wait_time)
13262306a36Sopenharmony_ci		bfq_stat_add(&stats->group_wait_time,
13362306a36Sopenharmony_ci			      now - stats->start_group_wait_time);
13462306a36Sopenharmony_ci	bfqg_stats_clear_waiting(stats);
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci/* This should be called with the scheduler lock held. */
13862306a36Sopenharmony_cistatic void bfqg_stats_set_start_group_wait_time(struct bfq_group *bfqg,
13962306a36Sopenharmony_ci						 struct bfq_group *curr_bfqg)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	struct bfqg_stats *stats = &bfqg->stats;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	if (bfqg_stats_waiting(stats))
14462306a36Sopenharmony_ci		return;
14562306a36Sopenharmony_ci	if (bfqg == curr_bfqg)
14662306a36Sopenharmony_ci		return;
14762306a36Sopenharmony_ci	stats->start_group_wait_time = ktime_get_ns();
14862306a36Sopenharmony_ci	bfqg_stats_mark_waiting(stats);
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci/* This should be called with the scheduler lock held. */
15262306a36Sopenharmony_cistatic void bfqg_stats_end_empty_time(struct bfqg_stats *stats)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	u64 now;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	if (!bfqg_stats_empty(stats))
15762306a36Sopenharmony_ci		return;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	now = ktime_get_ns();
16062306a36Sopenharmony_ci	if (now > stats->start_empty_time)
16162306a36Sopenharmony_ci		bfq_stat_add(&stats->empty_time,
16262306a36Sopenharmony_ci			      now - stats->start_empty_time);
16362306a36Sopenharmony_ci	bfqg_stats_clear_empty(stats);
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_civoid bfqg_stats_update_dequeue(struct bfq_group *bfqg)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	bfq_stat_add(&bfqg->stats.dequeue, 1);
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_civoid bfqg_stats_set_start_empty_time(struct bfq_group *bfqg)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	struct bfqg_stats *stats = &bfqg->stats;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	if (blkg_rwstat_total(&stats->queued))
17662306a36Sopenharmony_ci		return;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	/*
17962306a36Sopenharmony_ci	 * group is already marked empty. This can happen if bfqq got new
18062306a36Sopenharmony_ci	 * request in parent group and moved to this group while being added
18162306a36Sopenharmony_ci	 * to service tree. Just ignore the event and move on.
18262306a36Sopenharmony_ci	 */
18362306a36Sopenharmony_ci	if (bfqg_stats_empty(stats))
18462306a36Sopenharmony_ci		return;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	stats->start_empty_time = ktime_get_ns();
18762306a36Sopenharmony_ci	bfqg_stats_mark_empty(stats);
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_civoid bfqg_stats_update_idle_time(struct bfq_group *bfqg)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	struct bfqg_stats *stats = &bfqg->stats;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	if (bfqg_stats_idling(stats)) {
19562306a36Sopenharmony_ci		u64 now = ktime_get_ns();
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci		if (now > stats->start_idle_time)
19862306a36Sopenharmony_ci			bfq_stat_add(&stats->idle_time,
19962306a36Sopenharmony_ci				      now - stats->start_idle_time);
20062306a36Sopenharmony_ci		bfqg_stats_clear_idling(stats);
20162306a36Sopenharmony_ci	}
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_civoid bfqg_stats_set_start_idle_time(struct bfq_group *bfqg)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	struct bfqg_stats *stats = &bfqg->stats;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	stats->start_idle_time = ktime_get_ns();
20962306a36Sopenharmony_ci	bfqg_stats_mark_idling(stats);
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_civoid bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	struct bfqg_stats *stats = &bfqg->stats;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	bfq_stat_add(&stats->avg_queue_size_sum,
21762306a36Sopenharmony_ci		      blkg_rwstat_total(&stats->queued));
21862306a36Sopenharmony_ci	bfq_stat_add(&stats->avg_queue_size_samples, 1);
21962306a36Sopenharmony_ci	bfqg_stats_update_group_wait_time(stats);
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_civoid bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
22362306a36Sopenharmony_ci			      blk_opf_t opf)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	blkg_rwstat_add(&bfqg->stats.queued, opf, 1);
22662306a36Sopenharmony_ci	bfqg_stats_end_empty_time(&bfqg->stats);
22762306a36Sopenharmony_ci	if (!(bfqq == bfqg->bfqd->in_service_queue))
22862306a36Sopenharmony_ci		bfqg_stats_set_start_group_wait_time(bfqg, bfqq_group(bfqq));
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_civoid bfqg_stats_update_io_remove(struct bfq_group *bfqg, blk_opf_t opf)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	blkg_rwstat_add(&bfqg->stats.queued, opf, -1);
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_civoid bfqg_stats_update_io_merged(struct bfq_group *bfqg, blk_opf_t opf)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	blkg_rwstat_add(&bfqg->stats.merged, opf, 1);
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_civoid bfqg_stats_update_completion(struct bfq_group *bfqg, u64 start_time_ns,
24262306a36Sopenharmony_ci				  u64 io_start_time_ns, blk_opf_t opf)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	struct bfqg_stats *stats = &bfqg->stats;
24562306a36Sopenharmony_ci	u64 now = ktime_get_ns();
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	if (now > io_start_time_ns)
24862306a36Sopenharmony_ci		blkg_rwstat_add(&stats->service_time, opf,
24962306a36Sopenharmony_ci				now - io_start_time_ns);
25062306a36Sopenharmony_ci	if (io_start_time_ns > start_time_ns)
25162306a36Sopenharmony_ci		blkg_rwstat_add(&stats->wait_time, opf,
25262306a36Sopenharmony_ci				io_start_time_ns - start_time_ns);
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci#else /* CONFIG_BFQ_CGROUP_DEBUG */
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_civoid bfqg_stats_update_io_remove(struct bfq_group *bfqg, blk_opf_t opf) { }
25862306a36Sopenharmony_civoid bfqg_stats_update_io_merged(struct bfq_group *bfqg, blk_opf_t opf) { }
25962306a36Sopenharmony_civoid bfqg_stats_update_completion(struct bfq_group *bfqg, u64 start_time_ns,
26062306a36Sopenharmony_ci				  u64 io_start_time_ns, blk_opf_t opf) { }
26162306a36Sopenharmony_civoid bfqg_stats_update_dequeue(struct bfq_group *bfqg) { }
26262306a36Sopenharmony_civoid bfqg_stats_set_start_idle_time(struct bfq_group *bfqg) { }
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci#endif /* CONFIG_BFQ_CGROUP_DEBUG */
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci#ifdef CONFIG_BFQ_GROUP_IOSCHED
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci/*
26962306a36Sopenharmony_ci * blk-cgroup policy-related handlers
27062306a36Sopenharmony_ci * The following functions help in converting between blk-cgroup
27162306a36Sopenharmony_ci * internal structures and BFQ-specific structures.
27262306a36Sopenharmony_ci */
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic struct bfq_group *pd_to_bfqg(struct blkg_policy_data *pd)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	return pd ? container_of(pd, struct bfq_group, pd) : NULL;
27762306a36Sopenharmony_ci}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_cistruct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg)
28062306a36Sopenharmony_ci{
28162306a36Sopenharmony_ci	return pd_to_blkg(&bfqg->pd);
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic struct bfq_group *blkg_to_bfqg(struct blkcg_gq *blkg)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	return pd_to_bfqg(blkg_to_pd(blkg, &blkcg_policy_bfq));
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci/*
29062306a36Sopenharmony_ci * bfq_group handlers
29162306a36Sopenharmony_ci * The following functions help in navigating the bfq_group hierarchy
29262306a36Sopenharmony_ci * by allowing to find the parent of a bfq_group or the bfq_group
29362306a36Sopenharmony_ci * associated to a bfq_queue.
29462306a36Sopenharmony_ci */
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic struct bfq_group *bfqg_parent(struct bfq_group *bfqg)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	struct blkcg_gq *pblkg = bfqg_to_blkg(bfqg)->parent;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	return pblkg ? blkg_to_bfqg(pblkg) : NULL;
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistruct bfq_group *bfqq_group(struct bfq_queue *bfqq)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	struct bfq_entity *group_entity = bfqq->entity.parent;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	return group_entity ? container_of(group_entity, struct bfq_group,
30862306a36Sopenharmony_ci					   entity) :
30962306a36Sopenharmony_ci			      bfqq->bfqd->root_group;
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci/*
31362306a36Sopenharmony_ci * The following two functions handle get and put of a bfq_group by
31462306a36Sopenharmony_ci * wrapping the related blk-cgroup hooks.
31562306a36Sopenharmony_ci */
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic void bfqg_get(struct bfq_group *bfqg)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	refcount_inc(&bfqg->ref);
32062306a36Sopenharmony_ci}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cistatic void bfqg_put(struct bfq_group *bfqg)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	if (refcount_dec_and_test(&bfqg->ref))
32562306a36Sopenharmony_ci		kfree(bfqg);
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic void bfqg_and_blkg_get(struct bfq_group *bfqg)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	/* see comments in bfq_bic_update_cgroup for why refcounting bfqg */
33162306a36Sopenharmony_ci	bfqg_get(bfqg);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	blkg_get(bfqg_to_blkg(bfqg));
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_civoid bfqg_and_blkg_put(struct bfq_group *bfqg)
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	blkg_put(bfqg_to_blkg(bfqg));
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	bfqg_put(bfqg);
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_civoid bfqg_stats_update_legacy_io(struct request_queue *q, struct request *rq)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct bfq_group *bfqg = blkg_to_bfqg(rq->bio->bi_blkg);
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	if (!bfqg)
34862306a36Sopenharmony_ci		return;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	blkg_rwstat_add(&bfqg->stats.bytes, rq->cmd_flags, blk_rq_bytes(rq));
35162306a36Sopenharmony_ci	blkg_rwstat_add(&bfqg->stats.ios, rq->cmd_flags, 1);
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci/* @stats = 0 */
35562306a36Sopenharmony_cistatic void bfqg_stats_reset(struct bfqg_stats *stats)
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG
35862306a36Sopenharmony_ci	/* queued stats shouldn't be cleared */
35962306a36Sopenharmony_ci	blkg_rwstat_reset(&stats->merged);
36062306a36Sopenharmony_ci	blkg_rwstat_reset(&stats->service_time);
36162306a36Sopenharmony_ci	blkg_rwstat_reset(&stats->wait_time);
36262306a36Sopenharmony_ci	bfq_stat_reset(&stats->time);
36362306a36Sopenharmony_ci	bfq_stat_reset(&stats->avg_queue_size_sum);
36462306a36Sopenharmony_ci	bfq_stat_reset(&stats->avg_queue_size_samples);
36562306a36Sopenharmony_ci	bfq_stat_reset(&stats->dequeue);
36662306a36Sopenharmony_ci	bfq_stat_reset(&stats->group_wait_time);
36762306a36Sopenharmony_ci	bfq_stat_reset(&stats->idle_time);
36862306a36Sopenharmony_ci	bfq_stat_reset(&stats->empty_time);
36962306a36Sopenharmony_ci#endif
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci/* @to += @from */
37362306a36Sopenharmony_cistatic void bfqg_stats_add_aux(struct bfqg_stats *to, struct bfqg_stats *from)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	if (!to || !from)
37662306a36Sopenharmony_ci		return;
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG
37962306a36Sopenharmony_ci	/* queued stats shouldn't be cleared */
38062306a36Sopenharmony_ci	blkg_rwstat_add_aux(&to->merged, &from->merged);
38162306a36Sopenharmony_ci	blkg_rwstat_add_aux(&to->service_time, &from->service_time);
38262306a36Sopenharmony_ci	blkg_rwstat_add_aux(&to->wait_time, &from->wait_time);
38362306a36Sopenharmony_ci	bfq_stat_add_aux(&from->time, &from->time);
38462306a36Sopenharmony_ci	bfq_stat_add_aux(&to->avg_queue_size_sum, &from->avg_queue_size_sum);
38562306a36Sopenharmony_ci	bfq_stat_add_aux(&to->avg_queue_size_samples,
38662306a36Sopenharmony_ci			  &from->avg_queue_size_samples);
38762306a36Sopenharmony_ci	bfq_stat_add_aux(&to->dequeue, &from->dequeue);
38862306a36Sopenharmony_ci	bfq_stat_add_aux(&to->group_wait_time, &from->group_wait_time);
38962306a36Sopenharmony_ci	bfq_stat_add_aux(&to->idle_time, &from->idle_time);
39062306a36Sopenharmony_ci	bfq_stat_add_aux(&to->empty_time, &from->empty_time);
39162306a36Sopenharmony_ci#endif
39262306a36Sopenharmony_ci}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci/*
39562306a36Sopenharmony_ci * Transfer @bfqg's stats to its parent's aux counts so that the ancestors'
39662306a36Sopenharmony_ci * recursive stats can still account for the amount used by this bfqg after
39762306a36Sopenharmony_ci * it's gone.
39862306a36Sopenharmony_ci */
39962306a36Sopenharmony_cistatic void bfqg_stats_xfer_dead(struct bfq_group *bfqg)
40062306a36Sopenharmony_ci{
40162306a36Sopenharmony_ci	struct bfq_group *parent;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	if (!bfqg) /* root_group */
40462306a36Sopenharmony_ci		return;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	parent = bfqg_parent(bfqg);
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	lockdep_assert_held(&bfqg_to_blkg(bfqg)->q->queue_lock);
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	if (unlikely(!parent))
41162306a36Sopenharmony_ci		return;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	bfqg_stats_add_aux(&parent->stats, &bfqg->stats);
41462306a36Sopenharmony_ci	bfqg_stats_reset(&bfqg->stats);
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_civoid bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	entity->weight = entity->new_weight;
42262306a36Sopenharmony_ci	entity->orig_weight = entity->new_weight;
42362306a36Sopenharmony_ci	if (bfqq) {
42462306a36Sopenharmony_ci		bfqq->ioprio = bfqq->new_ioprio;
42562306a36Sopenharmony_ci		bfqq->ioprio_class = bfqq->new_ioprio_class;
42662306a36Sopenharmony_ci		/*
42762306a36Sopenharmony_ci		 * Make sure that bfqg and its associated blkg do not
42862306a36Sopenharmony_ci		 * disappear before entity.
42962306a36Sopenharmony_ci		 */
43062306a36Sopenharmony_ci		bfqg_and_blkg_get(bfqg);
43162306a36Sopenharmony_ci	}
43262306a36Sopenharmony_ci	entity->parent = bfqg->my_entity; /* NULL for root group */
43362306a36Sopenharmony_ci	entity->sched_data = &bfqg->sched_data;
43462306a36Sopenharmony_ci}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_cistatic void bfqg_stats_exit(struct bfqg_stats *stats)
43762306a36Sopenharmony_ci{
43862306a36Sopenharmony_ci	blkg_rwstat_exit(&stats->bytes);
43962306a36Sopenharmony_ci	blkg_rwstat_exit(&stats->ios);
44062306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG
44162306a36Sopenharmony_ci	blkg_rwstat_exit(&stats->merged);
44262306a36Sopenharmony_ci	blkg_rwstat_exit(&stats->service_time);
44362306a36Sopenharmony_ci	blkg_rwstat_exit(&stats->wait_time);
44462306a36Sopenharmony_ci	blkg_rwstat_exit(&stats->queued);
44562306a36Sopenharmony_ci	bfq_stat_exit(&stats->time);
44662306a36Sopenharmony_ci	bfq_stat_exit(&stats->avg_queue_size_sum);
44762306a36Sopenharmony_ci	bfq_stat_exit(&stats->avg_queue_size_samples);
44862306a36Sopenharmony_ci	bfq_stat_exit(&stats->dequeue);
44962306a36Sopenharmony_ci	bfq_stat_exit(&stats->group_wait_time);
45062306a36Sopenharmony_ci	bfq_stat_exit(&stats->idle_time);
45162306a36Sopenharmony_ci	bfq_stat_exit(&stats->empty_time);
45262306a36Sopenharmony_ci#endif
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic int bfqg_stats_init(struct bfqg_stats *stats, gfp_t gfp)
45662306a36Sopenharmony_ci{
45762306a36Sopenharmony_ci	if (blkg_rwstat_init(&stats->bytes, gfp) ||
45862306a36Sopenharmony_ci	    blkg_rwstat_init(&stats->ios, gfp))
45962306a36Sopenharmony_ci		goto error;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG
46262306a36Sopenharmony_ci	if (blkg_rwstat_init(&stats->merged, gfp) ||
46362306a36Sopenharmony_ci	    blkg_rwstat_init(&stats->service_time, gfp) ||
46462306a36Sopenharmony_ci	    blkg_rwstat_init(&stats->wait_time, gfp) ||
46562306a36Sopenharmony_ci	    blkg_rwstat_init(&stats->queued, gfp) ||
46662306a36Sopenharmony_ci	    bfq_stat_init(&stats->time, gfp) ||
46762306a36Sopenharmony_ci	    bfq_stat_init(&stats->avg_queue_size_sum, gfp) ||
46862306a36Sopenharmony_ci	    bfq_stat_init(&stats->avg_queue_size_samples, gfp) ||
46962306a36Sopenharmony_ci	    bfq_stat_init(&stats->dequeue, gfp) ||
47062306a36Sopenharmony_ci	    bfq_stat_init(&stats->group_wait_time, gfp) ||
47162306a36Sopenharmony_ci	    bfq_stat_init(&stats->idle_time, gfp) ||
47262306a36Sopenharmony_ci	    bfq_stat_init(&stats->empty_time, gfp))
47362306a36Sopenharmony_ci		goto error;
47462306a36Sopenharmony_ci#endif
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	return 0;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_cierror:
47962306a36Sopenharmony_ci	bfqg_stats_exit(stats);
48062306a36Sopenharmony_ci	return -ENOMEM;
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic struct bfq_group_data *cpd_to_bfqgd(struct blkcg_policy_data *cpd)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	return cpd ? container_of(cpd, struct bfq_group_data, pd) : NULL;
48662306a36Sopenharmony_ci}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_cistatic struct bfq_group_data *blkcg_to_bfqgd(struct blkcg *blkcg)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	return cpd_to_bfqgd(blkcg_to_cpd(blkcg, &blkcg_policy_bfq));
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic struct blkcg_policy_data *bfq_cpd_alloc(gfp_t gfp)
49462306a36Sopenharmony_ci{
49562306a36Sopenharmony_ci	struct bfq_group_data *bgd;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	bgd = kzalloc(sizeof(*bgd), gfp);
49862306a36Sopenharmony_ci	if (!bgd)
49962306a36Sopenharmony_ci		return NULL;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	bgd->weight = CGROUP_WEIGHT_DFL;
50262306a36Sopenharmony_ci	return &bgd->pd;
50362306a36Sopenharmony_ci}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_cistatic void bfq_cpd_free(struct blkcg_policy_data *cpd)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	kfree(cpd_to_bfqgd(cpd));
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_cistatic struct blkg_policy_data *bfq_pd_alloc(struct gendisk *disk,
51162306a36Sopenharmony_ci		struct blkcg *blkcg, gfp_t gfp)
51262306a36Sopenharmony_ci{
51362306a36Sopenharmony_ci	struct bfq_group *bfqg;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	bfqg = kzalloc_node(sizeof(*bfqg), gfp, disk->node_id);
51662306a36Sopenharmony_ci	if (!bfqg)
51762306a36Sopenharmony_ci		return NULL;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	if (bfqg_stats_init(&bfqg->stats, gfp)) {
52062306a36Sopenharmony_ci		kfree(bfqg);
52162306a36Sopenharmony_ci		return NULL;
52262306a36Sopenharmony_ci	}
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	/* see comments in bfq_bic_update_cgroup for why refcounting */
52562306a36Sopenharmony_ci	refcount_set(&bfqg->ref, 1);
52662306a36Sopenharmony_ci	return &bfqg->pd;
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_cistatic void bfq_pd_init(struct blkg_policy_data *pd)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	struct blkcg_gq *blkg = pd_to_blkg(pd);
53262306a36Sopenharmony_ci	struct bfq_group *bfqg = blkg_to_bfqg(blkg);
53362306a36Sopenharmony_ci	struct bfq_data *bfqd = blkg->q->elevator->elevator_data;
53462306a36Sopenharmony_ci	struct bfq_entity *entity = &bfqg->entity;
53562306a36Sopenharmony_ci	struct bfq_group_data *d = blkcg_to_bfqgd(blkg->blkcg);
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	entity->orig_weight = entity->weight = entity->new_weight = d->weight;
53862306a36Sopenharmony_ci	entity->my_sched_data = &bfqg->sched_data;
53962306a36Sopenharmony_ci	entity->last_bfqq_created = NULL;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	bfqg->my_entity = entity; /*
54262306a36Sopenharmony_ci				   * the root_group's will be set to NULL
54362306a36Sopenharmony_ci				   * in bfq_init_queue()
54462306a36Sopenharmony_ci				   */
54562306a36Sopenharmony_ci	bfqg->bfqd = bfqd;
54662306a36Sopenharmony_ci	bfqg->active_entities = 0;
54762306a36Sopenharmony_ci	bfqg->num_queues_with_pending_reqs = 0;
54862306a36Sopenharmony_ci	bfqg->rq_pos_tree = RB_ROOT;
54962306a36Sopenharmony_ci}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_cistatic void bfq_pd_free(struct blkg_policy_data *pd)
55262306a36Sopenharmony_ci{
55362306a36Sopenharmony_ci	struct bfq_group *bfqg = pd_to_bfqg(pd);
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	bfqg_stats_exit(&bfqg->stats);
55662306a36Sopenharmony_ci	bfqg_put(bfqg);
55762306a36Sopenharmony_ci}
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_cistatic void bfq_pd_reset_stats(struct blkg_policy_data *pd)
56062306a36Sopenharmony_ci{
56162306a36Sopenharmony_ci	struct bfq_group *bfqg = pd_to_bfqg(pd);
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	bfqg_stats_reset(&bfqg->stats);
56462306a36Sopenharmony_ci}
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_cistatic void bfq_group_set_parent(struct bfq_group *bfqg,
56762306a36Sopenharmony_ci					struct bfq_group *parent)
56862306a36Sopenharmony_ci{
56962306a36Sopenharmony_ci	struct bfq_entity *entity;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	entity = &bfqg->entity;
57262306a36Sopenharmony_ci	entity->parent = parent->my_entity;
57362306a36Sopenharmony_ci	entity->sched_data = &parent->sched_data;
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_cistatic void bfq_link_bfqg(struct bfq_data *bfqd, struct bfq_group *bfqg)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci	struct bfq_group *parent;
57962306a36Sopenharmony_ci	struct bfq_entity *entity;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	/*
58262306a36Sopenharmony_ci	 * Update chain of bfq_groups as we might be handling a leaf group
58362306a36Sopenharmony_ci	 * which, along with some of its relatives, has not been hooked yet
58462306a36Sopenharmony_ci	 * to the private hierarchy of BFQ.
58562306a36Sopenharmony_ci	 */
58662306a36Sopenharmony_ci	entity = &bfqg->entity;
58762306a36Sopenharmony_ci	for_each_entity(entity) {
58862306a36Sopenharmony_ci		struct bfq_group *curr_bfqg = container_of(entity,
58962306a36Sopenharmony_ci						struct bfq_group, entity);
59062306a36Sopenharmony_ci		if (curr_bfqg != bfqd->root_group) {
59162306a36Sopenharmony_ci			parent = bfqg_parent(curr_bfqg);
59262306a36Sopenharmony_ci			if (!parent)
59362306a36Sopenharmony_ci				parent = bfqd->root_group;
59462306a36Sopenharmony_ci			bfq_group_set_parent(curr_bfqg, parent);
59562306a36Sopenharmony_ci		}
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_cistruct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
60062306a36Sopenharmony_ci{
60162306a36Sopenharmony_ci	struct blkcg_gq *blkg = bio->bi_blkg;
60262306a36Sopenharmony_ci	struct bfq_group *bfqg;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	while (blkg) {
60562306a36Sopenharmony_ci		if (!blkg->online) {
60662306a36Sopenharmony_ci			blkg = blkg->parent;
60762306a36Sopenharmony_ci			continue;
60862306a36Sopenharmony_ci		}
60962306a36Sopenharmony_ci		bfqg = blkg_to_bfqg(blkg);
61062306a36Sopenharmony_ci		if (bfqg->pd.online) {
61162306a36Sopenharmony_ci			bio_associate_blkg_from_css(bio, &blkg->blkcg->css);
61262306a36Sopenharmony_ci			return bfqg;
61362306a36Sopenharmony_ci		}
61462306a36Sopenharmony_ci		blkg = blkg->parent;
61562306a36Sopenharmony_ci	}
61662306a36Sopenharmony_ci	bio_associate_blkg_from_css(bio,
61762306a36Sopenharmony_ci				&bfqg_to_blkg(bfqd->root_group)->blkcg->css);
61862306a36Sopenharmony_ci	return bfqd->root_group;
61962306a36Sopenharmony_ci}
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci/**
62262306a36Sopenharmony_ci * bfq_bfqq_move - migrate @bfqq to @bfqg.
62362306a36Sopenharmony_ci * @bfqd: queue descriptor.
62462306a36Sopenharmony_ci * @bfqq: the queue to move.
62562306a36Sopenharmony_ci * @bfqg: the group to move to.
62662306a36Sopenharmony_ci *
62762306a36Sopenharmony_ci * Move @bfqq to @bfqg, deactivating it from its old group and reactivating
62862306a36Sopenharmony_ci * it on the new one.  Avoid putting the entity on the old group idle tree.
62962306a36Sopenharmony_ci *
63062306a36Sopenharmony_ci * Must be called under the scheduler lock, to make sure that the blkg
63162306a36Sopenharmony_ci * owning @bfqg does not disappear (see comments in
63262306a36Sopenharmony_ci * bfq_bic_update_cgroup on guaranteeing the consistency of blkg
63362306a36Sopenharmony_ci * objects).
63462306a36Sopenharmony_ci */
63562306a36Sopenharmony_civoid bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
63662306a36Sopenharmony_ci		   struct bfq_group *bfqg)
63762306a36Sopenharmony_ci{
63862306a36Sopenharmony_ci	struct bfq_entity *entity = &bfqq->entity;
63962306a36Sopenharmony_ci	struct bfq_group *old_parent = bfqq_group(bfqq);
64062306a36Sopenharmony_ci	bool has_pending_reqs = false;
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	/*
64362306a36Sopenharmony_ci	 * No point to move bfqq to the same group, which can happen when
64462306a36Sopenharmony_ci	 * root group is offlined
64562306a36Sopenharmony_ci	 */
64662306a36Sopenharmony_ci	if (old_parent == bfqg)
64762306a36Sopenharmony_ci		return;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	/*
65062306a36Sopenharmony_ci	 * oom_bfqq is not allowed to move, oom_bfqq will hold ref to root_group
65162306a36Sopenharmony_ci	 * until elevator exit.
65262306a36Sopenharmony_ci	 */
65362306a36Sopenharmony_ci	if (bfqq == &bfqd->oom_bfqq)
65462306a36Sopenharmony_ci		return;
65562306a36Sopenharmony_ci	/*
65662306a36Sopenharmony_ci	 * Get extra reference to prevent bfqq from being freed in
65762306a36Sopenharmony_ci	 * next possible expire or deactivate.
65862306a36Sopenharmony_ci	 */
65962306a36Sopenharmony_ci	bfqq->ref++;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	if (entity->in_groups_with_pending_reqs) {
66262306a36Sopenharmony_ci		has_pending_reqs = true;
66362306a36Sopenharmony_ci		bfq_del_bfqq_in_groups_with_pending_reqs(bfqq);
66462306a36Sopenharmony_ci	}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	/* If bfqq is empty, then bfq_bfqq_expire also invokes
66762306a36Sopenharmony_ci	 * bfq_del_bfqq_busy, thereby removing bfqq and its entity
66862306a36Sopenharmony_ci	 * from data structures related to current group. Otherwise we
66962306a36Sopenharmony_ci	 * need to remove bfqq explicitly with bfq_deactivate_bfqq, as
67062306a36Sopenharmony_ci	 * we do below.
67162306a36Sopenharmony_ci	 */
67262306a36Sopenharmony_ci	if (bfqq == bfqd->in_service_queue)
67362306a36Sopenharmony_ci		bfq_bfqq_expire(bfqd, bfqd->in_service_queue,
67462306a36Sopenharmony_ci				false, BFQQE_PREEMPTED);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	if (bfq_bfqq_busy(bfqq))
67762306a36Sopenharmony_ci		bfq_deactivate_bfqq(bfqd, bfqq, false, false);
67862306a36Sopenharmony_ci	else if (entity->on_st_or_in_serv)
67962306a36Sopenharmony_ci		bfq_put_idle_entity(bfq_entity_service_tree(entity), entity);
68062306a36Sopenharmony_ci	bfqg_and_blkg_put(old_parent);
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	if (entity->parent &&
68362306a36Sopenharmony_ci	    entity->parent->last_bfqq_created == bfqq)
68462306a36Sopenharmony_ci		entity->parent->last_bfqq_created = NULL;
68562306a36Sopenharmony_ci	else if (bfqd->last_bfqq_created == bfqq)
68662306a36Sopenharmony_ci		bfqd->last_bfqq_created = NULL;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	entity->parent = bfqg->my_entity;
68962306a36Sopenharmony_ci	entity->sched_data = &bfqg->sched_data;
69062306a36Sopenharmony_ci	/* pin down bfqg and its associated blkg  */
69162306a36Sopenharmony_ci	bfqg_and_blkg_get(bfqg);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if (has_pending_reqs)
69462306a36Sopenharmony_ci		bfq_add_bfqq_in_groups_with_pending_reqs(bfqq);
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	if (bfq_bfqq_busy(bfqq)) {
69762306a36Sopenharmony_ci		if (unlikely(!bfqd->nonrot_with_queueing))
69862306a36Sopenharmony_ci			bfq_pos_tree_add_move(bfqd, bfqq);
69962306a36Sopenharmony_ci		bfq_activate_bfqq(bfqd, bfqq);
70062306a36Sopenharmony_ci	}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	if (!bfqd->in_service_queue && !bfqd->tot_rq_in_driver)
70362306a36Sopenharmony_ci		bfq_schedule_dispatch(bfqd);
70462306a36Sopenharmony_ci	/* release extra ref taken above, bfqq may happen to be freed now */
70562306a36Sopenharmony_ci	bfq_put_queue(bfqq);
70662306a36Sopenharmony_ci}
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_cistatic void bfq_sync_bfqq_move(struct bfq_data *bfqd,
70962306a36Sopenharmony_ci			       struct bfq_queue *sync_bfqq,
71062306a36Sopenharmony_ci			       struct bfq_io_cq *bic,
71162306a36Sopenharmony_ci			       struct bfq_group *bfqg,
71262306a36Sopenharmony_ci			       unsigned int act_idx)
71362306a36Sopenharmony_ci{
71462306a36Sopenharmony_ci	struct bfq_queue *bfqq;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	if (!sync_bfqq->new_bfqq && !bfq_bfqq_coop(sync_bfqq)) {
71762306a36Sopenharmony_ci		/* We are the only user of this bfqq, just move it */
71862306a36Sopenharmony_ci		if (sync_bfqq->entity.sched_data != &bfqg->sched_data)
71962306a36Sopenharmony_ci			bfq_bfqq_move(bfqd, sync_bfqq, bfqg);
72062306a36Sopenharmony_ci		return;
72162306a36Sopenharmony_ci	}
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci	/*
72462306a36Sopenharmony_ci	 * The queue was merged to a different queue. Check
72562306a36Sopenharmony_ci	 * that the merge chain still belongs to the same
72662306a36Sopenharmony_ci	 * cgroup.
72762306a36Sopenharmony_ci	 */
72862306a36Sopenharmony_ci	for (bfqq = sync_bfqq; bfqq; bfqq = bfqq->new_bfqq)
72962306a36Sopenharmony_ci		if (bfqq->entity.sched_data != &bfqg->sched_data)
73062306a36Sopenharmony_ci			break;
73162306a36Sopenharmony_ci	if (bfqq) {
73262306a36Sopenharmony_ci		/*
73362306a36Sopenharmony_ci		 * Some queue changed cgroup so the merge is not valid
73462306a36Sopenharmony_ci		 * anymore. We cannot easily just cancel the merge (by
73562306a36Sopenharmony_ci		 * clearing new_bfqq) as there may be other processes
73662306a36Sopenharmony_ci		 * using this queue and holding refs to all queues
73762306a36Sopenharmony_ci		 * below sync_bfqq->new_bfqq. Similarly if the merge
73862306a36Sopenharmony_ci		 * already happened, we need to detach from bfqq now
73962306a36Sopenharmony_ci		 * so that we cannot merge bio to a request from the
74062306a36Sopenharmony_ci		 * old cgroup.
74162306a36Sopenharmony_ci		 */
74262306a36Sopenharmony_ci		bfq_put_cooperator(sync_bfqq);
74362306a36Sopenharmony_ci		bic_set_bfqq(bic, NULL, true, act_idx);
74462306a36Sopenharmony_ci		bfq_release_process_ref(bfqd, sync_bfqq);
74562306a36Sopenharmony_ci	}
74662306a36Sopenharmony_ci}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci/**
74962306a36Sopenharmony_ci * __bfq_bic_change_cgroup - move @bic to @bfqg.
75062306a36Sopenharmony_ci * @bfqd: the queue descriptor.
75162306a36Sopenharmony_ci * @bic: the bic to move.
75262306a36Sopenharmony_ci * @bfqg: the group to move to.
75362306a36Sopenharmony_ci *
75462306a36Sopenharmony_ci * Move bic to blkcg, assuming that bfqd->lock is held; which makes
75562306a36Sopenharmony_ci * sure that the reference to cgroup is valid across the call (see
75662306a36Sopenharmony_ci * comments in bfq_bic_update_cgroup on this issue)
75762306a36Sopenharmony_ci */
75862306a36Sopenharmony_cistatic void __bfq_bic_change_cgroup(struct bfq_data *bfqd,
75962306a36Sopenharmony_ci				    struct bfq_io_cq *bic,
76062306a36Sopenharmony_ci				    struct bfq_group *bfqg)
76162306a36Sopenharmony_ci{
76262306a36Sopenharmony_ci	unsigned int act_idx;
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	for (act_idx = 0; act_idx < bfqd->num_actuators; act_idx++) {
76562306a36Sopenharmony_ci		struct bfq_queue *async_bfqq = bic_to_bfqq(bic, false, act_idx);
76662306a36Sopenharmony_ci		struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, true, act_idx);
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci		if (async_bfqq &&
76962306a36Sopenharmony_ci		    async_bfqq->entity.sched_data != &bfqg->sched_data) {
77062306a36Sopenharmony_ci			bic_set_bfqq(bic, NULL, false, act_idx);
77162306a36Sopenharmony_ci			bfq_release_process_ref(bfqd, async_bfqq);
77262306a36Sopenharmony_ci		}
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci		if (sync_bfqq)
77562306a36Sopenharmony_ci			bfq_sync_bfqq_move(bfqd, sync_bfqq, bic, bfqg, act_idx);
77662306a36Sopenharmony_ci	}
77762306a36Sopenharmony_ci}
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_civoid bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio)
78062306a36Sopenharmony_ci{
78162306a36Sopenharmony_ci	struct bfq_data *bfqd = bic_to_bfqd(bic);
78262306a36Sopenharmony_ci	struct bfq_group *bfqg = bfq_bio_bfqg(bfqd, bio);
78362306a36Sopenharmony_ci	uint64_t serial_nr;
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	serial_nr = bfqg_to_blkg(bfqg)->blkcg->css.serial_nr;
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	/*
78862306a36Sopenharmony_ci	 * Check whether blkcg has changed.  The condition may trigger
78962306a36Sopenharmony_ci	 * spuriously on a newly created cic but there's no harm.
79062306a36Sopenharmony_ci	 */
79162306a36Sopenharmony_ci	if (unlikely(!bfqd) || likely(bic->blkcg_serial_nr == serial_nr))
79262306a36Sopenharmony_ci		return;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	/*
79562306a36Sopenharmony_ci	 * New cgroup for this process. Make sure it is linked to bfq internal
79662306a36Sopenharmony_ci	 * cgroup hierarchy.
79762306a36Sopenharmony_ci	 */
79862306a36Sopenharmony_ci	bfq_link_bfqg(bfqd, bfqg);
79962306a36Sopenharmony_ci	__bfq_bic_change_cgroup(bfqd, bic, bfqg);
80062306a36Sopenharmony_ci	/*
80162306a36Sopenharmony_ci	 * Update blkg_path for bfq_log_* functions. We cache this
80262306a36Sopenharmony_ci	 * path, and update it here, for the following
80362306a36Sopenharmony_ci	 * reasons. Operations on blkg objects in blk-cgroup are
80462306a36Sopenharmony_ci	 * protected with the request_queue lock, and not with the
80562306a36Sopenharmony_ci	 * lock that protects the instances of this scheduler
80662306a36Sopenharmony_ci	 * (bfqd->lock). This exposes BFQ to the following sort of
80762306a36Sopenharmony_ci	 * race.
80862306a36Sopenharmony_ci	 *
80962306a36Sopenharmony_ci	 * The blkg_lookup performed in bfq_get_queue, protected
81062306a36Sopenharmony_ci	 * through rcu, may happen to return the address of a copy of
81162306a36Sopenharmony_ci	 * the original blkg. If this is the case, then the
81262306a36Sopenharmony_ci	 * bfqg_and_blkg_get performed in bfq_get_queue, to pin down
81362306a36Sopenharmony_ci	 * the blkg, is useless: it does not prevent blk-cgroup code
81462306a36Sopenharmony_ci	 * from destroying both the original blkg and all objects
81562306a36Sopenharmony_ci	 * directly or indirectly referred by the copy of the
81662306a36Sopenharmony_ci	 * blkg.
81762306a36Sopenharmony_ci	 *
81862306a36Sopenharmony_ci	 * On the bright side, destroy operations on a blkg invoke, as
81962306a36Sopenharmony_ci	 * a first step, hooks of the scheduler associated with the
82062306a36Sopenharmony_ci	 * blkg. And these hooks are executed with bfqd->lock held for
82162306a36Sopenharmony_ci	 * BFQ. As a consequence, for any blkg associated with the
82262306a36Sopenharmony_ci	 * request queue this instance of the scheduler is attached
82362306a36Sopenharmony_ci	 * to, we are guaranteed that such a blkg is not destroyed, and
82462306a36Sopenharmony_ci	 * that all the pointers it contains are consistent, while we
82562306a36Sopenharmony_ci	 * are holding bfqd->lock. A blkg_lookup performed with
82662306a36Sopenharmony_ci	 * bfqd->lock held then returns a fully consistent blkg, which
82762306a36Sopenharmony_ci	 * remains consistent until this lock is held.
82862306a36Sopenharmony_ci	 *
82962306a36Sopenharmony_ci	 * Thanks to the last fact, and to the fact that: (1) bfqg has
83062306a36Sopenharmony_ci	 * been obtained through a blkg_lookup in the above
83162306a36Sopenharmony_ci	 * assignment, and (2) bfqd->lock is being held, here we can
83262306a36Sopenharmony_ci	 * safely use the policy data for the involved blkg (i.e., the
83362306a36Sopenharmony_ci	 * field bfqg->pd) to get to the blkg associated with bfqg,
83462306a36Sopenharmony_ci	 * and then we can safely use any field of blkg. After we
83562306a36Sopenharmony_ci	 * release bfqd->lock, even just getting blkg through this
83662306a36Sopenharmony_ci	 * bfqg may cause dangling references to be traversed, as
83762306a36Sopenharmony_ci	 * bfqg->pd may not exist any more.
83862306a36Sopenharmony_ci	 *
83962306a36Sopenharmony_ci	 * In view of the above facts, here we cache, in the bfqg, any
84062306a36Sopenharmony_ci	 * blkg data we may need for this bic, and for its associated
84162306a36Sopenharmony_ci	 * bfq_queue. As of now, we need to cache only the path of the
84262306a36Sopenharmony_ci	 * blkg, which is used in the bfq_log_* functions.
84362306a36Sopenharmony_ci	 *
84462306a36Sopenharmony_ci	 * Finally, note that bfqg itself needs to be protected from
84562306a36Sopenharmony_ci	 * destruction on the blkg_free of the original blkg (which
84662306a36Sopenharmony_ci	 * invokes bfq_pd_free). We use an additional private
84762306a36Sopenharmony_ci	 * refcounter for bfqg, to let it disappear only after no
84862306a36Sopenharmony_ci	 * bfq_queue refers to it any longer.
84962306a36Sopenharmony_ci	 */
85062306a36Sopenharmony_ci	blkg_path(bfqg_to_blkg(bfqg), bfqg->blkg_path, sizeof(bfqg->blkg_path));
85162306a36Sopenharmony_ci	bic->blkcg_serial_nr = serial_nr;
85262306a36Sopenharmony_ci}
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci/**
85562306a36Sopenharmony_ci * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st.
85662306a36Sopenharmony_ci * @st: the service tree being flushed.
85762306a36Sopenharmony_ci */
85862306a36Sopenharmony_cistatic void bfq_flush_idle_tree(struct bfq_service_tree *st)
85962306a36Sopenharmony_ci{
86062306a36Sopenharmony_ci	struct bfq_entity *entity = st->first_idle;
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	for (; entity ; entity = st->first_idle)
86362306a36Sopenharmony_ci		__bfq_deactivate_entity(entity, false);
86462306a36Sopenharmony_ci}
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci/**
86762306a36Sopenharmony_ci * bfq_reparent_leaf_entity - move leaf entity to the root_group.
86862306a36Sopenharmony_ci * @bfqd: the device data structure with the root group.
86962306a36Sopenharmony_ci * @entity: the entity to move, if entity is a leaf; or the parent entity
87062306a36Sopenharmony_ci *	    of an active leaf entity to move, if entity is not a leaf.
87162306a36Sopenharmony_ci * @ioprio_class: I/O priority class to reparent.
87262306a36Sopenharmony_ci */
87362306a36Sopenharmony_cistatic void bfq_reparent_leaf_entity(struct bfq_data *bfqd,
87462306a36Sopenharmony_ci				     struct bfq_entity *entity,
87562306a36Sopenharmony_ci				     int ioprio_class)
87662306a36Sopenharmony_ci{
87762306a36Sopenharmony_ci	struct bfq_queue *bfqq;
87862306a36Sopenharmony_ci	struct bfq_entity *child_entity = entity;
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	while (child_entity->my_sched_data) { /* leaf not reached yet */
88162306a36Sopenharmony_ci		struct bfq_sched_data *child_sd = child_entity->my_sched_data;
88262306a36Sopenharmony_ci		struct bfq_service_tree *child_st = child_sd->service_tree +
88362306a36Sopenharmony_ci			ioprio_class;
88462306a36Sopenharmony_ci		struct rb_root *child_active = &child_st->active;
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci		child_entity = bfq_entity_of(rb_first(child_active));
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci		if (!child_entity)
88962306a36Sopenharmony_ci			child_entity = child_sd->in_service_entity;
89062306a36Sopenharmony_ci	}
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	bfqq = bfq_entity_to_bfqq(child_entity);
89362306a36Sopenharmony_ci	bfq_bfqq_move(bfqd, bfqq, bfqd->root_group);
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci/**
89762306a36Sopenharmony_ci * bfq_reparent_active_queues - move to the root group all active queues.
89862306a36Sopenharmony_ci * @bfqd: the device data structure with the root group.
89962306a36Sopenharmony_ci * @bfqg: the group to move from.
90062306a36Sopenharmony_ci * @st: the service tree to start the search from.
90162306a36Sopenharmony_ci * @ioprio_class: I/O priority class to reparent.
90262306a36Sopenharmony_ci */
90362306a36Sopenharmony_cistatic void bfq_reparent_active_queues(struct bfq_data *bfqd,
90462306a36Sopenharmony_ci				       struct bfq_group *bfqg,
90562306a36Sopenharmony_ci				       struct bfq_service_tree *st,
90662306a36Sopenharmony_ci				       int ioprio_class)
90762306a36Sopenharmony_ci{
90862306a36Sopenharmony_ci	struct rb_root *active = &st->active;
90962306a36Sopenharmony_ci	struct bfq_entity *entity;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	while ((entity = bfq_entity_of(rb_first(active))))
91262306a36Sopenharmony_ci		bfq_reparent_leaf_entity(bfqd, entity, ioprio_class);
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	if (bfqg->sched_data.in_service_entity)
91562306a36Sopenharmony_ci		bfq_reparent_leaf_entity(bfqd,
91662306a36Sopenharmony_ci					 bfqg->sched_data.in_service_entity,
91762306a36Sopenharmony_ci					 ioprio_class);
91862306a36Sopenharmony_ci}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci/**
92162306a36Sopenharmony_ci * bfq_pd_offline - deactivate the entity associated with @pd,
92262306a36Sopenharmony_ci *		    and reparent its children entities.
92362306a36Sopenharmony_ci * @pd: descriptor of the policy going offline.
92462306a36Sopenharmony_ci *
92562306a36Sopenharmony_ci * blkio already grabs the queue_lock for us, so no need to use
92662306a36Sopenharmony_ci * RCU-based magic
92762306a36Sopenharmony_ci */
92862306a36Sopenharmony_cistatic void bfq_pd_offline(struct blkg_policy_data *pd)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	struct bfq_service_tree *st;
93162306a36Sopenharmony_ci	struct bfq_group *bfqg = pd_to_bfqg(pd);
93262306a36Sopenharmony_ci	struct bfq_data *bfqd = bfqg->bfqd;
93362306a36Sopenharmony_ci	struct bfq_entity *entity = bfqg->my_entity;
93462306a36Sopenharmony_ci	unsigned long flags;
93562306a36Sopenharmony_ci	int i;
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	spin_lock_irqsave(&bfqd->lock, flags);
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	if (!entity) /* root group */
94062306a36Sopenharmony_ci		goto put_async_queues;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	/*
94362306a36Sopenharmony_ci	 * Empty all service_trees belonging to this group before
94462306a36Sopenharmony_ci	 * deactivating the group itself.
94562306a36Sopenharmony_ci	 */
94662306a36Sopenharmony_ci	for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) {
94762306a36Sopenharmony_ci		st = bfqg->sched_data.service_tree + i;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci		/*
95062306a36Sopenharmony_ci		 * It may happen that some queues are still active
95162306a36Sopenharmony_ci		 * (busy) upon group destruction (if the corresponding
95262306a36Sopenharmony_ci		 * processes have been forced to terminate). We move
95362306a36Sopenharmony_ci		 * all the leaf entities corresponding to these queues
95462306a36Sopenharmony_ci		 * to the root_group.
95562306a36Sopenharmony_ci		 * Also, it may happen that the group has an entity
95662306a36Sopenharmony_ci		 * in service, which is disconnected from the active
95762306a36Sopenharmony_ci		 * tree: it must be moved, too.
95862306a36Sopenharmony_ci		 * There is no need to put the sync queues, as the
95962306a36Sopenharmony_ci		 * scheduler has taken no reference.
96062306a36Sopenharmony_ci		 */
96162306a36Sopenharmony_ci		bfq_reparent_active_queues(bfqd, bfqg, st, i);
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci		/*
96462306a36Sopenharmony_ci		 * The idle tree may still contain bfq_queues
96562306a36Sopenharmony_ci		 * belonging to exited task because they never
96662306a36Sopenharmony_ci		 * migrated to a different cgroup from the one being
96762306a36Sopenharmony_ci		 * destroyed now. In addition, even
96862306a36Sopenharmony_ci		 * bfq_reparent_active_queues() may happen to add some
96962306a36Sopenharmony_ci		 * entities to the idle tree. It happens if, in some
97062306a36Sopenharmony_ci		 * of the calls to bfq_bfqq_move() performed by
97162306a36Sopenharmony_ci		 * bfq_reparent_active_queues(), the queue to move is
97262306a36Sopenharmony_ci		 * empty and gets expired.
97362306a36Sopenharmony_ci		 */
97462306a36Sopenharmony_ci		bfq_flush_idle_tree(st);
97562306a36Sopenharmony_ci	}
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	__bfq_deactivate_entity(entity, false);
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ciput_async_queues:
98062306a36Sopenharmony_ci	bfq_put_async_queues(bfqd, bfqg);
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	spin_unlock_irqrestore(&bfqd->lock, flags);
98362306a36Sopenharmony_ci	/*
98462306a36Sopenharmony_ci	 * @blkg is going offline and will be ignored by
98562306a36Sopenharmony_ci	 * blkg_[rw]stat_recursive_sum().  Transfer stats to the parent so
98662306a36Sopenharmony_ci	 * that they don't get lost.  If IOs complete after this point, the
98762306a36Sopenharmony_ci	 * stats for them will be lost.  Oh well...
98862306a36Sopenharmony_ci	 */
98962306a36Sopenharmony_ci	bfqg_stats_xfer_dead(bfqg);
99062306a36Sopenharmony_ci}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_civoid bfq_end_wr_async(struct bfq_data *bfqd)
99362306a36Sopenharmony_ci{
99462306a36Sopenharmony_ci	struct blkcg_gq *blkg;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	list_for_each_entry(blkg, &bfqd->queue->blkg_list, q_node) {
99762306a36Sopenharmony_ci		struct bfq_group *bfqg = blkg_to_bfqg(blkg);
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci		bfq_end_wr_async_queues(bfqd, bfqg);
100062306a36Sopenharmony_ci	}
100162306a36Sopenharmony_ci	bfq_end_wr_async_queues(bfqd, bfqd->root_group);
100262306a36Sopenharmony_ci}
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_cistatic int bfq_io_show_weight_legacy(struct seq_file *sf, void *v)
100562306a36Sopenharmony_ci{
100662306a36Sopenharmony_ci	struct blkcg *blkcg = css_to_blkcg(seq_css(sf));
100762306a36Sopenharmony_ci	struct bfq_group_data *bfqgd = blkcg_to_bfqgd(blkcg);
100862306a36Sopenharmony_ci	unsigned int val = 0;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	if (bfqgd)
101162306a36Sopenharmony_ci		val = bfqgd->weight;
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	seq_printf(sf, "%u\n", val);
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	return 0;
101662306a36Sopenharmony_ci}
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_cistatic u64 bfqg_prfill_weight_device(struct seq_file *sf,
101962306a36Sopenharmony_ci				     struct blkg_policy_data *pd, int off)
102062306a36Sopenharmony_ci{
102162306a36Sopenharmony_ci	struct bfq_group *bfqg = pd_to_bfqg(pd);
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	if (!bfqg->entity.dev_weight)
102462306a36Sopenharmony_ci		return 0;
102562306a36Sopenharmony_ci	return __blkg_prfill_u64(sf, pd, bfqg->entity.dev_weight);
102662306a36Sopenharmony_ci}
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_cistatic int bfq_io_show_weight(struct seq_file *sf, void *v)
102962306a36Sopenharmony_ci{
103062306a36Sopenharmony_ci	struct blkcg *blkcg = css_to_blkcg(seq_css(sf));
103162306a36Sopenharmony_ci	struct bfq_group_data *bfqgd = blkcg_to_bfqgd(blkcg);
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	seq_printf(sf, "default %u\n", bfqgd->weight);
103462306a36Sopenharmony_ci	blkcg_print_blkgs(sf, blkcg, bfqg_prfill_weight_device,
103562306a36Sopenharmony_ci			  &blkcg_policy_bfq, 0, false);
103662306a36Sopenharmony_ci	return 0;
103762306a36Sopenharmony_ci}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_cistatic void bfq_group_set_weight(struct bfq_group *bfqg, u64 weight, u64 dev_weight)
104062306a36Sopenharmony_ci{
104162306a36Sopenharmony_ci	weight = dev_weight ?: weight;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	bfqg->entity.dev_weight = dev_weight;
104462306a36Sopenharmony_ci	/*
104562306a36Sopenharmony_ci	 * Setting the prio_changed flag of the entity
104662306a36Sopenharmony_ci	 * to 1 with new_weight == weight would re-set
104762306a36Sopenharmony_ci	 * the value of the weight to its ioprio mapping.
104862306a36Sopenharmony_ci	 * Set the flag only if necessary.
104962306a36Sopenharmony_ci	 */
105062306a36Sopenharmony_ci	if ((unsigned short)weight != bfqg->entity.new_weight) {
105162306a36Sopenharmony_ci		bfqg->entity.new_weight = (unsigned short)weight;
105262306a36Sopenharmony_ci		/*
105362306a36Sopenharmony_ci		 * Make sure that the above new value has been
105462306a36Sopenharmony_ci		 * stored in bfqg->entity.new_weight before
105562306a36Sopenharmony_ci		 * setting the prio_changed flag. In fact,
105662306a36Sopenharmony_ci		 * this flag may be read asynchronously (in
105762306a36Sopenharmony_ci		 * critical sections protected by a different
105862306a36Sopenharmony_ci		 * lock than that held here), and finding this
105962306a36Sopenharmony_ci		 * flag set may cause the execution of the code
106062306a36Sopenharmony_ci		 * for updating parameters whose value may
106162306a36Sopenharmony_ci		 * depend also on bfqg->entity.new_weight (in
106262306a36Sopenharmony_ci		 * __bfq_entity_update_weight_prio).
106362306a36Sopenharmony_ci		 * This barrier makes sure that the new value
106462306a36Sopenharmony_ci		 * of bfqg->entity.new_weight is correctly
106562306a36Sopenharmony_ci		 * seen in that code.
106662306a36Sopenharmony_ci		 */
106762306a36Sopenharmony_ci		smp_wmb();
106862306a36Sopenharmony_ci		bfqg->entity.prio_changed = 1;
106962306a36Sopenharmony_ci	}
107062306a36Sopenharmony_ci}
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_cistatic int bfq_io_set_weight_legacy(struct cgroup_subsys_state *css,
107362306a36Sopenharmony_ci				    struct cftype *cftype,
107462306a36Sopenharmony_ci				    u64 val)
107562306a36Sopenharmony_ci{
107662306a36Sopenharmony_ci	struct blkcg *blkcg = css_to_blkcg(css);
107762306a36Sopenharmony_ci	struct bfq_group_data *bfqgd = blkcg_to_bfqgd(blkcg);
107862306a36Sopenharmony_ci	struct blkcg_gq *blkg;
107962306a36Sopenharmony_ci	int ret = -ERANGE;
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	if (val < BFQ_MIN_WEIGHT || val > BFQ_MAX_WEIGHT)
108262306a36Sopenharmony_ci		return ret;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	ret = 0;
108562306a36Sopenharmony_ci	spin_lock_irq(&blkcg->lock);
108662306a36Sopenharmony_ci	bfqgd->weight = (unsigned short)val;
108762306a36Sopenharmony_ci	hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
108862306a36Sopenharmony_ci		struct bfq_group *bfqg = blkg_to_bfqg(blkg);
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci		if (bfqg)
109162306a36Sopenharmony_ci			bfq_group_set_weight(bfqg, val, 0);
109262306a36Sopenharmony_ci	}
109362306a36Sopenharmony_ci	spin_unlock_irq(&blkcg->lock);
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	return ret;
109662306a36Sopenharmony_ci}
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_cistatic ssize_t bfq_io_set_device_weight(struct kernfs_open_file *of,
109962306a36Sopenharmony_ci					char *buf, size_t nbytes,
110062306a36Sopenharmony_ci					loff_t off)
110162306a36Sopenharmony_ci{
110262306a36Sopenharmony_ci	int ret;
110362306a36Sopenharmony_ci	struct blkg_conf_ctx ctx;
110462306a36Sopenharmony_ci	struct blkcg *blkcg = css_to_blkcg(of_css(of));
110562306a36Sopenharmony_ci	struct bfq_group *bfqg;
110662306a36Sopenharmony_ci	u64 v;
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	blkg_conf_init(&ctx, buf);
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	ret = blkg_conf_prep(blkcg, &blkcg_policy_bfq, &ctx);
111162306a36Sopenharmony_ci	if (ret)
111262306a36Sopenharmony_ci		goto out;
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	if (sscanf(ctx.body, "%llu", &v) == 1) {
111562306a36Sopenharmony_ci		/* require "default" on dfl */
111662306a36Sopenharmony_ci		ret = -ERANGE;
111762306a36Sopenharmony_ci		if (!v)
111862306a36Sopenharmony_ci			goto out;
111962306a36Sopenharmony_ci	} else if (!strcmp(strim(ctx.body), "default")) {
112062306a36Sopenharmony_ci		v = 0;
112162306a36Sopenharmony_ci	} else {
112262306a36Sopenharmony_ci		ret = -EINVAL;
112362306a36Sopenharmony_ci		goto out;
112462306a36Sopenharmony_ci	}
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	bfqg = blkg_to_bfqg(ctx.blkg);
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	ret = -ERANGE;
112962306a36Sopenharmony_ci	if (!v || (v >= BFQ_MIN_WEIGHT && v <= BFQ_MAX_WEIGHT)) {
113062306a36Sopenharmony_ci		bfq_group_set_weight(bfqg, bfqg->entity.weight, v);
113162306a36Sopenharmony_ci		ret = 0;
113262306a36Sopenharmony_ci	}
113362306a36Sopenharmony_ciout:
113462306a36Sopenharmony_ci	blkg_conf_exit(&ctx);
113562306a36Sopenharmony_ci	return ret ?: nbytes;
113662306a36Sopenharmony_ci}
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_cistatic ssize_t bfq_io_set_weight(struct kernfs_open_file *of,
113962306a36Sopenharmony_ci				 char *buf, size_t nbytes,
114062306a36Sopenharmony_ci				 loff_t off)
114162306a36Sopenharmony_ci{
114262306a36Sopenharmony_ci	char *endp;
114362306a36Sopenharmony_ci	int ret;
114462306a36Sopenharmony_ci	u64 v;
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	buf = strim(buf);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	/* "WEIGHT" or "default WEIGHT" sets the default weight */
114962306a36Sopenharmony_ci	v = simple_strtoull(buf, &endp, 0);
115062306a36Sopenharmony_ci	if (*endp == '\0' || sscanf(buf, "default %llu", &v) == 1) {
115162306a36Sopenharmony_ci		ret = bfq_io_set_weight_legacy(of_css(of), NULL, v);
115262306a36Sopenharmony_ci		return ret ?: nbytes;
115362306a36Sopenharmony_ci	}
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	return bfq_io_set_device_weight(of, buf, nbytes, off);
115662306a36Sopenharmony_ci}
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_cistatic int bfqg_print_rwstat(struct seq_file *sf, void *v)
115962306a36Sopenharmony_ci{
116062306a36Sopenharmony_ci	blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), blkg_prfill_rwstat,
116162306a36Sopenharmony_ci			  &blkcg_policy_bfq, seq_cft(sf)->private, true);
116262306a36Sopenharmony_ci	return 0;
116362306a36Sopenharmony_ci}
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_cistatic u64 bfqg_prfill_rwstat_recursive(struct seq_file *sf,
116662306a36Sopenharmony_ci					struct blkg_policy_data *pd, int off)
116762306a36Sopenharmony_ci{
116862306a36Sopenharmony_ci	struct blkg_rwstat_sample sum;
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	blkg_rwstat_recursive_sum(pd_to_blkg(pd), &blkcg_policy_bfq, off, &sum);
117162306a36Sopenharmony_ci	return __blkg_prfill_rwstat(sf, pd, &sum);
117262306a36Sopenharmony_ci}
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_cistatic int bfqg_print_rwstat_recursive(struct seq_file *sf, void *v)
117562306a36Sopenharmony_ci{
117662306a36Sopenharmony_ci	blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
117762306a36Sopenharmony_ci			  bfqg_prfill_rwstat_recursive, &blkcg_policy_bfq,
117862306a36Sopenharmony_ci			  seq_cft(sf)->private, true);
117962306a36Sopenharmony_ci	return 0;
118062306a36Sopenharmony_ci}
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG
118362306a36Sopenharmony_cistatic int bfqg_print_stat(struct seq_file *sf, void *v)
118462306a36Sopenharmony_ci{
118562306a36Sopenharmony_ci	blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), blkg_prfill_stat,
118662306a36Sopenharmony_ci			  &blkcg_policy_bfq, seq_cft(sf)->private, false);
118762306a36Sopenharmony_ci	return 0;
118862306a36Sopenharmony_ci}
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_cistatic u64 bfqg_prfill_stat_recursive(struct seq_file *sf,
119162306a36Sopenharmony_ci				      struct blkg_policy_data *pd, int off)
119262306a36Sopenharmony_ci{
119362306a36Sopenharmony_ci	struct blkcg_gq *blkg = pd_to_blkg(pd);
119462306a36Sopenharmony_ci	struct blkcg_gq *pos_blkg;
119562306a36Sopenharmony_ci	struct cgroup_subsys_state *pos_css;
119662306a36Sopenharmony_ci	u64 sum = 0;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	lockdep_assert_held(&blkg->q->queue_lock);
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	rcu_read_lock();
120162306a36Sopenharmony_ci	blkg_for_each_descendant_pre(pos_blkg, pos_css, blkg) {
120262306a36Sopenharmony_ci		struct bfq_stat *stat;
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci		if (!pos_blkg->online)
120562306a36Sopenharmony_ci			continue;
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci		stat = (void *)blkg_to_pd(pos_blkg, &blkcg_policy_bfq) + off;
120862306a36Sopenharmony_ci		sum += bfq_stat_read(stat) + atomic64_read(&stat->aux_cnt);
120962306a36Sopenharmony_ci	}
121062306a36Sopenharmony_ci	rcu_read_unlock();
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	return __blkg_prfill_u64(sf, pd, sum);
121362306a36Sopenharmony_ci}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_cistatic int bfqg_print_stat_recursive(struct seq_file *sf, void *v)
121662306a36Sopenharmony_ci{
121762306a36Sopenharmony_ci	blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
121862306a36Sopenharmony_ci			  bfqg_prfill_stat_recursive, &blkcg_policy_bfq,
121962306a36Sopenharmony_ci			  seq_cft(sf)->private, false);
122062306a36Sopenharmony_ci	return 0;
122162306a36Sopenharmony_ci}
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_cistatic u64 bfqg_prfill_sectors(struct seq_file *sf, struct blkg_policy_data *pd,
122462306a36Sopenharmony_ci			       int off)
122562306a36Sopenharmony_ci{
122662306a36Sopenharmony_ci	struct bfq_group *bfqg = blkg_to_bfqg(pd->blkg);
122762306a36Sopenharmony_ci	u64 sum = blkg_rwstat_total(&bfqg->stats.bytes);
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	return __blkg_prfill_u64(sf, pd, sum >> 9);
123062306a36Sopenharmony_ci}
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_cistatic int bfqg_print_stat_sectors(struct seq_file *sf, void *v)
123362306a36Sopenharmony_ci{
123462306a36Sopenharmony_ci	blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
123562306a36Sopenharmony_ci			  bfqg_prfill_sectors, &blkcg_policy_bfq, 0, false);
123662306a36Sopenharmony_ci	return 0;
123762306a36Sopenharmony_ci}
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_cistatic u64 bfqg_prfill_sectors_recursive(struct seq_file *sf,
124062306a36Sopenharmony_ci					 struct blkg_policy_data *pd, int off)
124162306a36Sopenharmony_ci{
124262306a36Sopenharmony_ci	struct blkg_rwstat_sample tmp;
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	blkg_rwstat_recursive_sum(pd->blkg, &blkcg_policy_bfq,
124562306a36Sopenharmony_ci			offsetof(struct bfq_group, stats.bytes), &tmp);
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	return __blkg_prfill_u64(sf, pd,
124862306a36Sopenharmony_ci		(tmp.cnt[BLKG_RWSTAT_READ] + tmp.cnt[BLKG_RWSTAT_WRITE]) >> 9);
124962306a36Sopenharmony_ci}
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_cistatic int bfqg_print_stat_sectors_recursive(struct seq_file *sf, void *v)
125262306a36Sopenharmony_ci{
125362306a36Sopenharmony_ci	blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
125462306a36Sopenharmony_ci			  bfqg_prfill_sectors_recursive, &blkcg_policy_bfq, 0,
125562306a36Sopenharmony_ci			  false);
125662306a36Sopenharmony_ci	return 0;
125762306a36Sopenharmony_ci}
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_cistatic u64 bfqg_prfill_avg_queue_size(struct seq_file *sf,
126062306a36Sopenharmony_ci				      struct blkg_policy_data *pd, int off)
126162306a36Sopenharmony_ci{
126262306a36Sopenharmony_ci	struct bfq_group *bfqg = pd_to_bfqg(pd);
126362306a36Sopenharmony_ci	u64 samples = bfq_stat_read(&bfqg->stats.avg_queue_size_samples);
126462306a36Sopenharmony_ci	u64 v = 0;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	if (samples) {
126762306a36Sopenharmony_ci		v = bfq_stat_read(&bfqg->stats.avg_queue_size_sum);
126862306a36Sopenharmony_ci		v = div64_u64(v, samples);
126962306a36Sopenharmony_ci	}
127062306a36Sopenharmony_ci	__blkg_prfill_u64(sf, pd, v);
127162306a36Sopenharmony_ci	return 0;
127262306a36Sopenharmony_ci}
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci/* print avg_queue_size */
127562306a36Sopenharmony_cistatic int bfqg_print_avg_queue_size(struct seq_file *sf, void *v)
127662306a36Sopenharmony_ci{
127762306a36Sopenharmony_ci	blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
127862306a36Sopenharmony_ci			  bfqg_prfill_avg_queue_size, &blkcg_policy_bfq,
127962306a36Sopenharmony_ci			  0, false);
128062306a36Sopenharmony_ci	return 0;
128162306a36Sopenharmony_ci}
128262306a36Sopenharmony_ci#endif /* CONFIG_BFQ_CGROUP_DEBUG */
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_cistruct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node)
128562306a36Sopenharmony_ci{
128662306a36Sopenharmony_ci	int ret;
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	ret = blkcg_activate_policy(bfqd->queue->disk, &blkcg_policy_bfq);
128962306a36Sopenharmony_ci	if (ret)
129062306a36Sopenharmony_ci		return NULL;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	return blkg_to_bfqg(bfqd->queue->root_blkg);
129362306a36Sopenharmony_ci}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_cistruct blkcg_policy blkcg_policy_bfq = {
129662306a36Sopenharmony_ci	.dfl_cftypes		= bfq_blkg_files,
129762306a36Sopenharmony_ci	.legacy_cftypes		= bfq_blkcg_legacy_files,
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	.cpd_alloc_fn		= bfq_cpd_alloc,
130062306a36Sopenharmony_ci	.cpd_free_fn		= bfq_cpd_free,
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	.pd_alloc_fn		= bfq_pd_alloc,
130362306a36Sopenharmony_ci	.pd_init_fn		= bfq_pd_init,
130462306a36Sopenharmony_ci	.pd_offline_fn		= bfq_pd_offline,
130562306a36Sopenharmony_ci	.pd_free_fn		= bfq_pd_free,
130662306a36Sopenharmony_ci	.pd_reset_stats_fn	= bfq_pd_reset_stats,
130762306a36Sopenharmony_ci};
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_cistruct cftype bfq_blkcg_legacy_files[] = {
131062306a36Sopenharmony_ci	{
131162306a36Sopenharmony_ci		.name = "bfq.weight",
131262306a36Sopenharmony_ci		.flags = CFTYPE_NOT_ON_ROOT,
131362306a36Sopenharmony_ci		.seq_show = bfq_io_show_weight_legacy,
131462306a36Sopenharmony_ci		.write_u64 = bfq_io_set_weight_legacy,
131562306a36Sopenharmony_ci	},
131662306a36Sopenharmony_ci	{
131762306a36Sopenharmony_ci		.name = "bfq.weight_device",
131862306a36Sopenharmony_ci		.flags = CFTYPE_NOT_ON_ROOT,
131962306a36Sopenharmony_ci		.seq_show = bfq_io_show_weight,
132062306a36Sopenharmony_ci		.write = bfq_io_set_weight,
132162306a36Sopenharmony_ci	},
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	/* statistics, covers only the tasks in the bfqg */
132462306a36Sopenharmony_ci	{
132562306a36Sopenharmony_ci		.name = "bfq.io_service_bytes",
132662306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.bytes),
132762306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat,
132862306a36Sopenharmony_ci	},
132962306a36Sopenharmony_ci	{
133062306a36Sopenharmony_ci		.name = "bfq.io_serviced",
133162306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.ios),
133262306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat,
133362306a36Sopenharmony_ci	},
133462306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG
133562306a36Sopenharmony_ci	{
133662306a36Sopenharmony_ci		.name = "bfq.time",
133762306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.time),
133862306a36Sopenharmony_ci		.seq_show = bfqg_print_stat,
133962306a36Sopenharmony_ci	},
134062306a36Sopenharmony_ci	{
134162306a36Sopenharmony_ci		.name = "bfq.sectors",
134262306a36Sopenharmony_ci		.seq_show = bfqg_print_stat_sectors,
134362306a36Sopenharmony_ci	},
134462306a36Sopenharmony_ci	{
134562306a36Sopenharmony_ci		.name = "bfq.io_service_time",
134662306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.service_time),
134762306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat,
134862306a36Sopenharmony_ci	},
134962306a36Sopenharmony_ci	{
135062306a36Sopenharmony_ci		.name = "bfq.io_wait_time",
135162306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.wait_time),
135262306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat,
135362306a36Sopenharmony_ci	},
135462306a36Sopenharmony_ci	{
135562306a36Sopenharmony_ci		.name = "bfq.io_merged",
135662306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.merged),
135762306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat,
135862306a36Sopenharmony_ci	},
135962306a36Sopenharmony_ci	{
136062306a36Sopenharmony_ci		.name = "bfq.io_queued",
136162306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.queued),
136262306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat,
136362306a36Sopenharmony_ci	},
136462306a36Sopenharmony_ci#endif /* CONFIG_BFQ_CGROUP_DEBUG */
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci	/* the same statistics which cover the bfqg and its descendants */
136762306a36Sopenharmony_ci	{
136862306a36Sopenharmony_ci		.name = "bfq.io_service_bytes_recursive",
136962306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.bytes),
137062306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat_recursive,
137162306a36Sopenharmony_ci	},
137262306a36Sopenharmony_ci	{
137362306a36Sopenharmony_ci		.name = "bfq.io_serviced_recursive",
137462306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.ios),
137562306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat_recursive,
137662306a36Sopenharmony_ci	},
137762306a36Sopenharmony_ci#ifdef CONFIG_BFQ_CGROUP_DEBUG
137862306a36Sopenharmony_ci	{
137962306a36Sopenharmony_ci		.name = "bfq.time_recursive",
138062306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.time),
138162306a36Sopenharmony_ci		.seq_show = bfqg_print_stat_recursive,
138262306a36Sopenharmony_ci	},
138362306a36Sopenharmony_ci	{
138462306a36Sopenharmony_ci		.name = "bfq.sectors_recursive",
138562306a36Sopenharmony_ci		.seq_show = bfqg_print_stat_sectors_recursive,
138662306a36Sopenharmony_ci	},
138762306a36Sopenharmony_ci	{
138862306a36Sopenharmony_ci		.name = "bfq.io_service_time_recursive",
138962306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.service_time),
139062306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat_recursive,
139162306a36Sopenharmony_ci	},
139262306a36Sopenharmony_ci	{
139362306a36Sopenharmony_ci		.name = "bfq.io_wait_time_recursive",
139462306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.wait_time),
139562306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat_recursive,
139662306a36Sopenharmony_ci	},
139762306a36Sopenharmony_ci	{
139862306a36Sopenharmony_ci		.name = "bfq.io_merged_recursive",
139962306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.merged),
140062306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat_recursive,
140162306a36Sopenharmony_ci	},
140262306a36Sopenharmony_ci	{
140362306a36Sopenharmony_ci		.name = "bfq.io_queued_recursive",
140462306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.queued),
140562306a36Sopenharmony_ci		.seq_show = bfqg_print_rwstat_recursive,
140662306a36Sopenharmony_ci	},
140762306a36Sopenharmony_ci	{
140862306a36Sopenharmony_ci		.name = "bfq.avg_queue_size",
140962306a36Sopenharmony_ci		.seq_show = bfqg_print_avg_queue_size,
141062306a36Sopenharmony_ci	},
141162306a36Sopenharmony_ci	{
141262306a36Sopenharmony_ci		.name = "bfq.group_wait_time",
141362306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.group_wait_time),
141462306a36Sopenharmony_ci		.seq_show = bfqg_print_stat,
141562306a36Sopenharmony_ci	},
141662306a36Sopenharmony_ci	{
141762306a36Sopenharmony_ci		.name = "bfq.idle_time",
141862306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.idle_time),
141962306a36Sopenharmony_ci		.seq_show = bfqg_print_stat,
142062306a36Sopenharmony_ci	},
142162306a36Sopenharmony_ci	{
142262306a36Sopenharmony_ci		.name = "bfq.empty_time",
142362306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.empty_time),
142462306a36Sopenharmony_ci		.seq_show = bfqg_print_stat,
142562306a36Sopenharmony_ci	},
142662306a36Sopenharmony_ci	{
142762306a36Sopenharmony_ci		.name = "bfq.dequeue",
142862306a36Sopenharmony_ci		.private = offsetof(struct bfq_group, stats.dequeue),
142962306a36Sopenharmony_ci		.seq_show = bfqg_print_stat,
143062306a36Sopenharmony_ci	},
143162306a36Sopenharmony_ci#endif	/* CONFIG_BFQ_CGROUP_DEBUG */
143262306a36Sopenharmony_ci	{ }	/* terminate */
143362306a36Sopenharmony_ci};
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_cistruct cftype bfq_blkg_files[] = {
143662306a36Sopenharmony_ci	{
143762306a36Sopenharmony_ci		.name = "bfq.weight",
143862306a36Sopenharmony_ci		.flags = CFTYPE_NOT_ON_ROOT,
143962306a36Sopenharmony_ci		.seq_show = bfq_io_show_weight,
144062306a36Sopenharmony_ci		.write = bfq_io_set_weight,
144162306a36Sopenharmony_ci	},
144262306a36Sopenharmony_ci	{} /* terminate */
144362306a36Sopenharmony_ci};
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci#else	/* CONFIG_BFQ_GROUP_IOSCHED */
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_civoid bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
144862306a36Sopenharmony_ci		   struct bfq_group *bfqg) {}
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_civoid bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg)
145162306a36Sopenharmony_ci{
145262306a36Sopenharmony_ci	struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	entity->weight = entity->new_weight;
145562306a36Sopenharmony_ci	entity->orig_weight = entity->new_weight;
145662306a36Sopenharmony_ci	if (bfqq) {
145762306a36Sopenharmony_ci		bfqq->ioprio = bfqq->new_ioprio;
145862306a36Sopenharmony_ci		bfqq->ioprio_class = bfqq->new_ioprio_class;
145962306a36Sopenharmony_ci	}
146062306a36Sopenharmony_ci	entity->sched_data = &bfqg->sched_data;
146162306a36Sopenharmony_ci}
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_civoid bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) {}
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_civoid bfq_end_wr_async(struct bfq_data *bfqd)
146662306a36Sopenharmony_ci{
146762306a36Sopenharmony_ci	bfq_end_wr_async_queues(bfqd, bfqd->root_group);
146862306a36Sopenharmony_ci}
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_cistruct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
147162306a36Sopenharmony_ci{
147262306a36Sopenharmony_ci	return bfqd->root_group;
147362306a36Sopenharmony_ci}
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_cistruct bfq_group *bfqq_group(struct bfq_queue *bfqq)
147662306a36Sopenharmony_ci{
147762306a36Sopenharmony_ci	return bfqq->bfqd->root_group;
147862306a36Sopenharmony_ci}
147962306a36Sopenharmony_ci
148062306a36Sopenharmony_civoid bfqg_and_blkg_put(struct bfq_group *bfqg) {}
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_cistruct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node)
148362306a36Sopenharmony_ci{
148462306a36Sopenharmony_ci	struct bfq_group *bfqg;
148562306a36Sopenharmony_ci	int i;
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node);
148862306a36Sopenharmony_ci	if (!bfqg)
148962306a36Sopenharmony_ci		return NULL;
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	for (i = 0; i < BFQ_IOPRIO_CLASSES; i++)
149262306a36Sopenharmony_ci		bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT;
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	return bfqg;
149562306a36Sopenharmony_ci}
149662306a36Sopenharmony_ci#endif	/* CONFIG_BFQ_GROUP_IOSCHED */
1497