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