[Devel] [PATCH v2 12/14] fs/fuse kio: implement cs statistics accounting
Pavel Butsykin
pbutsykin at virtuozzo.com
Fri May 24 18:55:01 MSK 2019
This is preparation patch that adds the implementation of calculating statistics
for cs objects. Backport from user-mod vstorage client.
Signed-off-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
---
fs/fuse/kio/pcs/fuse_stat.c | 2 +-
fs/fuse/kio/pcs/fuse_stat.h | 1 +
fs/fuse/kio/pcs/pcs_cs.c | 72 ++++++++++++++++++++++++++++++---
fs/fuse/kio/pcs/pcs_cs.h | 34 ++++++++++------
fs/fuse/kio/pcs/pcs_perfcounters.h | 17 +++++++-
fs/fuse/kio/pcs/pcs_perfcounters_stub.h | 30 --------------
6 files changed, 104 insertions(+), 52 deletions(-)
delete mode 100644 fs/fuse/kio/pcs/pcs_perfcounters_stub.h
diff --git a/fs/fuse/kio/pcs/fuse_stat.c b/fs/fuse/kio/pcs/fuse_stat.c
index 53398514e841..f54f29c5bae8 100644
--- a/fs/fuse/kio/pcs/fuse_stat.c
+++ b/fs/fuse/kio/pcs/fuse_stat.c
@@ -44,7 +44,7 @@ static inline void fuse_val_stat_update(struct fuse_val_stat *s, u64 val)
preempt_enable();
}
-static inline void fuse_latency_update(struct fuse_lat_stat *s, u64 val)
+void fuse_latency_update(struct fuse_lat_stat *s, u64 val)
{
int i;
diff --git a/fs/fuse/kio/pcs/fuse_stat.h b/fs/fuse/kio/pcs/fuse_stat.h
index dae495cd79aa..b6d513bed7ea 100644
--- a/fs/fuse/kio/pcs/fuse_stat.h
+++ b/fs/fuse/kio/pcs/fuse_stat.h
@@ -79,6 +79,7 @@ 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,
u32 io_lat, u32 net_lat);
+void fuse_latency_update(struct fuse_lat_stat *s, u64 val);
int pcs_fuse_io_stat_alloc(struct pcs_fuse_io_stat_sync *iostat);
void pcs_fuse_io_stat_free(struct pcs_fuse_io_stat_sync *iostat);
diff --git a/fs/fuse/kio/pcs/pcs_cs.c b/fs/fuse/kio/pcs/pcs_cs.c
index 28dfc10246de..93b121127595 100644
--- a/fs/fuse/kio/pcs/pcs_cs.c
+++ b/fs/fuse/kio/pcs/pcs_cs.c
@@ -46,6 +46,50 @@ struct pcs_rpc_ops cn_rpc_ops = {
.connect = cs_connect,
};
+static int pcs_cs_percpu_stat_alloc(struct pcs_cs *cs)
+{
+ seqlock_init(&cs->stat.seqlock);
+ cs->stat.iolat = alloc_percpu(struct fuse_lat_stat);
+ if (!cs->stat.iolat)
+ return -ENOMEM;
+
+ cs->stat.netlat = alloc_percpu(struct fuse_lat_stat);
+ if (!cs->stat.netlat)
+ goto fail1;
+
+ cs->stat.read_ops_rate = alloc_percpu(struct pcs_perf_rate_cnt);
+ if (!cs->stat.read_ops_rate)
+ goto fail2;
+
+ cs->stat.write_ops_rate = alloc_percpu(struct pcs_perf_rate_cnt);
+ if (!cs->stat.write_ops_rate)
+ goto fail3;
+
+ cs->stat.sync_ops_rate = alloc_percpu(struct pcs_perf_rate_cnt);
+ if (!cs->stat.sync_ops_rate)
+ goto fail4;
+
+ return 0;
+fail4:
+ free_percpu(cs->stat.write_ops_rate);
+fail3:
+ free_percpu(cs->stat.read_ops_rate);
+fail2:
+ free_percpu(cs->stat.netlat);
+fail1:
+ free_percpu(cs->stat.iolat);
+ return -ENOMEM;
+}
+
+static void pcs_cs_percpu_stat_free(struct pcs_cs *cs)
+{
+ free_percpu(cs->stat.sync_ops_rate);
+ free_percpu(cs->stat.write_ops_rate);
+ free_percpu(cs->stat.read_ops_rate);
+ free_percpu(cs->stat.netlat);
+ free_percpu(cs->stat.iolat);
+}
+
struct pcs_cs *pcs_cs_alloc(struct pcs_cs_set *css,
struct pcs_cluster_core *cc)
{
@@ -70,8 +114,13 @@ struct pcs_cs *pcs_cs_alloc(struct pcs_cs_set *css,
INIT_LIST_HEAD(&cs->flow_lru);
INIT_LIST_HEAD(&cs->bl_link);
+ if (pcs_cs_percpu_stat_alloc(cs)) {
+ kfree(cs);
+ return NULL;
+ }
cs->rpc = pcs_rpc_create(&cc->eng, &cn_rpc_params, &cn_rpc_ops);
if (cs->rpc == NULL) {
+ pcs_cs_percpu_stat_free(cs);
kfree(cs);
return NULL;
}
@@ -296,20 +345,24 @@ void cs_log_io_times(struct pcs_int_request * ireq, struct pcs_msg * resp, unsig
void pcs_cs_update_stat(struct pcs_cs *cs, u32 iolat, u32 netlat, int op_type)
{
- pcs_perfcounter_stat_update(&cs->stat.iolat, iolat);
- pcs_perfcounter_stat_update(&cs->stat.netlat, netlat);
+ write_seqlock(&cs->stat.seqlock);
+ preempt_disable();
+ fuse_latency_update(cs->stat.iolat, iolat);
+ fuse_latency_update(cs->stat.netlat, netlat);
switch (op_type) {
case PCS_CS_WRITE_SYNC_RESP:
case PCS_CS_WRITE_RESP:
- cs->stat.write_ops_rate.total++;
+ this_cpu_inc(cs->stat.write_ops_rate->total);
break;
case PCS_CS_READ_RESP:
- cs->stat.read_ops_rate.total++;
+ this_cpu_inc(cs->stat.read_ops_rate->total);
break;
case PCS_CS_SYNC_RESP:
- cs->stat.sync_ops_rate.total++;
+ this_cpu_inc(cs->stat.sync_ops_rate->total);
break;
}
+ preempt_enable();
+ write_sequnlock(&cs->stat.seqlock);
}
static void cs_response_done(struct pcs_msg *msg)
@@ -753,6 +806,13 @@ static void pcs_cs_isolate(struct pcs_cs *cs, struct list_head *dispose)
BUG_ON(cs->nflows);
}
+static void cs_destroy_rcu(struct rcu_head *head)
+{
+ struct pcs_cs *cs = container_of(head, struct pcs_cs, rcu);
+ pcs_cs_percpu_stat_free(cs);
+ kfree(cs);
+}
+
static void pcs_cs_destroy(struct pcs_cs *cs)
{
BUG_ON(!list_empty(&cs->active_list));
@@ -763,7 +823,7 @@ static void pcs_cs_destroy(struct pcs_cs *cs)
pcs_rpc_close(cs->rpc);
cs->rpc = NULL;
}
- kfree_rcu(cs, rcu);
+ call_rcu(&cs->rcu, cs_destroy_rcu);
}
void cs_aborting(struct pcs_rpc *ep, int error)
diff --git a/fs/fuse/kio/pcs/pcs_cs.h b/fs/fuse/kio/pcs/pcs_cs.h
index 1fb40936d046..8bdd056b5196 100644
--- a/fs/fuse/kio/pcs/pcs_cs.h
+++ b/fs/fuse/kio/pcs/pcs_cs.h
@@ -90,11 +90,12 @@ struct pcs_cs {
struct list_head map_list;
struct {
- struct pcs_perf_stat_cnt iolat;
- struct pcs_perf_stat_cnt netlat;
- struct pcs_perf_rate_cnt read_ops_rate;
- struct pcs_perf_rate_cnt write_ops_rate;
- struct pcs_perf_rate_cnt sync_ops_rate;
+ struct fuse_lat_stat __percpu *iolat;
+ struct fuse_lat_stat __percpu *netlat;
+ struct pcs_perf_rate_cnt __percpu *read_ops_rate;
+ struct pcs_perf_rate_cnt __percpu *write_ops_rate;
+ struct pcs_perf_rate_cnt __percpu *sync_ops_rate;
+ seqlock_t seqlock;
} stat;
};
@@ -160,14 +161,21 @@ void pcs_cs_update_stat(struct pcs_cs *cs, u32 iolat, u32 netlat, int op_type);
static inline void pcs_cs_stat_up(struct pcs_cs *cs)
{
-#if 0
- /* TODO: temproraly disable perf counters */
- pcs_perfcounter_stat_up(&cs->stat.iolat);
- pcs_perfcounter_stat_up(&cs->stat.netlat);
- pcs_perfcounter_up_rate(&cs->stat.write_ops_rate);
- pcs_perfcounter_up_rate(&cs->stat.read_ops_rate);
- pcs_perfcounter_up_rate(&cs->stat.sync_ops_rate);
-#endif
+ int cpu;
+
+ write_seqlock(&cs->stat.seqlock);
+ for_each_possible_cpu(cpu) {
+ struct pcs_perf_rate_cnt *rate;
+ rate = per_cpu_ptr(cs->stat.write_ops_rate, cpu);
+ pcs_perfcounter_up_rate(rate);
+
+ rate = per_cpu_ptr(cs->stat.read_ops_rate, cpu);
+ pcs_perfcounter_up_rate(rate);
+
+ rate = per_cpu_ptr(cs->stat.sync_ops_rate, cpu);
+ pcs_perfcounter_up_rate(rate);
+ }
+ write_sequnlock(&cs->stat.seqlock);
}
static inline bool cs_is_blacklisted(struct pcs_cs *cs)
diff --git a/fs/fuse/kio/pcs/pcs_perfcounters.h b/fs/fuse/kio/pcs/pcs_perfcounters.h
index f902ce06d72d..3ae4db2ff049 100644
--- a/fs/fuse/kio/pcs/pcs_perfcounters.h
+++ b/fs/fuse/kio/pcs/pcs_perfcounters.h
@@ -1,7 +1,20 @@
#ifndef _PCS_PERFCOUNTERS_H_
#define _PCS_PERFCOUNTERS_H_ 1
-/* TODO:!!! this is stump for flow_detection */
-#include "pcs_perfcounters_stub.h"
+/* Generic event rate counter */
+struct pcs_perf_rate_cnt {
+ /* Total number of events */
+ u64 total;
+ u64 last_total;
+ /* The number of events for the last 5 sec interval */
+ u64 rate;
+};
+
+static inline void pcs_perfcounter_up_rate(struct pcs_perf_rate_cnt* cnt)
+{
+ BUG_ON(cnt->total < cnt->last_total);
+ cnt->rate = cnt->total - cnt->last_total;
+ cnt->last_total = cnt->total;
+}
#endif /* _PCS_PERFCOUNTERS_H_ */
diff --git a/fs/fuse/kio/pcs/pcs_perfcounters_stub.h b/fs/fuse/kio/pcs/pcs_perfcounters_stub.h
deleted file mode 100644
index 17dae73fcd08..000000000000
--- a/fs/fuse/kio/pcs/pcs_perfcounters_stub.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef _PCS_PERFCOUNTERS_STUB_H_
-#define _PCS_PERFCOUNTERS_STUB_H_ 1
-
-
-struct pcs_perf_stat_cnt {
- u64 val_total;
- u64 events;
- u64 curr_max;
- u64 events_last;
- u64 avg;
- u64 maximum;
-};
-
-/* Generic event rate counter */
-struct pcs_perf_rate_cnt {
- /* Total number of events */
- u64 total;
- u64 last_total;
- /* The number of events for the last 5 sec interval */
- u64 rate;
- /* The number of events per 5 sec averaged over 1, 5, 15 min and shifted by AV_SHIFT to the left */
- u64 av1;
- u64 av5;
-};
-
-
-static inline void pcs_perfcounter_stat_update(struct pcs_perf_stat_cnt *cnt, u64 val) __attribute__((unused));
-
-static inline void pcs_perfcounter_stat_update(struct pcs_perf_stat_cnt *cnt, u64 val) {}
-#endif //_PCS_PERFCOUNTERS_STUB_H_
--
2.15.1
More information about the Devel
mailing list