<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<meta content="text/html; charset=UTF-8">
<style type="text/css" style="">
<!--
p
        {margin-top:0;
        margin-bottom:0}
-->
</style>
<div dir="ltr">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:#000000; font-family:Calibri,Helvetica,sans-serif">
<p>ack</p>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> Yuriy Vasilev <yuriy.vasilev@virtuozzo.com><br>
<b>Sent:</b> Thursday, July 27, 2023 7:50:30 PM<br>
<b>To:</b> Alexey Kuznetsov<br>
<b>Cc:</b> Andrey Zaitsev; Devel; yuriy.vasilev@virtuozzo.com<br>
<b>Subject:</b> [PATCH vz9 v3] fs/fuse kio: implement rpc errors collection</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">Implement collecting rpc errors and exporting them to userspace fuse<br>
daemon via relayfs.<br>
Errors are grouped per IP addresses and exported as a field of<br>
kfuse_metrics struct. This field is updated on each read.<br>
<br>
Also move pcs_net* functions to a separate file.<br>
<br>
Affects: #VSTOR-70161<br>
<a href="https://pmc.acronis.work/browse/VSTOR-70161">https://pmc.acronis.work/browse/VSTOR-70161</a><br>
<br>
Signed-off-by: Yuriy Vasilev <yuriy.vasilev@virtuozzo.com><br>
---<br>
v2: Replace flex array with a single struct containing a 'next' field<br>
that refreshes after each successful read, provided there is a next elem<br>
in the list. Now, after reading, only head of an rpc errors list is<br>
cleaned.<br>
Replace spinlock with mutex. Also, remove rpc errors accounting as it is<br>
not necessary now.<br>
Add more rpc error types.<br>
<br>
v3: Fixed copying. Now, copying and removal occur in one place. First,<br>
under mutex an error record is removed from list, and this record is<br>
copied to stat struct. fuse_error_metrics is now part of fuse_ktrace,<br>
unnecessary memory management code for it has been removed.<br>
---<br>
fs/fuse/Makefile | 3 +-<br>
fs/fuse/kio/pcs/fuse_ktrace.h | 1 +<br>
fs/fuse/kio/pcs/fuse_prometheus.h | 18 +++++<br>
fs/fuse/kio/pcs/fuse_prometheus_prot.h | 19 ++++++<br>
fs/fuse/kio/pcs/pcs_cs.c | 34 +---------<br>
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 87 ++++++++++++++++++++++--<br>
fs/fuse/kio/pcs/pcs_net_addr.c | 93 ++++++++++++++++++++++++++<br>
fs/fuse/kio/pcs/pcs_net_addr.h | 16 +++++<br>
fs/fuse/kio/pcs/pcs_rdma_conn.c | 4 ++<br>
fs/fuse/kio/pcs/pcs_rpc.c | 27 ++++++--<br>
fs/fuse/kio/pcs/pcs_rpc.h | 3 +<br>
fs/fuse/kio/pcs/pcs_sock_conn.c | 29 ++------<br>
fs/fuse/kio/pcs/pcs_sock_conn.h | 1 -<br>
13 files changed, 264 insertions(+), 71 deletions(-)<br>
create mode 100644 fs/fuse/kio/pcs/pcs_net_addr.c<br>
create mode 100644 fs/fuse/kio/pcs/pcs_net_addr.h<br>
<br>
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile<br>
index cc0d0c1d63b3..37ef32ffa13d 100644<br>
--- a/fs/fuse/Makefile<br>
+++ b/fs/fuse/Makefile<br>
@@ -31,6 +31,7 @@ fuse_kio_pcs-objs := kio/pcs/pcs_fuse_kdirect.o \<br>
kio/pcs/pcs_auth.o \<br>
kio/pcs/pcs_rdma_io.o \<br>
kio/pcs/pcs_rdma_rw.o \<br>
- kio/pcs/pcs_rdma_conn.o<br>
+ kio/pcs/pcs_rdma_conn.o \<br>
+ kio/pcs/pcs_net_addr.o<br>
<br>
virtiofs-y := virtio_fs.o<br>
diff --git a/fs/fuse/kio/pcs/fuse_ktrace.h b/fs/fuse/kio/pcs/fuse_ktrace.h<br>
index aef368fcacef..72342342b8da 100644<br>
--- a/fs/fuse/kio/pcs/fuse_ktrace.h<br>
+++ b/fs/fuse/kio/pcs/fuse_ktrace.h<br>
@@ -29,6 +29,7 @@ struct fuse_ktrace<br>
struct dentry *prometheus_dentry;<br>
struct kfuse_metrics __percpu *prometheus_metrics;<br>
u8 * __percpu buf;<br>
+ struct fuse_error_metrics error_metrics;<br>
};<br>
<br>
static inline void * fuse_trace_prepare(struct fuse_ktrace * tr, int type, int len)<br>
diff --git a/fs/fuse/kio/pcs/fuse_prometheus.h b/fs/fuse/kio/pcs/fuse_prometheus.h<br>
index 3f1b31c290d6..6dba65409077 100644<br>
--- a/fs/fuse/kio/pcs/fuse_prometheus.h<br>
+++ b/fs/fuse/kio/pcs/fuse_prometheus.h<br>
@@ -15,4 +15,22 @@ struct fuse_prometheus_data<br>
struct kfuse_histogram __percpu *histo;<br>
};<br>
<br>
+struct fuse_rpc_error {<br>
+ PCS_NET_ADDR_T addr;<br>
+ u64 err[PCS_RPC_ERR_MAX];<br>
+};<br>
+<br>
+struct fuse_rpc_error_metric {<br>
+ struct fuse_rpc_error m;<br>
+ struct list_head list;<br>
+};<br>
+<br>
+struct fuse_error_metrics {<br>
+ struct mutex mutex;<br>
+ struct list_head fuse_rpc_error_metric_list;<br>
+};<br>
+<br>
+void fuse_rpc_error_account(struct fuse_error_metrics *metrics,<br>
+ PCS_NET_ADDR_T const *addr, unsigned int err, u64 val);<br>
+<br>
#endif /* __FUSE_PROMETHEUS_H__ */<br>
diff --git a/fs/fuse/kio/pcs/fuse_prometheus_prot.h b/fs/fuse/kio/pcs/fuse_prometheus_prot.h<br>
index e7b6f8a52d26..eeaa2420a063 100644<br>
--- a/fs/fuse/kio/pcs/fuse_prometheus_prot.h<br>
+++ b/fs/fuse/kio/pcs/fuse_prometheus_prot.h<br>
@@ -39,6 +39,22 @@ struct kfuse_counter {<br>
u64 val_total;<br>
};<br>
<br>
+#define PCS_RPC_ERR_CONNECT_TOUT 0<br>
+#define PCS_RPC_ERR_CONNECT_ERROR 1<br>
+#define PCS_RPC_ERR_AUTH_TOUT 2<br>
+#define PCS_RPC_ERR_AUTH_ERR 3<br>
+#define PCS_RPC_ERR_RESPONSE_TOUT 4<br>
+#define PCS_RPC_ERR_ABORTED 5<br>
+#define PCS_RPC_ERR_MAX 6<br>
+<br>
+#define MAX_RPC_ADDR_LEN 46<br>
+<br>
+struct kfuse_rpc_error {<br>
+ char address[MAX_RPC_ADDR_LEN];<br>
+ u64 error[PCS_RPC_ERR_MAX];<br>
+ int has_next;<br>
+};<br>
+<br>
struct kfuse_metrics {<br>
/* Histograms are compatible with old version of proto<br>
* between userspace and kio where the counters were skipped.<br>
@@ -51,6 +67,9 @@ struct kfuse_metrics {<br>
u64 stucked_reqs_cnt_8s;<br>
u64 stucked_reqs_cnt_30s;<br>
u64 stucked_reqs_cnt_120s;<br>
+<br>
+ /* Each read triggers replacement of this field with the next one from a list */<br>
+ struct kfuse_rpc_error rpc_error;<br>
};<br>
<br>
#endif /* __FUSE_PROMETHEUS_PROT__ */<br>
diff --git a/fs/fuse/kio/pcs/pcs_cs.c b/fs/fuse/kio/pcs/pcs_cs.c<br>
index 9d81fe8bf22c..13e2b4e6b50c 100644<br>
--- a/fs/fuse/kio/pcs/pcs_cs.c<br>
+++ b/fs/fuse/kio/pcs/pcs_cs.c<br>
@@ -24,6 +24,7 @@<br>
#include "pcs_ioctl.h"<br>
#include "log.h"<br>
#include "fuse_ktrace.h"<br>
+#include "pcs_net_addr.h"<br>
<br>
/* Lock order: cs->lock -> css->lock (lru, hash, bl_list) */<br>
<br>
@@ -210,38 +211,6 @@ static void add_cs(struct pcs_cs_set *csset, struct pcs_cs *cs)<br>
hlist_add_head_rcu(&cs->hlist, &csset->ht[hash]);<br>
}<br>
<br>
-static inline int netaddr_cmp(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2, int ignore_port)<br>
-{<br>
- unsigned int d;<br>
- size_t sz = 0;<br>
-<br>
- d = addr1->type - addr2->type;<br>
- if (d)<br>
- return d;<br>
- d = addr1->port - addr2->port;<br>
- if (!ignore_port && d)<br>
- return d;<br>
-<br>
- switch (addr1->type) {<br>
- case PCS_ADDRTYPE_IP:<br>
- case PCS_ADDRTYPE_RDMA:<br>
- sz = sizeof(struct in_addr);<br>
- break;<br>
- case PCS_ADDRTYPE_IP6:<br>
- sz = sizeof(struct in6_addr);<br>
- break;<br>
- default:<br>
- BUG();<br>
- }<br>
-<br>
- return memcmp(addr1->address, addr2->address, sz);<br>
-}<br>
-<br>
-static int pcs_netaddr_cmp(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2)<br>
-{<br>
- return netaddr_cmp(addr1, addr2, 0);<br>
-}<br>
-<br>
/* Return locked cs */<br>
struct pcs_cs *pcs_cs_find_create(struct pcs_cs_set *csset, PCS_NODE_ID_T *id, PCS_NET_ADDR_T *addr, int flags)<br>
{<br>
@@ -502,6 +471,7 @@ static void cs_connect(struct pcs_rpc *ep)<br>
connect_start(ep); /* TODO: rewrite to use pcs_netconnect callback */<br>
return;<br>
fail:<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);<br>
pcs_rpc_reset(ep);<br>
return;<br>
}<br>
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c<br>
index af008e63294c..706da8e536c9 100644<br>
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c<br>
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c<br>
@@ -34,6 +34,7 @@<br>
#include "pcs_rpc.h"<br>
#include "fuse_ktrace.h"<br>
#include "fuse_prometheus.h"<br>
+#include "pcs_net_addr.h"<br>
<br>
unsigned int pcs_loglevel = LOG_TRACE;<br>
module_param(pcs_loglevel, uint, 0644);<br>
@@ -1243,6 +1244,8 @@ static void kpcs_req_send(struct fuse_req *req, bool bg)<br>
return;<br>
}<br>
<br>
+static void fuse_rpc_error_metrics_clean(struct fuse_error_metrics *metrics);<br>
+<br>
static void fuse_trace_free(struct fuse_ktrace *tr)<br>
{<br>
relay_close(tr->rchan);<br>
@@ -1254,6 +1257,7 @@ static void fuse_trace_free(struct fuse_ktrace *tr)<br>
free_percpu(tr->prometheus_metrics);<br>
free_percpu(tr->buf);<br>
debugfs_remove(tr->dir);<br>
+ fuse_rpc_error_metrics_clean(&tr->error_metrics);<br>
if (tr->fc)<br>
fuse_conn_put(tr->fc);<br>
kfree(tr);<br>
@@ -1359,6 +1363,73 @@ void fuse_stat_account(struct fuse_conn *fc, int op, u64 val)<br>
}<br>
}<br>
<br>
+static void fuse_rpc_error_metrics_clean(struct fuse_error_metrics *metrics)<br>
+{<br>
+ struct fuse_rpc_error_metric *entry, *next;<br>
+<br>
+ mutex_lock(&metrics->mutex);<br>
+ list_for_each_entry_safe(entry, next,<br>
+ &metrics->fuse_rpc_error_metric_list, list) {<br>
+ list_del(&entry->list);<br>
+ kfree(entry);<br>
+ }<br>
+ mutex_unlock(&metrics->mutex);<br>
+}<br>
+<br>
+void fuse_rpc_error_account(struct fuse_error_metrics *metrics,<br>
+ PCS_NET_ADDR_T const *addr, unsigned int err, u64 val)<br>
+{<br>
+ struct fuse_rpc_error_metric *metric, *entry;<br>
+<br>
+ if (!metrics || err >= PCS_RPC_ERR_MAX) {<br>
+ WARN_ON_ONCE(1);<br>
+ return;<br>
+ }<br>
+<br>
+ metric = NULL;<br>
+ mutex_lock(&metrics->mutex);<br>
+ list_for_each_entry(entry, &metrics->fuse_rpc_error_metric_list, list) {<br>
+ if (pcs_netaddr_cmp_ignore_port(&entry->m.addr, addr) == 0) {<br>
+ metric = entry;<br>
+ break;<br>
+ }<br>
+ }<br>
+<br>
+ if (!metric) {<br>
+ metric = kzalloc(sizeof(*metric), GFP_KERNEL);<br>
+ if (!metric)<br>
+ goto out;<br>
+ metric->m.addr = *addr;<br>
+ list_add_tail(&metric->list, &metrics->fuse_rpc_error_metric_list);<br>
+ }<br>
+<br>
+ metric->m.err[err] += val;<br>
+<br>
+out:<br>
+ mutex_unlock(&metrics->mutex);<br>
+}<br>
+<br>
+static void fuse_rpc_error_remove_first_and_copy_to_stat(struct fuse_error_metrics *metrics,<br>
+ struct kfuse_metrics *stats)<br>
+{<br>
+ struct fuse_rpc_error_metric *entry;<br>
+<br>
+ mutex_lock(&metrics->mutex);<br>
+ entry = list_first_entry_or_null(&metrics->fuse_rpc_error_metric_list,<br>
+ struct fuse_rpc_error_metric, list);<br>
+ if (!entry) {<br>
+ mutex_unlock(&metrics->mutex);<br>
+ return;<br>
+ }<br>
+ list_del(&entry->list);<br>
+ mutex_unlock(&metrics->mutex);<br>
+<br>
+ pcs_format_netaddr_ignore_port(stats->rpc_error.address, MAX_RPC_ADDR_LEN, &entry->m.addr);<br>
+ memcpy(stats->rpc_error.error, entry->m.err, sizeof(stats->rpc_error.error));<br>
+ stats->rpc_error.has_next = entry->list.next != NULL;<br>
+ kfree(entry);<br>
+}<br>
+<br>
static int prometheus_file_open(struct inode *inode, struct file *filp)<br>
{<br>
struct fuse_ktrace * tr = inode->i_private;<br>
@@ -1407,19 +1478,18 @@ static ssize_t prometheus_file_read(struct file *filp,<br>
struct kfuse_metrics *stats;<br>
int cpu;<br>
<br>
+ if (!tr->prometheus_metrics)<br>
+ return -EINVAL;<br>
+<br>
if (*ppos >= sizeof(struct kfuse_metrics))<br>
return 0;<br>
if (*ppos + count > sizeof(struct kfuse_metrics))<br>
count = sizeof(struct kfuse_metrics) - *ppos;<br>
<br>
- stats = (void *)get_zeroed_page(GFP_KERNEL);<br>
- BUILD_BUG_ON(sizeof(*stats) > PAGE_SIZE);<br>
+ stats = kzalloc(sizeof(struct kfuse_metrics), GFP_KERNEL);<br>
if (!stats)<br>
return -ENOMEM;<br>
<br>
- if (!tr->prometheus_metrics)<br>
- return -EINVAL;<br>
-<br>
for_each_possible_cpu(cpu) {<br>
struct kfuse_metrics *m;<br>
<br>
@@ -1446,12 +1516,14 @@ static ssize_t prometheus_file_read(struct file *filp,<br>
pcs_kio_req_list(tr->fc, prometheus_req_iter, stats);<br>
spin_unlock(&tr->fc->lock);<br>
<br>
+ fuse_rpc_error_remove_first_and_copy_to_stat(&tr->error_metrics, stats);<br>
+<br>
if (copy_to_user(buffer, (char *)stats + *ppos, count))<br>
count = -EFAULT;<br>
else<br>
*ppos += count;<br>
<br>
- free_page((unsigned long)stats);<br>
+ kfree(stats);<br>
return count;<br>
}<br>
<br>
@@ -1517,6 +1589,9 @@ static int fuse_ktrace_setup(struct fuse_conn * fc)<br>
<br>
tr->buf = __alloc_percpu(KTRACE_LOG_BUF_SIZE, 16);<br>
<br>
+ INIT_LIST_HEAD(&tr->error_metrics.fuse_rpc_error_metric_list);<br>
+ mutex_init(&tr->error_metrics.mutex);<br>
+<br>
atomic_set(&tr->refcnt, 1);<br>
<br>
ret = -EBUSY;<br>
diff --git a/fs/fuse/kio/pcs/pcs_net_addr.c b/fs/fuse/kio/pcs/pcs_net_addr.c<br>
new file mode 100644<br>
index 000000000000..f75b42e1e7c9<br>
--- /dev/null<br>
+++ b/fs/fuse/kio/pcs/pcs_net_addr.c<br>
@@ -0,0 +1,93 @@<br>
+/*<br>
+ * fs/fuse/kio/pcs/pcs_net_addr.c<br>
+ *<br>
+ * Copyright (c) 2023 Virtuozzo International GmbH. All rights reserved.<br>
+ *<br>
+ */<br>
+<br>
+#include <net/sock.h><br>
+<br>
+#include "pcs_types.h"<br>
+<br>
+int pcs_netaddr2sockaddr(PCS_NET_ADDR_T const *addr, struct sockaddr *sa, int *salen)<br>
+{<br>
+ BUG_ON(!sa);<br>
+ if (addr->type == PCS_ADDRTYPE_IP || addr->type == PCS_ADDRTYPE_RDMA) {<br>
+ struct sockaddr_in *saddr4 = (struct sockaddr_in *)sa;<br>
+ *saddr4 = (struct sockaddr_in) {<br>
+ .sin_family = AF_INET,<br>
+ .sin_port = (u16)addr->port,<br>
+ };<br>
+ memcpy(&saddr4->sin_addr, addr->address, sizeof(saddr4->sin_addr));<br>
+ *salen = sizeof(*saddr4);<br>
+ } else if (addr->type == PCS_ADDRTYPE_IP6) {<br>
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)sa;<br>
+ *saddr6 = (struct sockaddr_in6) {<br>
+ .sin6_family = AF_INET6,<br>
+ .sin6_port = (u16)addr->port,<br>
+ };<br>
+ memcpy(&saddr6->sin6_addr, addr->address, sizeof(saddr6->sin6_addr));<br>
+ *salen = sizeof(*saddr6);<br>
+ } else<br>
+ return -EINVAL;<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+static inline int netaddr_cmp(PCS_NET_ADDR_T const *addr1,<br>
+ PCS_NET_ADDR_T const *addr2, int ignore_port)<br>
+{<br>
+ unsigned int d;<br>
+ size_t sz = 0;<br>
+<br>
+ d = addr1->type - addr2->type;<br>
+ if (d)<br>
+ return d;<br>
+ d = addr1->port - addr2->port;<br>
+ if (!ignore_port && d)<br>
+ return d;<br>
+<br>
+ switch (addr1->type) {<br>
+ case PCS_ADDRTYPE_IP:<br>
+ case PCS_ADDRTYPE_RDMA:<br>
+ sz = sizeof(struct in_addr);<br>
+ break;<br>
+ case PCS_ADDRTYPE_IP6:<br>
+ sz = sizeof(struct in6_addr);<br>
+ break;<br>
+ default:<br>
+ BUG();<br>
+ }<br>
+<br>
+ return memcmp(addr1->address, addr2->address, sz);<br>
+}<br>
+<br>
+int pcs_netaddr_cmp(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2)<br>
+{<br>
+ return netaddr_cmp(addr1, addr2, 0);<br>
+}<br>
+<br>
+int pcs_netaddr_cmp_ignore_port(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2)<br>
+{<br>
+ return netaddr_cmp(addr1, addr2, 1);<br>
+}<br>
+<br>
+int pcs_format_netaddr_ignore_port(char *str, int len, PCS_NET_ADDR_T const *addr)<br>
+{<br>
+ int ret;<br>
+<br>
+ switch (addr->type) {<br>
+ case PCS_ADDRTYPE_IP:<br>
+ case PCS_ADDRTYPE_RDMA:<br>
+ ret = snprintf(str, len, "%pI4", addr->address);<br>
+ break;<br>
+ case PCS_ADDRTYPE_IP6:<br>
+ ret = snprintf(str, len, "%pI6", addr->address);<br>
+ break;<br>
+ default:<br>
+ ret = snprintf(str, len, "unknown");<br>
+ break;<br>
+ }<br>
+<br>
+ return ret;<br>
+}<br>
diff --git a/fs/fuse/kio/pcs/pcs_net_addr.h b/fs/fuse/kio/pcs/pcs_net_addr.h<br>
new file mode 100644<br>
index 000000000000..032d265472fd<br>
--- /dev/null<br>
+++ b/fs/fuse/kio/pcs/pcs_net_addr.h<br>
@@ -0,0 +1,16 @@<br>
+/*<br>
+ * fs/fuse/kio/pcs/pcs_net_addr.h<br>
+ *<br>
+ * Copyright (c) 2023 Virtuozzo International GmbH. All rights reserved.<br>
+ *<br>
+ */<br>
+<br>
+#ifndef __PCS_NET_ADDR_H__<br>
+#define __PCS_NET_ADDR_H__ 1<br>
+<br>
+int pcs_netaddr2sockaddr(PCS_NET_ADDR_T const *addr, struct sockaddr *sa, int *salen);<br>
+int pcs_netaddr_cmp(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2);<br>
+int pcs_netaddr_cmp_ignore_port(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2);<br>
+int pcs_format_netaddr_ignore_port(char *str, int len, PCS_NET_ADDR_T const *addr);<br>
+<br>
+#endif /* __PCS_NET_ADDR_H__ */<br>
diff --git a/fs/fuse/kio/pcs/pcs_rdma_conn.c b/fs/fuse/kio/pcs/pcs_rdma_conn.c<br>
index 8d27c9b8f7ec..8ba7c60fb9b2 100644<br>
--- a/fs/fuse/kio/pcs/pcs_rdma_conn.c<br>
+++ b/fs/fuse/kio/pcs/pcs_rdma_conn.c<br>
@@ -130,18 +130,21 @@ void pcs_rdmaconnect_start(struct pcs_rpc *ep)<br>
RDMA_PS_TCP, IB_QPT_RC);<br>
if (IS_ERR(rc.cmid)) {<br>
TRACE("rdma_create_id failed: %ld\n", PTR_ERR(rc.cmid));<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);<br>
goto fail;<br>
}<br>
<br>
ret = rdma_resolve_addr(rc.cmid, NULL, sa, RESOLVE_TIMEOUT_MS);<br>
if (ret) {<br>
TRACE("rdma_resolve_addr failed: %d\n", ret);<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);<br>
goto fail_cm;<br>
}<br>
<br>
wait_for_completion(&rc.cm_done);<br>
if (rc.cm_event != RDMA_CM_EVENT_ESTABLISHED) {<br>
TRACE("rdma connection failed: %d\n", rc.cm_event);<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);<br>
goto fail_cm;<br>
}<br>
<br>
@@ -168,6 +171,7 @@ void pcs_rdmaconnect_start(struct pcs_rpc *ep)<br>
if (ret < 0) {<br>
TRACE("rdma authorization failed: %d, rio: 0x%p",<br>
ret, rc.rio);<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_AUTH_ERR);<br>
goto fail; /* since ep->conn is initialized,<br>
* rio will be freed in pcs_rpc_reset()<br>
*/<br>
diff --git a/fs/fuse/kio/pcs/pcs_rpc.c b/fs/fuse/kio/pcs/pcs_rpc.c<br>
index 7f8d4b250277..4f49b4eb60dd 100644<br>
--- a/fs/fuse/kio/pcs/pcs_rpc.c<br>
+++ b/fs/fuse/kio/pcs/pcs_rpc.c<br>
@@ -102,6 +102,17 @@ static void rpc_del_hash(struct pcs_rpc * ep)<br>
}<br>
}<br>
<br>
+void pcs_rpc_report_error(struct pcs_rpc *ep, unsigned int err)<br>
+{<br>
+ if (!ep->eng || !cc_from_rpc(ep->eng)->fc->ktrace) {<br>
+ WARN_ON_ONCE(1);<br>
+ return;<br>
+ }<br>
+<br>
+ fuse_rpc_error_account(&cc_from_rpc(ep->eng)->fc->ktrace->error_metrics,<br>
+ &ep->addr, err, 1);<br>
+}<br>
+<br>
<br>
struct pcs_msg * pcs_rpc_lookup_xid(struct pcs_rpc * ep, PCS_XID_T * xid)<br>
{<br>
@@ -230,12 +241,15 @@ void rpc_abort(struct pcs_rpc * ep, int fatal, int error)<br>
queue_delayed_work(cc->wq, &ep->timer_work, ep->params.holddown_timeout);<br>
}<br>
<br>
- while (!list_empty(&failed_list)) {<br>
- struct pcs_msg * msg = list_first_entry(&failed_list, struct pcs_msg, list);<br>
- list_del_init(&msg->list);<br>
- pcs_set_rpc_error(&msg->error, error, ep);<br>
- BUG_ON(!hlist_unhashed(&msg->kill_link));<br>
- msg->done(msg);<br>
+ if (!list_empty(&failed_list)) {<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_ABORTED);<br>
+ while (!list_empty(&failed_list)) {<br>
+ struct pcs_msg * msg = list_first_entry(&failed_list, struct pcs_msg, list);<br>
+ list_del_init(&msg->list);<br>
+ pcs_set_rpc_error(&msg->error, error, ep);<br>
+ BUG_ON(!hlist_unhashed(&msg->kill_link));<br>
+ msg->done(msg);<br>
+ }<br>
}<br>
<br>
if (ep->state != PCS_RPC_ABORT)<br>
@@ -1279,6 +1293,7 @@ static void timer_work(struct work_struct *w)<br>
case PCS_RPC_WORK: {<br>
int err = list_empty(&ep->pending_queue) ? PCS_ERR_RESPONSE_TIMEOUT : PCS_ERR_WRITE_TIMEOUT;<br>
<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_RESPONSE_TOUT);<br>
FUSE_KTRACE(cc_from_rpc(ep->eng)->fc, "rpc timer expired, killing connection to " PEER_FMT ", %d",<br>
PEER_ARGS(ep), err);<br>
rpc_abort(ep, 0, err);<br>
diff --git a/fs/fuse/kio/pcs/pcs_rpc.h b/fs/fuse/kio/pcs/pcs_rpc.h<br>
index 7427fe4c4257..6e9f75145bcc 100644<br>
--- a/fs/fuse/kio/pcs/pcs_rpc.h<br>
+++ b/fs/fuse/kio/pcs/pcs_rpc.h<br>
@@ -12,6 +12,7 @@<br>
#include "pcs_rpc_prot.h"<br>
#include "pcs_net.h"<br>
#include "pcs_sock_io.h"<br>
+#include "fuse_prometheus.h"<br>
<br>
struct pcs_msg;<br>
<br>
@@ -316,4 +317,6 @@ static inline struct pcs_rpc *pcs_rpc_from_work(struct work_struct *wr)<br>
<br>
const char* pcs_rpc_state_name(unsigned state);<br>
<br>
+void pcs_rpc_report_error(struct pcs_rpc *ep, unsigned int err);<br>
+<br>
#endif /* _PCS_RPC_H_ */<br>
diff --git a/fs/fuse/kio/pcs/pcs_sock_conn.c b/fs/fuse/kio/pcs/pcs_sock_conn.c<br>
index f463c1ecef9d..13823da22a9d 100644<br>
--- a/fs/fuse/kio/pcs/pcs_sock_conn.c<br>
+++ b/fs/fuse/kio/pcs/pcs_sock_conn.c<br>
@@ -33,31 +33,6 @@ static inline void pcs_sock_cork(struct socket *sock)<br>
tcp_sock_set_cork(sock->sk, true);<br>
}<br>
<br>
-int pcs_netaddr2sockaddr(PCS_NET_ADDR_T const* addr, struct sockaddr *sa, int *salen)<br>
-{<br>
- BUG_ON(!sa);<br>
- if (addr->type == PCS_ADDRTYPE_IP || addr->type == PCS_ADDRTYPE_RDMA) {<br>
- struct sockaddr_in *saddr4 = (struct sockaddr_in *)sa;<br>
- *saddr4 = (struct sockaddr_in) {<br>
- .sin_family = AF_INET,<br>
- .sin_port = (u16)addr->port,<br>
- };<br>
- memcpy(&saddr4->sin_addr, addr->address, sizeof(saddr4->sin_addr));<br>
- *salen = sizeof(*saddr4);<br>
- } else if (addr->type == PCS_ADDRTYPE_IP6) {<br>
- struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)sa;<br>
- *saddr6 = (struct sockaddr_in6) {<br>
- .sin6_family = AF_INET6,<br>
- .sin6_port = (u16)addr->port,<br>
- };<br>
- memcpy(&saddr6->sin6_addr, addr->address, sizeof(saddr6->sin6_addr));<br>
- *salen = sizeof(*saddr6);<br>
- } else<br>
- return -EINVAL;<br>
-<br>
- return 0;<br>
-}<br>
-<br>
void pcs_sockconnect_start(struct pcs_rpc *ep)<br>
{<br>
struct pcs_sockio *sio;<br>
@@ -70,6 +45,7 @@ void pcs_sockconnect_start(struct pcs_rpc *ep)<br>
sio = kzalloc(sizeof(struct pcs_sockio) + alloc_max, GFP_NOIO);<br>
if (!sio) {<br>
TRACE("Can't allocate sio\n");<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);<br>
goto fail;<br>
}<br>
<br>
@@ -82,6 +58,7 @@ void pcs_sockconnect_start(struct pcs_rpc *ep)<br>
err = sock_create(sa->sa_family, SOCK_STREAM, 0, &sock);<br>
if (err < 0) {<br>
TRACE("Can't create socket: %d\n", err);<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);<br>
goto fail2;<br>
}<br>
pcs_clear_error(&sio->error);<br>
@@ -90,6 +67,7 @@ void pcs_sockconnect_start(struct pcs_rpc *ep)<br>
if (err != 0 && err != -EINPROGRESS) {<br>
TRACE("Failed connection: %d\n", err);<br>
sock_release(sock);<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);<br>
goto fail2;<br>
}<br>
pcs_sock_keepalive(sock);<br>
@@ -122,6 +100,7 @@ void pcs_sockconnect_start(struct pcs_rpc *ep)<br>
if (err < 0) {<br>
FUSE_KLOG(cc_from_rpc(ep->eng)->fc, LOG_ERR,<br>
"Authorization failed: %d", err);<br>
+ pcs_rpc_report_error(ep, PCS_RPC_ERR_AUTH_ERR);<br>
goto fail; /* since ep->conn is initialized,<br>
* sio will be freed in pcs_rpc_reset()<br>
*/<br>
diff --git a/fs/fuse/kio/pcs/pcs_sock_conn.h b/fs/fuse/kio/pcs/pcs_sock_conn.h<br>
index bf39a29f78e9..554958b419d0 100644<br>
--- a/fs/fuse/kio/pcs/pcs_sock_conn.h<br>
+++ b/fs/fuse/kio/pcs/pcs_sock_conn.h<br>
@@ -9,6 +9,5 @@<br>
#define _PCS_SOCK_CONN_H_ 1<br>
<br>
void pcs_sockconnect_start(struct pcs_rpc *ep);<br>
-int pcs_netaddr2sockaddr(PCS_NET_ADDR_T const* addr, struct sockaddr *sa, int *salen);<br>
<br>
#endif /* _PCS_SOCK_CONN_H_ */<br>
-- <br>
2.34.1<br>
<br>
</div>
</span></font>
</body>
</html>