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 985998e70e6a3e1d9507de69035f39f8752d9459
Author: Pavel Butsykin <pbutsy...@virtuozzo.com>
Date:   Tue May 21 18:47:44 2019 +0300

    fs/fuse kio: implement fstat_lat statistics info
    
    This statistic shows latency of requests for each open kio file. Latency is
    displayed for 99 and 95 percentile in the following time ranges: 20ms, 50ms,
    100ms, 200ms, 500ms. In turn, the request latency is detailed in three 
parts:
    pending_lat - time spent in the queue
    net_lat     - time spent in the network
    io_lat      - disk operation time
    
    example:
    # rw open/age inactive  net_lat                      net_lat_global         
      io_lat                       io_lat_global                plat            
             plat_global                  path
    rw       2/6360    0    (5% > 500ms, 1% > 500ms)     (5% > 500ms, 1% > 
500ms)     (95% <= 20ms, 99% <= 50ms)   (95% <= 20ms, 99% <= 50ms)   (95% <= 
20ms, 99% <= 20ms)   (95% <= 20ms, 99% <= 20ms)   
/fio_test/randasyncread_jobs24_4k.0.0
    rw       2/6360    0    (5% > 500ms, 1% > 500ms)     (5% > 500ms, 1% > 
500ms)     (95% <= 20ms, 99% <= 50ms)   (95% <= 20ms, 99% <= 20ms)   (95% <= 
20ms, 99% <= 20ms)   (95% <= 20ms, 99% <= 20ms)   
/fio_test/randasyncread_jobs24_4k.1.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 | 183 +++++++++++++++++++++++++++++++++++++++++++-
 fs/fuse/kio/pcs/fuse_stat.h |  30 +++++++-
 fs/fuse/kio/pcs/pcs_map.c   |   2 +-
 3 files changed, 212 insertions(+), 3 deletions(-)

diff --git a/fs/fuse/kio/pcs/fuse_stat.c b/fs/fuse/kio/pcs/fuse_stat.c
index 85c8f7e04413..452bb4e9664c 100644
--- a/fs/fuse/kio/pcs/fuse_stat.c
+++ b/fs/fuse/kio/pcs/fuse_stat.c
@@ -7,6 +7,44 @@
 
 extern struct super_block *fuse_control_sb;
 
