[RHEL7,COMMIT] fs/fuse kio: implement cs_stats statistics info

Submitted by Konstantin Khorenko on May 29, 2019, 2:35 p.m.

Details

Message ID 201905291435.x4TEZjxQ010124@finist-ce7.sw.ru
State New
Series "Statistics for vstorage kernel fast-path"
Headers show

Commit Message

Konstantin Khorenko May 29, 2019, 2:35 p.m.
The commit is pushed to "branch-rh7-3.10.0-957.12.2.vz7.96.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.12.2.vz7.96.7
------>
commit 049aa5f3a22cd46842c010bb83c08aec77bd7196
Author: Pavel Butsykin <pbutsykin@virtuozzo.com>
Date:   Wed May 29 17:35:45 2019 +0300

    fs/fuse kio: implement cs_stats statistics info
    
    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>
    
    =====================
    Patchset description:
    
    Statistics for vstorage kernel fast-path
    
    Vstorage provides plenty of statistics information via 'vstorage -c cl mnt-top',
    but when it comes kernel fast-path, it doesn't work. All because mnt-top
    command collects information from .vstorage.info directory, where vstorage-mount
    provides a lot of different statistical information in the form of files, but
    it was not implemented for for fast-path.
    
    This patch-set is aimed to implementation of the support of some statistics
    inforamtion files from .vstorage.info:
      cs_stats
      fstat
      fstat_lat
      iostat
      requests
    Which will be located at "/sys/fs/fuse/connections/*mnt_id*/kio_stat/". This
    will be enough to maintain vstorage mnt-top command for fast-path mount points.
    
    https://pmc.acronis.com/browse/VSTOR-20979
    
    Acked-by: Alexey Kuznetsov <kuznet@virtuozzo.com>
    
    Pavel Butsykin (14):
      fs/fuse: add conn_ctl to fuse_conn struct
      fs/fuse kio: create sysfs stat directory
      fs/fuse kio: implement iostat statistics info
      fs/fuse kio: make interface pcs_kio_file_list() for listing kio files
      fs/fuse kio: make interface pcs_kio_req_list() for listing kio reqs
      fs/fuse kio: add retry counter for kio requests
      fs/fuse kio: implement pcs_strerror()
      fs/fuse kio: implement requests statistics info
      fs/fuse kio: implement fstat statistics info
      fs/fuse kio: implement fstat_lat statistics info
      fs/fuse kio: remove useless pcs_cs initialization
      fs/fuse kio: implement cs statistics accounting
      fs/fuse kio: convert rpc state id to string
      fs/fuse kio: implement cs_stats statistics info
---
 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..1b44793d25f8 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 98f8193c8a99..c6ff456c59c2 100644
--- a/fs/fuse/kio/pcs/pcs_cs.c
+++ b/fs/fuse/kio/pcs/pcs_cs.c
@@ -1214,7 +1214,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 7f124ecf58f3..5a7bee151be8 100644
--- a/fs/fuse/kio/pcs/pcs_cs.h
+++ b/fs/fuse/kio/pcs/pcs_cs.h
@@ -160,6 +160,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;