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.1
------>
commit 959eb3ee819cc39f6390a63e764b7a5c18318160
Author: Pavel Butsykin <pbutsy...@virtuozzo.com>
Date:   Tue May 21 18:47:43 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 <pbutsy...@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
    
    Pavel Butsykin (15):
      fs/fuse: add conn_ctl to fuse_conn struct
      fs/fuse kio: create sysfs stat directory
      fs/fuse kio: implement iostat
      fs/fuse kio: make common interface pcs_kio_file_list() for listing kio 
files
      fs/fuse kio: make common 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
      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: add locked cs_get_avg_in_flight()
---
 fs/fuse/kio/pcs/fuse_stat.c        | 131 +++++++++++++++++++++++++++++++++++--
 fs/fuse/kio/pcs/fuse_stat.h        |  11 ++++
 fs/fuse/kio/pcs/pcs_client_types.h |   3 +
 fs/fuse/kio/pcs/pcs_fuse_kdirect.c |   2 +
 4 files changed, 142 insertions(+), 5 deletions(-)

diff --git a/fs/fuse/kio/pcs/fuse_stat.c b/fs/fuse/kio/pcs/fuse_stat.c
index 1b3af5137d14..85c8f7e04413 100644
--- a/fs/fuse/kio/pcs/fuse_stat.c
+++ b/fs/fuse/kio/pcs/fuse_stat.c
@@ -77,13 +77,119 @@ static inline unsigned long long 
fuse_val_cnt_events(struct fuse_val_cnt const*
 {
        return c->curr.events + c->glob.events;
 }
+static inline unsigned long long fuse_val_cnt_min(struct fuse_val_cnt const* c)
+{
+       return min(c->curr.val_min, c->glob.val_min);
+}
+
+static inline unsigned long long fuse_val_cnt_max(struct fuse_val_cnt const* c)
+{
+       return max(c->curr.val_max, c->glob.val_max);
+}
 
 #define EVT_RATE(s)   fuse_evt_rate(&(s), STAT_TIMER_PERIOD)
 #define VAL_RATE(s)   fuse_val_rate(&(s), STAT_TIMER_PERIOD)
 #define VAL_AVER(s)   fuse_val_aver(&(s))
 #define CNT_TOTAL(c)  fuse_val_cnt_total(&(c))
 #define CNT_EVENTS(c) fuse_val_cnt_events(&(c))
+#define CNT_MIN(c)    fuse_val_cnt_min(&(c))
+#define CNT_MAX(c)    fuse_val_cnt_max(&(c))
+
+
+static void fuse_fstat_up_itr(struct fuse_file *ff, struct pcs_dentry_info *di,
+                             void *ctx)
+{
+       struct fuse_io_cnt *fstat = &di->stat;
+
+       spin_lock(&fstat->lock);
+       fuse_val_cnt_up(&fstat->io.read_bytes);
+       fuse_val_cnt_up(&fstat->io.write_bytes);
+       fuse_val_cnt_up(&fstat->io.flush_cnt);
+       spin_unlock(&fstat->lock);
+}
+
+static void pcs_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 seq_file *m = ctx;
+       umode_t mode = di->inode->inode.i_mode;
+       abs_time_t now = jiffies;
+       struct pcs_fuse_io_stat io_stat;
+
+       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(&fstat->lock);
+       io_stat = fstat->io;
+       spin_unlock(&fstat->lock);
+
+       seq_printf(m, "%-6llu %-10llu %-13llu ", 
EVT_RATE(io_stat.read_bytes.last),
+                  VAL_RATE(io_stat.read_bytes.last), 
CNT_TOTAL(io_stat.read_bytes));
+       seq_printf(m, "%-6llu %-10llu %-13llu ", 
EVT_RATE(io_stat.write_bytes.last),
+                  VAL_RATE(io_stat.write_bytes.last), 
CNT_TOTAL(io_stat.write_bytes));
+       seq_printf(m, "%-6llu %-7llu ", EVT_RATE(io_stat.flush_cnt.last),
+                  CNT_TOTAL(io_stat.flush_cnt));
+       seq_printf(m, "%-6llu %-6llu %-6llu ", CNT_MIN(io_stat.read_bytes),
+                  VAL_AVER(io_stat.read_bytes.glob), 
CNT_MAX(io_stat.read_bytes));
+       seq_printf(m, "%-6llu %-6llu %-6llu ", CNT_MIN(io_stat.write_bytes),
+                  VAL_AVER(io_stat.write_bytes.glob), 
CNT_MAX(io_stat.write_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) {
+               mutex_unlock(&fuse_mutex);
+               return 0;
+       }
+
+       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);
+       }
+       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)
@@ -214,16 +320,23 @@ void pcs_fuse_stat_io_count(struct pcs_int_request *ireq, 
struct pcs_msg *resp)
 {
        struct pcs_cluster_core *cc = ireq->cc;
        struct pcs_fuse_stat *stat = &cc->stat;
+       struct fuse_io_cnt *fstat = &ireq->dentry->stat;
        struct pcs_cs_iohdr *h = (struct pcs_cs_iohdr *)msg_inline_head(resp);
        struct fuse_val_cnt *se = req_stat_entry(&stat->io, h->hdr.type);
        u64 size = h->hdr.type != PCS_CS_SYNC_RESP ? ireq->iochunk.size : 0;
 
-       if (unlikely(!se))
-               return;
+       if (likely(se)) {
+               spin_lock(&stat->lock);
+               fuse_val_stat_update(&se->curr, size);
+               spin_unlock(&stat->lock);
+       }
 
-       spin_lock(&stat->lock);
-       fuse_val_stat_update(&se->curr, size);
-       spin_unlock(&stat->lock);
+       se = req_stat_entry(&fstat->io, h->hdr.type);
+       if (likely(se)) {
+               spin_lock(&fstat->lock);
+               fuse_val_stat_update(&se->curr, size);
+               spin_unlock(&fstat->lock);
+       }
 }
 
 static void pcs_fuse_stat_work(struct work_struct *w)
@@ -238,6 +351,8 @@ static void pcs_fuse_stat_work(struct work_struct *w)
        fuse_val_cnt_up(&stat->io.flush_cnt);
        spin_unlock(&stat->lock);
 
+       pcs_fuse_stat_files_up(cc);
+
        mod_delayed_work(cc->wq, &cc->stat.work, STAT_TIMER_PERIOD * HZ);
 }
 
@@ -317,6 +432,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);
 out:
        mutex_unlock(&fuse_mutex);
 }
@@ -332,6 +451,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 a6f3a7abe456..b65620b51738 100644
--- a/fs/fuse/kio/pcs/fuse_stat.h
+++ b/fs/fuse/kio/pcs/fuse_stat.h
@@ -3,6 +3,9 @@
 
 #define STAT_TIMER_PERIOD 5
 
+struct pcs_msg;
+struct pcs_int_request;
+
 struct fuse_val_stat {
        u64 events;
        u64 val_total;
@@ -30,6 +33,14 @@ 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 io;
+
+       abs_time_t created_ts;
+       spinlock_t lock;
 };
 
 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 d837bf3051ed..3ae6e4e9385a 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -352,6 +352,8 @@ 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);
+       spin_lock_init(&di->stat.lock);
+       di->stat.created_ts = jiffies;
 
        pcs_mapping_init(&pfc->cc, &di->mapping);
        pcs_set_fileinfo(di, &info);

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to