[v2,14/14] fs/fuse kio: implement cs_stats statistics info

Submitted by Pavel Butsykin on May 24, 2019, 3:55 p.m.

Details

Message ID 20190524155503.7205-15-pbutsykin@virtuozzo.com
State New
Series "Statistics for vstorage kernel fast-path"
Headers show

Commit Message

Pavel Butsykin May 24, 2019, 3:55 p.m.
This statistic shows information about all cs's, directed to show how much and
what type of load the chunk servers are loaded on. Made by analogy with
.vstorage.info/cs_stats statistics of user-mod client.

example:
# csid     rpc        rd_ops     wr_ops     sync_ops   net_lat                  io_lat                   avg_in_flight
1025       5=WORK     4909       0          0          (95% <= 20, 99% <= 20)   (95% <= 20, 99% <= 20)   128877

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
---
 fs/fuse/kio/pcs/fuse_stat.c | 96 +++++++++++++++++++++++++++++++++++++++++++++
 fs/fuse/kio/pcs/fuse_stat.h |  1 +
 fs/fuse/kio/pcs/pcs_cs.c    |  2 +
 fs/fuse/kio/pcs/pcs_cs.h    | 15 +++++++
 4 files changed, 114 insertions(+)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/kio/pcs/fuse_stat.c b/fs/fuse/kio/pcs/fuse_stat.c
index f54f29c5bae8..c2bb29404f2e 100644
--- a/fs/fuse/kio/pcs/fuse_stat.c
+++ b/fs/fuse/kio/pcs/fuse_stat.c
@@ -308,6 +308,96 @@  static void latency_percl_print(struct fuse_lat_stat *s, struct seq_file *m)
 	seq_printf(m, ")%*s", max(icnt, 0), "");
 }
 
+static int do_show_cs_stats(struct pcs_cs *cs, void *ctx)
+{
+	struct seq_file *m = ctx;
+	int rpc_state = cs->rpc ? cs->rpc->state : PCS_RPC_UNCONN;
+	unsigned int in_flight_avg = cs->in_flight_avg;
+	struct fuse_lat_stat iolat, netlat;
+	struct pcs_perf_rate_cnt read_ops_rate, write_ops_rate, sync_ops_rate;
+	unsigned seq;
+
+	do {
+		int cpu;
+		bool inited = false;
+
+		seq = read_seqbegin(&cs->stat.seqlock);
+		for_each_possible_cpu(cpu) {
+			struct fuse_lat_stat *pcpu_iolat, *pcpu_netlat;
+			struct pcs_perf_rate_cnt *pcpu_read_rate,
+						 *pcpu_write_rate,
+						 *pcpu_sync_rate;
+
+			pcpu_iolat = per_cpu_ptr(cs->stat.iolat, cpu);
+			pcpu_netlat = per_cpu_ptr(cs->stat.netlat, cpu);
+			pcpu_read_rate = per_cpu_ptr(cs->stat.read_ops_rate, cpu);
+			pcpu_write_rate = per_cpu_ptr(cs->stat.write_ops_rate, cpu);
+			pcpu_sync_rate = per_cpu_ptr(cs->stat.sync_ops_rate, cpu);
+
+			if (!inited) {
+				iolat = *pcpu_iolat;
+				netlat = *pcpu_netlat;
+				read_ops_rate = *pcpu_read_rate;
+				write_ops_rate = *pcpu_write_rate;
+				sync_ops_rate = *pcpu_sync_rate;
+				inited = true;
+				continue;
+			}
+			fuse_iolat_sum(&iolat, pcpu_iolat);
+			fuse_iolat_sum(&netlat, pcpu_netlat);
+			pcs_cs_stat_rate_sum(&read_ops_rate, pcpu_read_rate);
+			pcs_cs_stat_rate_sum(&write_ops_rate, pcpu_write_rate);
+			pcs_cs_stat_rate_sum(&sync_ops_rate, pcpu_sync_rate);
+		}
+	} while (read_seqretry(&cs->stat.seqlock, seq));
+
+	seq_printf(m, "%-10llu %d=%-8s %-10llu %-10llu %-11llu",
+		NODE_ARGS(cs->id), rpc_state, pcs_rpc_state_name(rpc_state),
+		read_ops_rate.rate / STAT_TIMER_PERIOD,
+		write_ops_rate.rate / STAT_TIMER_PERIOD,
+		sync_ops_rate.rate / STAT_TIMER_PERIOD);
+	latency_percl_print(&iolat, m);
+	latency_percl_print(&netlat, m);
+	seq_printf(m, "%-10u\n", in_flight_avg);
+	return 0;
+}
+
+static int pcs_fuse_cs_stats_show(struct seq_file *m, void *v)
+{
+	struct inode *inode = m->private;
+	struct pcs_cluster_core *cc;
+	struct pcs_fuse_stat *stat;
+
+	if (!inode)
+		return 0;
+
+	mutex_lock(&fuse_mutex);
+	stat = inode->i_private;
+	if (!stat)
+		goto out;
+
+	seq_printf(m, "# csid     rpc        rd_ops     wr_ops     sync_ops   net_lat\t\t\tio_lat\t\t\t avg_in_flight\n");
+
+	cc = container_of(stat, struct pcs_cluster_core, stat);
+	pcs_cs_for_each_entry(&cc->css, do_show_cs_stats, m);
+out:
+	mutex_unlock(&fuse_mutex);
+	return 0;
+}
+
+static int pcs_fuse_cs_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pcs_fuse_cs_stats_show, inode);
+}
+
+static const struct file_operations pcs_fuse_cs_stats_ops = {
+	.owner   = THIS_MODULE,
+	.open    = pcs_fuse_cs_stats_open,
+	.read    = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
 static void fuse_kio_fstat_lat_itr(struct fuse_file *ff,
 				   struct pcs_dentry_info *di, void *ctx)
 {
@@ -612,6 +702,7 @@  static void pcs_fuse_stat_work(struct work_struct *w)
 
 	fuse_iostat_up(&stat->io);
 	fuse_stat_files_up(cc);
+	pcs_cs_set_stat_up(&cc->css);
 
 	mod_delayed_work(cc->wq, &cc->stat.work, STAT_TIMER_PERIOD * HZ);
 }
@@ -749,6 +840,9 @@  void pcs_fuse_stat_init(struct pcs_fuse_stat *stat)
 	stat->fstat_lat = fuse_kio_add_dentry(stat->kio_stat, fc, "fstat_lat",
 					      S_IFREG | S_IRUSR, 1, NULL,
 					      &pcs_fuse_fstat_lat_ops, stat);
+	stat->cs_stats = fuse_kio_add_dentry(stat->kio_stat, fc, "cs_stats",
+					     S_IFREG | S_IRUSR, 1, NULL,
+					     &pcs_fuse_cs_stats_ops, stat);
 	mutex_unlock(&fuse_mutex);
 	return;
 
@@ -773,6 +867,8 @@  void pcs_fuse_stat_fini(struct pcs_fuse_stat *stat)
 			fuse_kio_rm_dentry(stat->fstat);
 		if (stat->fstat_lat)
 			fuse_kio_rm_dentry(stat->fstat_lat);
+		if (stat->cs_stats)
+			fuse_kio_rm_dentry(stat->cs_stats);
 		fuse_kio_rm_dentry(stat->kio_stat);
 	}
 	mutex_unlock(&fuse_mutex);