+static u64 lat_oreder_list[] = {
+       [LAT_ORDER1] = 20 * USEC_PER_MSEC,
+       [LAT_ORDER2] = 50 * USEC_PER_MSEC,
+       [LAT_ORDER3] = 100 * USEC_PER_MSEC,
+       [LAT_ORDER4] = 200 * USEC_PER_MSEC,
+       [LAT_ORDER5] = 500 * USEC_PER_MSEC,
+};
+
+
+static void fuse_latency_update(struct fuse_lat_stat *s, u64 lat)
+{
+       int i;
+
+       s->count++;
+
+       for (i = LAT_ORDER1; i <= LAT_ORDER5; i++) {
+               if (likely(lat <= lat_oreder_list[i])) {
+                       s->lat[i]++;
+                       return;
+               }
+       }
+       s->lat[LAT_ORDER_OTHER]++;
+       return;
+}
+
+static inline void fuse_latency_count(struct fuse_lat_cnt *c, u64 val)
+{
+       fuse_latency_update(&c->curr, val);
+       fuse_latency_update(&c->glob, val);
+}
+
+static inline void fuse_latency_cnt_up(struct fuse_lat_cnt *c)
+{
+       BUILD_BUG_ON(sizeof(c->last) != sizeof(c->curr));
+
+       memcpy(&c->last, &c->curr, sizeof(c->last));
+       memset(&c->curr, 0, sizeof(c->curr));
+}
 
 static const char *fuse_kio_op_name(unsigned opcode)
 {
@@ -96,12 +134,142 @@ static inline unsigned long long fuse_val_cnt_max(struct 
fuse_val_cnt const* c)
 #define CNT_MAX(c)    fuse_val_cnt_max(&(c))
 
 
+#define MAX_PERCENT 100
+static int latency_npercl_format(struct fuse_lat_stat *s, u8 percl, char *buf,
+                                size_t sz)
+{
+       u64 cnt = s->count, nper;
+       int i;
+
+       BUG_ON(percl > MAX_PERCENT);
+
+       if (!cnt)
+               return 0;
+
+       nper = cnt * (MAX_PERCENT - percl);
+       if (s->lat[LAT_ORDER_OTHER] * MAX_PERCENT >= nper)
+               return scnprintf(buf, sz, "%u%% > %llums", MAX_PERCENT - percl,
+                                lat_oreder_list[LAT_ORDER_OTHER - 1] / 1000);
+
+       for(i = LAT_ORDER_OTHER - 1; i >= 0; i--) {
+               if (s->lat[i] * MAX_PERCENT >= nper)
+                       return scnprintf(buf, sz, "%u%% <= %llums", percl,
+                                        lat_oreder_list[i] / 1000);
+       }
+       BUG();
+       return 0;
+}
+
+#define LAT_LINE_MAX 27
+static void latency_percl_print(struct fuse_lat_stat *s, struct seq_file *m)
+{
+       int n, icnt = LAT_LINE_MAX;
+       char buf[LAT_LINE_MAX];
+
+       seq_printf(m, "(");
+       n = latency_npercl_format(s, 95, buf, sizeof(buf) - 1);
+       if (n) {
+               seq_printf(m,"%.*s, ", n, buf);
+               icnt -= n;
+               icnt -= 2;
+       }
+       n = latency_npercl_format(s, 99, buf, sizeof(buf) - 1);
+       if (n) {
+               seq_printf(m, "%.*s", n, buf);
+               icnt -= n;
+       }
+
+       WARN_ON(icnt < 0);
+       seq_printf(m, ")%*s", max(icnt, 0), "");
+}
+
+static void fuse_kio_fstat_lat_itr(struct fuse_file *ff,
+                                  struct pcs_dentry_info *di, void *ctx)
+{
+       struct seq_file *m = ctx;
+       struct fuse_io_cnt *fstat = &di->stat;
+       umode_t mode = di->inode->inode.i_mode;
+       abs_time_t now = jiffies;
+       struct fuse_lat_cnt io_lat;
+       struct fuse_lat_cnt net_lat;
+       struct fuse_lat_cnt pending_lat;
+
+       seq_printf(m, "%s%s %7u/%-7llu %-5u",
+                  mode & S_IRUGO ? "r": "", mode & S_IWUGO ? "w": "",
+                  atomic_read(&ff->count), (now - di->stat.created_ts) / 1000, 
0);
+
+       spin_lock(&fstat->lock);
+       io_lat = fstat->io_lat;
+       net_lat = fstat->net_lat;
+       pending_lat = fstat->pending_lat;
+       spin_unlock(&fstat->lock);
+
+       latency_percl_print(&net_lat.last, m);
+       latency_percl_print(&net_lat.glob, m);
+
+       latency_percl_print(&io_lat.last, m);
+       latency_percl_print(&io_lat.glob, m);
+
+       latency_percl_print(&pending_lat.last, m);
+       latency_percl_print(&pending_lat.glob, m);
+
+       seq_dentry(m, ff->ff_dentry, "");
+       seq_putc(m, '\n');
+}
+
+static int pcs_fuse_fstat_lat_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  net_lat\t\t\t     
net_lat_global\t\t  io_lat\t\t       io_lat_global\t\t    plat\t\t\t 
plat_global\t\t      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_lat_itr, m);
+               spin_unlock(&fc->lock);
+       }
+       mutex_unlock(&fuse_mutex);
+
+
+       return 0;
+}
+
+static int pcs_fuse_fstat_lat_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, pcs_fuse_fstat_lat_show, inode);
+}
+
+static const struct file_operations pcs_fuse_fstat_lat_ops = {
+       .owner   = THIS_MODULE,
+       .open    = pcs_fuse_fstat_lat_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = single_release,
+};
+
 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_latency_cnt_up(&fstat->io_lat);
+       fuse_latency_cnt_up(&fstat->net_lat);
+       fuse_latency_cnt_up(&fstat->pending_lat);
+
        fuse_val_cnt_up(&fstat->io.read_bytes);
        fuse_val_cnt_up(&fstat->io.write_bytes);
        fuse_val_cnt_up(&fstat->io.flush_cnt);
@@ -316,7 +484,8 @@ struct fuse_val_cnt *req_stat_entry(struct pcs_fuse_io_stat 
*io, u32 type)
        return NULL;
 }
 
