162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci * 362306a36Sopenharmony_ci * Legacy blkg rwstat helpers enabled by CONFIG_BLK_CGROUP_RWSTAT. 462306a36Sopenharmony_ci * Do not use in new code. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef _BLK_CGROUP_RWSTAT_H 762306a36Sopenharmony_ci#define _BLK_CGROUP_RWSTAT_H 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "blk-cgroup.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cienum blkg_rwstat_type { 1262306a36Sopenharmony_ci BLKG_RWSTAT_READ, 1362306a36Sopenharmony_ci BLKG_RWSTAT_WRITE, 1462306a36Sopenharmony_ci BLKG_RWSTAT_SYNC, 1562306a36Sopenharmony_ci BLKG_RWSTAT_ASYNC, 1662306a36Sopenharmony_ci BLKG_RWSTAT_DISCARD, 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci BLKG_RWSTAT_NR, 1962306a36Sopenharmony_ci BLKG_RWSTAT_TOTAL = BLKG_RWSTAT_NR, 2062306a36Sopenharmony_ci}; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * blkg_[rw]stat->aux_cnt is excluded for local stats but included for 2462306a36Sopenharmony_ci * recursive. Used to carry stats of dead children. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_cistruct blkg_rwstat { 2762306a36Sopenharmony_ci struct percpu_counter cpu_cnt[BLKG_RWSTAT_NR]; 2862306a36Sopenharmony_ci atomic64_t aux_cnt[BLKG_RWSTAT_NR]; 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistruct blkg_rwstat_sample { 3262306a36Sopenharmony_ci u64 cnt[BLKG_RWSTAT_NR]; 3362306a36Sopenharmony_ci}; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic inline u64 blkg_rwstat_read_counter(struct blkg_rwstat *rwstat, 3662306a36Sopenharmony_ci unsigned int idx) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci return atomic64_read(&rwstat->aux_cnt[idx]) + 3962306a36Sopenharmony_ci percpu_counter_sum_positive(&rwstat->cpu_cnt[idx]); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ciint blkg_rwstat_init(struct blkg_rwstat *rwstat, gfp_t gfp); 4362306a36Sopenharmony_civoid blkg_rwstat_exit(struct blkg_rwstat *rwstat); 4462306a36Sopenharmony_ciu64 __blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd, 4562306a36Sopenharmony_ci const struct blkg_rwstat_sample *rwstat); 4662306a36Sopenharmony_ciu64 blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd, 4762306a36Sopenharmony_ci int off); 4862306a36Sopenharmony_civoid blkg_rwstat_recursive_sum(struct blkcg_gq *blkg, struct blkcg_policy *pol, 4962306a36Sopenharmony_ci int off, struct blkg_rwstat_sample *sum); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/** 5362306a36Sopenharmony_ci * blkg_rwstat_add - add a value to a blkg_rwstat 5462306a36Sopenharmony_ci * @rwstat: target blkg_rwstat 5562306a36Sopenharmony_ci * @op: REQ_OP and flags 5662306a36Sopenharmony_ci * @val: value to add 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * Add @val to @rwstat. The counters are chosen according to @rw. The 5962306a36Sopenharmony_ci * caller is responsible for synchronizing calls to this function. 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_cistatic inline void blkg_rwstat_add(struct blkg_rwstat *rwstat, 6262306a36Sopenharmony_ci blk_opf_t opf, uint64_t val) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci struct percpu_counter *cnt; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci if (op_is_discard(opf)) 6762306a36Sopenharmony_ci cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_DISCARD]; 6862306a36Sopenharmony_ci else if (op_is_write(opf)) 6962306a36Sopenharmony_ci cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_WRITE]; 7062306a36Sopenharmony_ci else 7162306a36Sopenharmony_ci cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_READ]; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci percpu_counter_add_batch(cnt, val, BLKG_STAT_CPU_BATCH); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (op_is_sync(opf)) 7662306a36Sopenharmony_ci cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_SYNC]; 7762306a36Sopenharmony_ci else 7862306a36Sopenharmony_ci cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_ASYNC]; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci percpu_counter_add_batch(cnt, val, BLKG_STAT_CPU_BATCH); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/** 8462306a36Sopenharmony_ci * blkg_rwstat_read - read the current values of a blkg_rwstat 8562306a36Sopenharmony_ci * @rwstat: blkg_rwstat to read 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * Read the current snapshot of @rwstat and return it in the aux counts. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_cistatic inline void blkg_rwstat_read(struct blkg_rwstat *rwstat, 9062306a36Sopenharmony_ci struct blkg_rwstat_sample *result) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci int i; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci for (i = 0; i < BLKG_RWSTAT_NR; i++) 9562306a36Sopenharmony_ci result->cnt[i] = 9662306a36Sopenharmony_ci percpu_counter_sum_positive(&rwstat->cpu_cnt[i]); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/** 10062306a36Sopenharmony_ci * blkg_rwstat_total - read the total count of a blkg_rwstat 10162306a36Sopenharmony_ci * @rwstat: blkg_rwstat to read 10262306a36Sopenharmony_ci * 10362306a36Sopenharmony_ci * Return the total count of @rwstat regardless of the IO direction. This 10462306a36Sopenharmony_ci * function can be called without synchronization and takes care of u64 10562306a36Sopenharmony_ci * atomicity. 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_cistatic inline uint64_t blkg_rwstat_total(struct blkg_rwstat *rwstat) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct blkg_rwstat_sample tmp = { }; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci blkg_rwstat_read(rwstat, &tmp); 11262306a36Sopenharmony_ci return tmp.cnt[BLKG_RWSTAT_READ] + tmp.cnt[BLKG_RWSTAT_WRITE]; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/** 11662306a36Sopenharmony_ci * blkg_rwstat_reset - reset a blkg_rwstat 11762306a36Sopenharmony_ci * @rwstat: blkg_rwstat to reset 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_cistatic inline void blkg_rwstat_reset(struct blkg_rwstat *rwstat) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci int i; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci for (i = 0; i < BLKG_RWSTAT_NR; i++) { 12462306a36Sopenharmony_ci percpu_counter_set(&rwstat->cpu_cnt[i], 0); 12562306a36Sopenharmony_ci atomic64_set(&rwstat->aux_cnt[i], 0); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/** 13062306a36Sopenharmony_ci * blkg_rwstat_add_aux - add a blkg_rwstat into another's aux count 13162306a36Sopenharmony_ci * @to: the destination blkg_rwstat 13262306a36Sopenharmony_ci * @from: the source 13362306a36Sopenharmony_ci * 13462306a36Sopenharmony_ci * Add @from's count including the aux one to @to's aux count. 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_cistatic inline void blkg_rwstat_add_aux(struct blkg_rwstat *to, 13762306a36Sopenharmony_ci struct blkg_rwstat *from) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci u64 sum[BLKG_RWSTAT_NR]; 14062306a36Sopenharmony_ci int i; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci for (i = 0; i < BLKG_RWSTAT_NR; i++) 14362306a36Sopenharmony_ci sum[i] = percpu_counter_sum_positive(&from->cpu_cnt[i]); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci for (i = 0; i < BLKG_RWSTAT_NR; i++) 14662306a36Sopenharmony_ci atomic64_add(sum[i] + atomic64_read(&from->aux_cnt[i]), 14762306a36Sopenharmony_ci &to->aux_cnt[i]); 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci#endif /* _BLK_CGROUP_RWSTAT_H */ 150