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