189dd4c3bSJack Wang // SPDX-License-Identifier: GPL-2.0-or-later
289dd4c3bSJack Wang /*
389dd4c3bSJack Wang  * RDMA Transport Layer
489dd4c3bSJack Wang  *
589dd4c3bSJack Wang  * Copyright (c) 2014 - 2018 ProfitBricks GmbH. All rights reserved.
689dd4c3bSJack Wang  * Copyright (c) 2018 - 2019 1&1 IONOS Cloud GmbH. All rights reserved.
789dd4c3bSJack Wang  * Copyright (c) 2019 - 2020 1&1 IONOS SE. All rights reserved.
889dd4c3bSJack Wang  */
989dd4c3bSJack Wang #undef pr_fmt
1089dd4c3bSJack Wang #define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt
1189dd4c3bSJack Wang 
1289dd4c3bSJack Wang #include "rtrs-clt.h"
1389dd4c3bSJack Wang 
rtrs_clt_update_wc_stats(struct rtrs_clt_con * con)1489dd4c3bSJack Wang void rtrs_clt_update_wc_stats(struct rtrs_clt_con *con)
1589dd4c3bSJack Wang {
16caa84d95SVaishali Thakkar 	struct rtrs_clt_path *clt_path = to_clt_path(con->c.path);
17caa84d95SVaishali Thakkar 	struct rtrs_clt_stats *stats = clt_path->stats;
1889dd4c3bSJack Wang 	struct rtrs_clt_stats_pcpu *s;
1989dd4c3bSJack Wang 	int cpu;
2089dd4c3bSJack Wang 
2189dd4c3bSJack Wang 	cpu = raw_smp_processor_id();
22db6169b5SGuoqing Jiang 	s = get_cpu_ptr(stats->pcpu_stats);
234693d6b7SGioh Kim 	if (con->cpu != cpu) {
2489dd4c3bSJack Wang 		s->cpu_migr.to++;
2589dd4c3bSJack Wang 
2689dd4c3bSJack Wang 		/* Careful here, override s pointer */
2789dd4c3bSJack Wang 		s = per_cpu_ptr(stats->pcpu_stats, con->cpu);
2889dd4c3bSJack Wang 		atomic_inc(&s->cpu_migr.from);
2989dd4c3bSJack Wang 	}
30db6169b5SGuoqing Jiang 	put_cpu_ptr(stats->pcpu_stats);
3189dd4c3bSJack Wang }
3289dd4c3bSJack Wang 
rtrs_clt_inc_failover_cnt(struct rtrs_clt_stats * stats)3389dd4c3bSJack Wang void rtrs_clt_inc_failover_cnt(struct rtrs_clt_stats *stats)
3489dd4c3bSJack Wang {
35*861703b4SSantosh Kumar Pradhan 	this_cpu_inc(stats->pcpu_stats->rdma.failover_cnt);
3689dd4c3bSJack Wang }
3789dd4c3bSJack Wang 
rtrs_clt_stats_migration_from_cnt_to_str(struct rtrs_clt_stats * stats,char * buf)383f3fe682SMd Haris Iqbal int rtrs_clt_stats_migration_from_cnt_to_str(struct rtrs_clt_stats *stats, char *buf)
3989dd4c3bSJack Wang {
4089dd4c3bSJack Wang 	struct rtrs_clt_stats_pcpu *s;
4189dd4c3bSJack Wang 
4289dd4c3bSJack Wang 	size_t used;
4389dd4c3bSJack Wang 	int cpu;
4489dd4c3bSJack Wang 
453f3fe682SMd Haris Iqbal 	used = 0;
4689dd4c3bSJack Wang 	for_each_possible_cpu(cpu) {
4789dd4c3bSJack Wang 		s = per_cpu_ptr(stats->pcpu_stats, cpu);
482f232912SMd Haris Iqbal 		used += sysfs_emit_at(buf, used, "%d ",
4989dd4c3bSJack Wang 				  atomic_read(&s->cpu_migr.from));
5089dd4c3bSJack Wang 	}
5189dd4c3bSJack Wang 
523f3fe682SMd Haris Iqbal 	used += sysfs_emit_at(buf, used, "\n");
533f3fe682SMd Haris Iqbal 
543f3fe682SMd Haris Iqbal 	return used;
553f3fe682SMd Haris Iqbal }
563f3fe682SMd Haris Iqbal 
rtrs_clt_stats_migration_to_cnt_to_str(struct rtrs_clt_stats * stats,char * buf)573f3fe682SMd Haris Iqbal int rtrs_clt_stats_migration_to_cnt_to_str(struct rtrs_clt_stats *stats, char *buf)
583f3fe682SMd Haris Iqbal {
593f3fe682SMd Haris Iqbal 	struct rtrs_clt_stats_pcpu *s;
603f3fe682SMd Haris Iqbal 
613f3fe682SMd Haris Iqbal 	size_t used;
623f3fe682SMd Haris Iqbal 	int cpu;
633f3fe682SMd Haris Iqbal 
643f3fe682SMd Haris Iqbal 	used = 0;
6589dd4c3bSJack Wang 	for_each_possible_cpu(cpu) {
6689dd4c3bSJack Wang 		s = per_cpu_ptr(stats->pcpu_stats, cpu);
672f232912SMd Haris Iqbal 		used += sysfs_emit_at(buf, used, "%d ", s->cpu_migr.to);
6889dd4c3bSJack Wang 	}
693f3fe682SMd Haris Iqbal 
702f232912SMd Haris Iqbal 	used += sysfs_emit_at(buf, used, "\n");
7189dd4c3bSJack Wang 
7289dd4c3bSJack Wang 	return used;
7389dd4c3bSJack Wang }
7489dd4c3bSJack Wang 
rtrs_clt_stats_reconnects_to_str(struct rtrs_clt_stats * stats,char * buf)7580ad07f7SMd Haris Iqbal int rtrs_clt_stats_reconnects_to_str(struct rtrs_clt_stats *stats, char *buf)
7689dd4c3bSJack Wang {
772f232912SMd Haris Iqbal 	return sysfs_emit(buf, "%d %d\n", stats->reconnects.successful_cnt,
7889dd4c3bSJack Wang 			  stats->reconnects.fail_cnt);
7989dd4c3bSJack Wang }
8089dd4c3bSJack Wang 
rtrs_clt_stats_rdma_to_str(struct rtrs_clt_stats * stats,char * page)8180ad07f7SMd Haris Iqbal ssize_t rtrs_clt_stats_rdma_to_str(struct rtrs_clt_stats *stats, char *page)
8289dd4c3bSJack Wang {
8389dd4c3bSJack Wang 	struct rtrs_clt_stats_rdma sum;
8489dd4c3bSJack Wang 	struct rtrs_clt_stats_rdma *r;
8589dd4c3bSJack Wang 	int cpu;
8689dd4c3bSJack Wang 
8789dd4c3bSJack Wang 	memset(&sum, 0, sizeof(sum));
8889dd4c3bSJack Wang 
8989dd4c3bSJack Wang 	for_each_possible_cpu(cpu) {
9089dd4c3bSJack Wang 		r = &per_cpu_ptr(stats->pcpu_stats, cpu)->rdma;
9189dd4c3bSJack Wang 
9289dd4c3bSJack Wang 		sum.dir[READ].cnt	  += r->dir[READ].cnt;
9389dd4c3bSJack Wang 		sum.dir[READ].size_total  += r->dir[READ].size_total;
9489dd4c3bSJack Wang 		sum.dir[WRITE].cnt	  += r->dir[WRITE].cnt;
9589dd4c3bSJack Wang 		sum.dir[WRITE].size_total += r->dir[WRITE].size_total;
9689dd4c3bSJack Wang 		sum.failover_cnt	  += r->failover_cnt;
9789dd4c3bSJack Wang 	}
9889dd4c3bSJack Wang 
992f232912SMd Haris Iqbal 	return sysfs_emit(page, "%llu %llu %llu %llu %u %llu\n",
10089dd4c3bSJack Wang 			 sum.dir[READ].cnt, sum.dir[READ].size_total,
10189dd4c3bSJack Wang 			 sum.dir[WRITE].cnt, sum.dir[WRITE].size_total,
10289dd4c3bSJack Wang 			 atomic_read(&stats->inflight), sum.failover_cnt);
10389dd4c3bSJack Wang }
10489dd4c3bSJack Wang 
rtrs_clt_reset_all_help(struct rtrs_clt_stats * s,char * page)10580ad07f7SMd Haris Iqbal ssize_t rtrs_clt_reset_all_help(struct rtrs_clt_stats *s, char *page)
10689dd4c3bSJack Wang {
1072f232912SMd Haris Iqbal 	return sysfs_emit(page, "echo 1 to reset all statistics\n");
10889dd4c3bSJack Wang }
10989dd4c3bSJack Wang 
rtrs_clt_reset_rdma_stats(struct rtrs_clt_stats * stats,bool enable)11089dd4c3bSJack Wang int rtrs_clt_reset_rdma_stats(struct rtrs_clt_stats *stats, bool enable)
11189dd4c3bSJack Wang {
11289dd4c3bSJack Wang 	struct rtrs_clt_stats_pcpu *s;
11389dd4c3bSJack Wang 	int cpu;
11489dd4c3bSJack Wang 
11589dd4c3bSJack Wang 	if (!enable)
11689dd4c3bSJack Wang 		return -EINVAL;
11789dd4c3bSJack Wang 
11889dd4c3bSJack Wang 	for_each_possible_cpu(cpu) {
11989dd4c3bSJack Wang 		s = per_cpu_ptr(stats->pcpu_stats, cpu);
12089dd4c3bSJack Wang 		memset(&s->rdma, 0, sizeof(s->rdma));
12189dd4c3bSJack Wang 	}
12289dd4c3bSJack Wang 
12389dd4c3bSJack Wang 	return 0;
12489dd4c3bSJack Wang }
12589dd4c3bSJack Wang 
rtrs_clt_reset_cpu_migr_stats(struct rtrs_clt_stats * stats,bool enable)12689dd4c3bSJack Wang int rtrs_clt_reset_cpu_migr_stats(struct rtrs_clt_stats *stats, bool enable)
12789dd4c3bSJack Wang {
12889dd4c3bSJack Wang 	struct rtrs_clt_stats_pcpu *s;
12989dd4c3bSJack Wang 	int cpu;
13089dd4c3bSJack Wang 
13189dd4c3bSJack Wang 	if (!enable)
13289dd4c3bSJack Wang 		return -EINVAL;
13389dd4c3bSJack Wang 
13489dd4c3bSJack Wang 	for_each_possible_cpu(cpu) {
13589dd4c3bSJack Wang 		s = per_cpu_ptr(stats->pcpu_stats, cpu);
13689dd4c3bSJack Wang 		memset(&s->cpu_migr, 0, sizeof(s->cpu_migr));
13789dd4c3bSJack Wang 	}
13889dd4c3bSJack Wang 
13989dd4c3bSJack Wang 	return 0;
14089dd4c3bSJack Wang }
14189dd4c3bSJack Wang 
rtrs_clt_reset_reconnects_stat(struct rtrs_clt_stats * stats,bool enable)14289dd4c3bSJack Wang int rtrs_clt_reset_reconnects_stat(struct rtrs_clt_stats *stats, bool enable)
14389dd4c3bSJack Wang {
14489dd4c3bSJack Wang 	if (!enable)
14589dd4c3bSJack Wang 		return -EINVAL;
14689dd4c3bSJack Wang 
14789dd4c3bSJack Wang 	memset(&stats->reconnects, 0, sizeof(stats->reconnects));
14889dd4c3bSJack Wang 
14989dd4c3bSJack Wang 	return 0;
15089dd4c3bSJack Wang }
15189dd4c3bSJack Wang 
rtrs_clt_reset_all_stats(struct rtrs_clt_stats * s,bool enable)15289dd4c3bSJack Wang int rtrs_clt_reset_all_stats(struct rtrs_clt_stats *s, bool enable)
15389dd4c3bSJack Wang {
15489dd4c3bSJack Wang 	if (enable) {
15589dd4c3bSJack Wang 		rtrs_clt_reset_rdma_stats(s, enable);
15689dd4c3bSJack Wang 		rtrs_clt_reset_cpu_migr_stats(s, enable);
15789dd4c3bSJack Wang 		rtrs_clt_reset_reconnects_stat(s, enable);
15889dd4c3bSJack Wang 		atomic_set(&s->inflight, 0);
15989dd4c3bSJack Wang 		return 0;
16089dd4c3bSJack Wang 	}
16189dd4c3bSJack Wang 
16289dd4c3bSJack Wang 	return -EINVAL;
16389dd4c3bSJack Wang }
16489dd4c3bSJack Wang 
rtrs_clt_update_rdma_stats(struct rtrs_clt_stats * stats,size_t size,int d)16589dd4c3bSJack Wang static inline void rtrs_clt_update_rdma_stats(struct rtrs_clt_stats *stats,
16689dd4c3bSJack Wang 					       size_t size, int d)
16789dd4c3bSJack Wang {
168*861703b4SSantosh Kumar Pradhan 	this_cpu_inc(stats->pcpu_stats->rdma.dir[d].cnt);
169*861703b4SSantosh Kumar Pradhan 	this_cpu_add(stats->pcpu_stats->rdma.dir[d].size_total, size);
17089dd4c3bSJack Wang }
17189dd4c3bSJack Wang 
rtrs_clt_update_all_stats(struct rtrs_clt_io_req * req,int dir)17289dd4c3bSJack Wang void rtrs_clt_update_all_stats(struct rtrs_clt_io_req *req, int dir)
17389dd4c3bSJack Wang {
17489dd4c3bSJack Wang 	struct rtrs_clt_con *con = req->con;
175caa84d95SVaishali Thakkar 	struct rtrs_clt_path *clt_path = to_clt_path(con->c.path);
176caa84d95SVaishali Thakkar 	struct rtrs_clt_stats *stats = clt_path->stats;
17789dd4c3bSJack Wang 	unsigned int len;
17889dd4c3bSJack Wang 
17989dd4c3bSJack Wang 	len = req->usr_len + req->data_len;
18089dd4c3bSJack Wang 	rtrs_clt_update_rdma_stats(stats, len, dir);
1810d8f2cfaSGioh Kim 	if (req->mp_policy == MP_POLICY_MIN_INFLIGHT)
18289dd4c3bSJack Wang 		atomic_inc(&stats->inflight);
18389dd4c3bSJack Wang }
18489dd4c3bSJack Wang 
rtrs_clt_init_stats(struct rtrs_clt_stats * stats)18589dd4c3bSJack Wang int rtrs_clt_init_stats(struct rtrs_clt_stats *stats)
18689dd4c3bSJack Wang {
18789dd4c3bSJack Wang 	stats->pcpu_stats = alloc_percpu(typeof(*stats->pcpu_stats));
18889dd4c3bSJack Wang 	if (!stats->pcpu_stats)
18989dd4c3bSJack Wang 		return -ENOMEM;
19089dd4c3bSJack Wang 
19189dd4c3bSJack Wang 	/*
19289dd4c3bSJack Wang 	 * successful_cnt will be set to 0 after session
19389dd4c3bSJack Wang 	 * is established for the first time
19489dd4c3bSJack Wang 	 */
19589dd4c3bSJack Wang 	stats->reconnects.successful_cnt = -1;
19689dd4c3bSJack Wang 
19789dd4c3bSJack Wang 	return 0;
19889dd4c3bSJack Wang }
199