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