-void pcs_fuse_stat_io_count(struct pcs_int_request *ireq, struct pcs_msg *resp)
+void pcs_fuse_stat_io_count(struct pcs_int_request *ireq, struct pcs_msg *resp,
+                           u32 io_lat, u32 net_lat)
 {
        struct pcs_cluster_core *cc = ireq->cc;
        struct pcs_fuse_stat *stat = &cc->stat;
@@ -333,7 +502,13 @@ void pcs_fuse_stat_io_count(struct pcs_int_request *ireq, 
struct pcs_msg *resp)
 
        se = req_stat_entry(&fstat->io, h->hdr.type);
        if (likely(se)) {
+               u32 pending_lat = ktime_to_us(ktime_sub(ireq->ts_sent, 
ireq->ts));
+
                spin_lock(&fstat->lock);
+               fuse_latency_count(&fstat->pending_lat, pending_lat);
+               fuse_latency_count(&fstat->io_lat, io_lat);
+               fuse_latency_count(&fstat->net_lat, net_lat);
+
                fuse_val_stat_update(&se->curr, size);
                spin_unlock(&fstat->lock);
        }
@@ -436,6 +611,10 @@ void pcs_fuse_stat_init(struct pcs_fuse_stat *stat)
        stat->fstat = fuse_kio_add_dentry(stat->kio_stat, fc, "fstat",
                                          S_IFREG | S_IRUSR, 1, NULL,
                                          &pcs_fuse_fstat_ops, 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);
 out:
        mutex_unlock(&fuse_mutex);
 }
@@ -453,6 +632,8 @@ void pcs_fuse_stat_fini(struct pcs_fuse_stat *stat)
                        fuse_kio_rm_dentry(stat->requests);
                if (stat->fstat)
                        fuse_kio_rm_dentry(stat->fstat);
+               if (stat->fstat_lat)
+                       fuse_kio_rm_dentry(stat->fstat_lat);
                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 b65620b51738..32971cf77dc4 100644
--- a/fs/fuse/kio/pcs/fuse_stat.h
+++ b/fs/fuse/kio/pcs/fuse_stat.h
@@ -34,11 +34,38 @@ struct pcs_fuse_stat {
        struct dentry *iostat;
        struct dentry *requests;
        struct dentry *fstat;
+       struct dentry *fstat_lat;
+};
+
+enum {
+       LAT_ORDER1 = 0,
+       LAT_ORDER2 = 1,
+       LAT_ORDER3 = 2,
+       LAT_ORDER4 = 3,
+       LAT_ORDER5 = 4,
+       LAT_ORDER_OTHER = 5,
+};
+
+#define LATENCY_ORDER_MAX (LAT_ORDER_OTHER + 1)
+
+struct fuse_lat_stat {
+       u64 lat[LATENCY_ORDER_MAX];
+       u64 count;
+};
+
+struct fuse_lat_cnt {
+       struct fuse_lat_stat  curr;
+       struct fuse_lat_stat  last;
+       struct fuse_lat_stat  glob;
 };
 
 struct fuse_io_cnt {
        struct pcs_fuse_io_stat io;
 
+       struct fuse_lat_cnt io_lat;
+       struct fuse_lat_cnt net_lat;
+       struct fuse_lat_cnt pending_lat;
+
        abs_time_t created_ts;
        spinlock_t lock;
 };
@@ -46,6 +73,7 @@ struct fuse_io_cnt {
 void pcs_fuse_stat_init(struct pcs_fuse_stat *stat);
 void pcs_fuse_stat_fini(struct pcs_fuse_stat *stat);
 
-void pcs_fuse_stat_io_count(struct pcs_int_request *ireq, struct pcs_msg 
*resp);
+void pcs_fuse_stat_io_count(struct pcs_int_request *ireq, struct pcs_msg *resp,
+                           u32 io_lat, u32 net_lat);
 
 #endif /* _FUSE_STAT_H_ */
diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c
index 59de04be0512..c1cacae38fe4 100644
--- a/fs/fuse/kio/pcs/pcs_map.c
+++ b/fs/fuse/kio/pcs/pcs_map.c
@@ -2711,7 +2711,7 @@ static int commit_sync_info(struct pcs_int_request *req,
                                max_iolat = srec->sync.ts_io;
                }
        }
-       pcs_fuse_stat_io_count(req, resp);
+       pcs_fuse_stat_io_count(req, resp, max_iolat, lat - max_iolat);
        cs_log_io_times(req, resp, max_iolat);
 
        evaluate_dirty_status(m);

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

Reply via email to