[Devel] [PATCH RHEL7 COMMIT] fs/fuse kio: implement fstat statistics info
Konstantin Khorenko
khorenko at virtuozzo.com
Wed May 29 17:24:51 MSK 2019
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 9251889e21b47b76040fb8f749099df150a81291
Author: Pavel Butsykin <pbutsykin at virtuozzo.com>
Date: Wed May 29 17:24:49 2019 +0300
fs/fuse kio: implement fstat statistics info
This statistic shows information about all open kio files. Made by analogy with
.vstorage.info/fstat statistics of user-mod client.
example:
# rw open/age inactive handles rd/sec rbytes/sec rtotal wr/sec wbytes/sec wtotal sync/sec stotal rmin ravg rmax wmin wavg wmax path
rw 2/5750 0 0 987 4039476 248864768 0 0 0 0 0 4096 4096 4096 0 0 0 /fio_test/randasyncread_jobs24_4k.1.0
rw 2/5750 0 0 60 243303 87810048 0 0 0 0 0 4096 4096 4096 0 0 0 /fio_test/randasyncread_jobs24_4k.0.0
Signed-off-by: Pavel Butsykin <pbutsykin at 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 at 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 | 99 ++++++++++++++++++++++++++++++++++++++
fs/fuse/kio/pcs/fuse_stat.h | 6 +++
fs/fuse/kio/pcs/pcs_client_types.h | 3 ++
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 7 ++-
4 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/fs/fuse/kio/pcs/fuse_stat.c b/fs/fuse/kio/pcs/fuse_stat.c
index 20691955a2f1..51a4ee106497 100644
--- a/fs/fuse/kio/pcs/fuse_stat.c
+++ b/fs/fuse/kio/pcs/fuse_stat.c
@@ -148,6 +148,96 @@ static void fuse_iostat_up(struct pcs_fuse_io_stat_sync *iostat)
spin_unlock(&iostat->lock);
}
+static void fuse_fstat_up_itr(struct fuse_file *ff, struct pcs_dentry_info *di,
+ void *ctx)
+{
+ struct fuse_io_cnt *fstat = &di->stat;
+ fuse_iostat_up(&fstat->io);
+}
+
+static void fuse_stat_files_up(struct pcs_cluster_core *cc)
+{
+ struct fuse_conn *fc = container_of(cc, struct pcs_fuse_cluster, cc)->fc;
+ if (fc) {
+ spin_lock(&fc->lock);
+ pcs_kio_file_list(fc, fuse_fstat_up_itr, NULL);
+ spin_unlock(&fc->lock);
+ }
+}
+
+static void fuse_kio_fstat_itr(struct fuse_file *ff, struct pcs_dentry_info *di,
+ void *ctx)
+{
+ struct fuse_io_cnt *fstat = &di->stat;
+ struct pcs_fuse_io_stat_sync *iostat = &fstat->io;
+ struct seq_file *m = ctx;
+ umode_t mode = di->inode->inode.i_mode;
+ abs_time_t now = jiffies;
+ struct pcs_fuse_io_stat lstat, gstat;
+
+ seq_printf(m, "%s%s %7u/%-7llu %-7u %-4u ",
+ mode & S_IRUGO ? "r": "", mode & S_IWUGO ? "w": "",
+ atomic_read(&ff->count), (now - fstat->created_ts) / 1000, 0, 0);
+
+ spin_lock(&iostat->lock);
+ stat_period_read(iostat->LAST(iostat), &lstat);
+ gstat = iostat->glob;
+ spin_unlock(&iostat->lock);
+
+ seq_printf(m, "%-6llu %-10llu %-13llu ", EVT_RATE(lstat.read_bytes),
+ VAL_RATE(lstat.read_bytes), gstat.read_bytes.val_total);
+ seq_printf(m, "%-6llu %-10llu %-13llu ", EVT_RATE(lstat.write_bytes),
+ VAL_RATE(lstat.write_bytes), gstat.write_bytes.val_total);
+ seq_printf(m, "%-6llu %-7llu ", EVT_RATE(lstat.flush_cnt),
+ gstat.flush_cnt.val_total);
+ seq_printf(m, "%-6llu %-6llu %-6llu ", CNT_MIN(lstat.read_bytes, gstat.read_bytes),
+ VAL_AVER(gstat.read_bytes), CNT_MAX(lstat.read_bytes, gstat.read_bytes));
+ seq_printf(m, "%-6llu %-6llu %-6llu ", CNT_MIN(lstat.write_bytes, gstat.read_bytes),
+ VAL_AVER(gstat.write_bytes), CNT_MAX(lstat.write_bytes, gstat.read_bytes));
+ seq_dentry(m, ff->ff_dentry, "");
+ seq_putc(m, '\n');
+}
+
+static int pcs_fuse_fstat_show(struct seq_file *m, void *v)
+{
+ struct inode *inode = m->private;
+ struct pcs_fuse_stat *stat;
+ struct fuse_conn *fc;
+
+ if (!inode)
+ return 0;
+
+ mutex_lock(&fuse_mutex);
+ stat = inode->i_private;
+ if (!stat)
+ goto out;
+
+ seq_printf(m, "# rw open/age inactive handles rd/sec rbytes/sec rtotal wr/sec wbytes/sec wtotal sync/sec stotal rmin ravg rmax wmin wavg wmax path\n");
+
+ fc = container_of(stat, struct pcs_fuse_cluster, cc.stat)->fc;
+ if (fc) {
+ spin_lock(&fc->lock);
+ pcs_kio_file_list(fc, fuse_kio_fstat_itr, m);
+ spin_unlock(&fc->lock);
+ }
+out:
+ mutex_unlock(&fuse_mutex);
+ return 0;
+}
+
+static int pcs_fuse_fstat_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pcs_fuse_fstat_show, inode);
+}
+
+static const struct file_operations pcs_fuse_fstat_ops = {
+ .owner = THIS_MODULE,
+ .open = pcs_fuse_fstat_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static void fuse_kio_stat_req_itr(struct fuse_file *ff, struct fuse_req *req,
void *ctx)
{
@@ -288,10 +378,12 @@ static void fuse_iostat_count(struct pcs_fuse_io_stat_sync *iostat,
void pcs_fuse_stat_io_count(struct pcs_int_request *ireq, struct pcs_msg *resp)
{
struct pcs_fuse_stat *stat = &ireq->cc->stat;
+ struct fuse_io_cnt *fstat = &ireq->dentry->stat;
struct pcs_cs_iohdr *h = (struct pcs_cs_iohdr *)msg_inline_head(resp);
u64 size = h->hdr.type != PCS_CS_SYNC_RESP ? ireq->iochunk.size : 0;
fuse_iostat_count(&stat->io, size, h->hdr.type);
+ fuse_iostat_count(&fstat->io, size, h->hdr.type);
}
static void pcs_fuse_stat_work(struct work_struct *w)
@@ -301,6 +393,7 @@ static void pcs_fuse_stat_work(struct work_struct *w)
struct pcs_fuse_stat *stat = &cc->stat;
fuse_iostat_up(&stat->io);
+ fuse_stat_files_up(cc);
mod_delayed_work(cc->wq, &cc->stat.work, STAT_TIMER_PERIOD * HZ);
}
@@ -405,6 +498,10 @@ void pcs_fuse_stat_init(struct pcs_fuse_stat *stat)
stat->requests = fuse_kio_add_dentry(stat->kio_stat, fc, "requests",
S_IFREG | S_IRUSR, 1, NULL,
&pcs_fuse_requests_ops, stat);
+ stat->fstat = fuse_kio_add_dentry(stat->kio_stat, fc, "fstat",
+ S_IFREG | S_IRUSR, 1, NULL,
+ &pcs_fuse_fstat_ops, stat);
+
mutex_unlock(&fuse_mutex);
return;
@@ -425,6 +522,8 @@ void pcs_fuse_stat_fini(struct pcs_fuse_stat *stat)
fuse_kio_rm_dentry(stat->iostat);
if (stat->requests)
fuse_kio_rm_dentry(stat->requests);
+ if (stat->fstat)
+ fuse_kio_rm_dentry(stat->fstat);
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 2a300c35213e..83bf0dc573f4 100644
--- a/fs/fuse/kio/pcs/fuse_stat.h
+++ b/fs/fuse/kio/pcs/fuse_stat.h
@@ -34,6 +34,12 @@ struct pcs_fuse_stat {
struct dentry *kio_stat;
struct dentry *iostat;
struct dentry *requests;
+ struct dentry *fstat;
+};
+
+struct fuse_io_cnt {
+ struct pcs_fuse_io_stat_sync io;
+ abs_time_t created_ts;
};
void pcs_fuse_stat_init(struct pcs_fuse_stat *stat);
diff --git a/fs/fuse/kio/pcs/pcs_client_types.h b/fs/fuse/kio/pcs/pcs_client_types.h
index c0d14ec5b5d4..5e72eb0fac3e 100644
--- a/fs/fuse/kio/pcs/pcs_client_types.h
+++ b/fs/fuse/kio/pcs/pcs_client_types.h
@@ -4,6 +4,7 @@
#include "pcs_prot_types.h"
#include "pcs_mds_prot.h"
#include "pcs_flow_detect.h"
+#include "fuse_stat.h"
/* Values of lease. It is value, not bitmask. */
#define PCS_LEASE_NONE 0
@@ -70,6 +71,8 @@ struct pcs_dentry_info {
struct fuse_inode *inode;
struct list_head kq;
spinlock_t kq_lock;
+
+ struct fuse_io_cnt stat;
};
static inline void pcs_clear_fileinfo(struct pcs_dentry_info *i)
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index d974285d0ec8..60ca97bc0e25 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -352,7 +352,11 @@ static int kpcs_do_file_open(struct fuse_conn *fc, struct file *file, struct ino
di->size.required = 0;
di->size.op = PCS_SIZE_INACTION;
INIT_WORK(&di->size.work, fuse_size_grow_work);
-
+ di->stat.created_ts = jiffies;
+ if (pcs_fuse_io_stat_alloc(&di->stat.io)) {
+ kfree(di);
+ return -ENOMEM;
+ }
pcs_mapping_init(&pfc->cc, &di->mapping);
pcs_set_fileinfo(di, &info);
di->cluster = &pfc->cc;
@@ -421,6 +425,7 @@ void kpcs_inode_release(struct fuse_inode *fi)
pcs_mapping_invalidate(&di->mapping);
pcs_mapping_deinit(&di->mapping);
/* TODO: properly destroy dentry info here!! */
+ pcs_fuse_io_stat_free(&di->stat.io);
kfree(di);
}
More information about the Devel
mailing list