diff --git a/fs/fuse/kio/pcs/fuse_stat.h b/fs/fuse/kio/pcs/fuse_stat.h
index b6d513bed7ea..438836898437 100644
--- a/fs/fuse/kio/pcs/fuse_stat.h
+++ b/fs/fuse/kio/pcs/fuse_stat.h
@@ -36,6 +36,7 @@  struct pcs_fuse_stat {
 	struct dentry *requests;
 	struct dentry *fstat;
 	struct dentry *fstat_lat;
+	struct dentry *cs_stats;
 };
 
 enum {
diff --git a/fs/fuse/kio/pcs/pcs_cs.c b/fs/fuse/kio/pcs/pcs_cs.c
index 93b121127595..7f90089f16fb 100644
--- a/fs/fuse/kio/pcs/pcs_cs.c
+++ b/fs/fuse/kio/pcs/pcs_cs.c
@@ -1198,7 +1198,9 @@  int pcs_cs_for_each_entry(struct pcs_cs_set *set, int (*cb)(struct pcs_cs *cs, v
 	spin_lock(&set->lock);
 	for (i = 0; i < PCS_CS_HASH_SIZE; i++) {
 		hlist_for_each_entry_safe(cs, node, &set->ht[i], hlist) {
+			rcu_read_lock();
 			rc = cb(cs, arg);
+			rcu_read_unlock();
 			if (rc < 0) {
 				spin_lock(&set->lock);
 				return rc;
diff --git a/fs/fuse/kio/pcs/pcs_cs.h b/fs/fuse/kio/pcs/pcs_cs.h
index 8bdd056b5196..a5e3abc5703c 100644
--- a/fs/fuse/kio/pcs/pcs_cs.h
+++ b/fs/fuse/kio/pcs/pcs_cs.h
@@ -159,6 +159,21 @@  int pcs_cs_for_each_entry(struct pcs_cs_set *set, int (*cb)(struct pcs_cs *cs, v
 
 void pcs_cs_update_stat(struct pcs_cs *cs, u32 iolat, u32 netlat, int op_type);
 
+static inline void pcs_cs_stat_rate_sum(struct pcs_perf_rate_cnt *s,
+					struct pcs_perf_rate_cnt *add)
+{
+	if (!add->total)
+		return;
+
+	if (!s->total)
+		*s = *add;
+	else {
+		s->total += add->total;
+		s->last_total += add->last_total;
+		s->rate += add->rate;
+	}
+}
+
 static inline void pcs_cs_stat_up(struct pcs_cs *cs)
 {
 	int cpu;