[Devel] [PATCH vz9 v2] fs/fuse kio: implement rpc errors collection

Yuriy Vasilev yuriy.vasilev at virtuozzo.com
Thu Jul 27 11:16:13 MSK 2023


Implement collecting rpc errors and exporting them to userspace fuse
daemon via relayfs.
Errors are grouped per IP addresses and exported as a field of
kfuse_metrics struct. This field is updated on each read.

Also move pcs_net* functions to a separate file.

Affects: #VSTOR-70161
https://pmc.acronis.work/browse/VSTOR-70161

Signed-off-by: Yuriy Vasilev <yuriy.vasilev at virtuozzo.com>
---
v2:
Replace flex array with a single struct containing a 'next' field
that refreshes after each successful read, provided there is a next elem
in the list. Now, after reading, only head of an rpc errors list is
cleaned.
Replace spinlock with mutex. Also, remove rpc errors accounting as it is
not necessary now.
Add more rpc error types.
---
 fs/fuse/Makefile                       |   3 +-
 fs/fuse/kio/pcs/fuse_ktrace.h          |   1 +
 fs/fuse/kio/pcs/fuse_prometheus.h      |  18 ++++
 fs/fuse/kio/pcs/fuse_prometheus_prot.h |  19 ++++
 fs/fuse/kio/pcs/pcs_cs.c               |  34 +-------
 fs/fuse/kio/pcs/pcs_fuse_kdirect.c     | 115 +++++++++++++++++++++++--
 fs/fuse/kio/pcs/pcs_net_addr.c         |  93 ++++++++++++++++++++
 fs/fuse/kio/pcs/pcs_net_addr.h         |  16 ++++
 fs/fuse/kio/pcs/pcs_rdma_conn.c        |   4 +
 fs/fuse/kio/pcs/pcs_rpc.c              |  27 ++++--
 fs/fuse/kio/pcs/pcs_rpc.h              |   3 +
 fs/fuse/kio/pcs/pcs_sock_conn.c        |  29 +------
 fs/fuse/kio/pcs/pcs_sock_conn.h        |   1 -
 13 files changed, 290 insertions(+), 73 deletions(-)
 create mode 100644 fs/fuse/kio/pcs/pcs_net_addr.c
 create mode 100644 fs/fuse/kio/pcs/pcs_net_addr.h

diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile
index cc0d0c1d63b3..37ef32ffa13d 100644
--- a/fs/fuse/Makefile
+++ b/fs/fuse/Makefile
@@ -31,6 +31,7 @@ fuse_kio_pcs-objs := kio/pcs/pcs_fuse_kdirect.o \
 	kio/pcs/pcs_auth.o \
 	kio/pcs/pcs_rdma_io.o \
 	kio/pcs/pcs_rdma_rw.o \
-	kio/pcs/pcs_rdma_conn.o
+	kio/pcs/pcs_rdma_conn.o \
+	kio/pcs/pcs_net_addr.o
 
 virtiofs-y := virtio_fs.o
diff --git a/fs/fuse/kio/pcs/fuse_ktrace.h b/fs/fuse/kio/pcs/fuse_ktrace.h
index aef368fcacef..bfee4e831a70 100644
--- a/fs/fuse/kio/pcs/fuse_ktrace.h
+++ b/fs/fuse/kio/pcs/fuse_ktrace.h
@@ -29,6 +29,7 @@ struct fuse_ktrace
 	struct dentry				*prometheus_dentry;
 	struct kfuse_metrics __percpu	*prometheus_metrics;
 	u8 * __percpu				buf;
+	struct fuse_error_metrics	*error_metrics;
 };
 
 static inline void * fuse_trace_prepare(struct fuse_ktrace * tr, int type, int len)
diff --git a/fs/fuse/kio/pcs/fuse_prometheus.h b/fs/fuse/kio/pcs/fuse_prometheus.h
index 3f1b31c290d6..6dba65409077 100644
--- a/fs/fuse/kio/pcs/fuse_prometheus.h
+++ b/fs/fuse/kio/pcs/fuse_prometheus.h
@@ -15,4 +15,22 @@ struct fuse_prometheus_data
 	struct kfuse_histogram __percpu *histo;
 };
 
+struct fuse_rpc_error {
+	PCS_NET_ADDR_T addr;
+	u64 err[PCS_RPC_ERR_MAX];
+};
+
+struct fuse_rpc_error_metric {
+	struct fuse_rpc_error m;
+	struct list_head list;
+};
+
+struct fuse_error_metrics {
+	struct mutex mutex;
+	struct list_head fuse_rpc_error_metric_list;
+};
+
+void fuse_rpc_error_account(struct fuse_error_metrics *metrics,
+	PCS_NET_ADDR_T const *addr, unsigned int err, u64 val);
+
 #endif /* __FUSE_PROMETHEUS_H__ */
diff --git a/fs/fuse/kio/pcs/fuse_prometheus_prot.h b/fs/fuse/kio/pcs/fuse_prometheus_prot.h
index e7b6f8a52d26..eeaa2420a063 100644
--- a/fs/fuse/kio/pcs/fuse_prometheus_prot.h
+++ b/fs/fuse/kio/pcs/fuse_prometheus_prot.h
@@ -39,6 +39,22 @@ struct kfuse_counter {
 	u64 val_total;
 };
 
+#define PCS_RPC_ERR_CONNECT_TOUT		0
+#define PCS_RPC_ERR_CONNECT_ERROR		1
+#define PCS_RPC_ERR_AUTH_TOUT			2
+#define PCS_RPC_ERR_AUTH_ERR			3
+#define PCS_RPC_ERR_RESPONSE_TOUT		4
+#define PCS_RPC_ERR_ABORTED				5
+#define PCS_RPC_ERR_MAX					6
+
+#define MAX_RPC_ADDR_LEN 46
+
+struct kfuse_rpc_error {
+	char address[MAX_RPC_ADDR_LEN];
+	u64 error[PCS_RPC_ERR_MAX];
+	int has_next;
+};
+
 struct kfuse_metrics {
 	/* Histograms are compatible with old version of proto
 	 * between userspace and kio where the counters were skipped.
@@ -51,6 +67,9 @@ struct kfuse_metrics {
 	u64 stucked_reqs_cnt_8s;
 	u64 stucked_reqs_cnt_30s;
 	u64 stucked_reqs_cnt_120s;
+
+	/* Each read triggers replacement of this field with the next one from a list */
+	struct kfuse_rpc_error rpc_error;
 };
 
 #endif /* __FUSE_PROMETHEUS_PROT__ */
diff --git a/fs/fuse/kio/pcs/pcs_cs.c b/fs/fuse/kio/pcs/pcs_cs.c
index 9d81fe8bf22c..13e2b4e6b50c 100644
--- a/fs/fuse/kio/pcs/pcs_cs.c
+++ b/fs/fuse/kio/pcs/pcs_cs.c
@@ -24,6 +24,7 @@
 #include "pcs_ioctl.h"
 #include "log.h"
 #include "fuse_ktrace.h"
+#include "pcs_net_addr.h"
 
 /* Lock order: cs->lock -> css->lock (lru, hash, bl_list) */
 
@@ -210,38 +211,6 @@ static void add_cs(struct pcs_cs_set *csset, struct pcs_cs *cs)
 	hlist_add_head_rcu(&cs->hlist, &csset->ht[hash]);
 }
 
-static inline int netaddr_cmp(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2, int ignore_port)
-{
-	unsigned int d;
-	size_t sz = 0;
-
-	d = addr1->type - addr2->type;
-	if (d)
-		return d;
-	d = addr1->port - addr2->port;
-	if (!ignore_port && d)
-		return d;
-
-	switch (addr1->type) {
-	case PCS_ADDRTYPE_IP:
-	case PCS_ADDRTYPE_RDMA:
-		sz = sizeof(struct in_addr);
-		break;
-	case PCS_ADDRTYPE_IP6:
-		sz = sizeof(struct in6_addr);
-		break;
-	default:
-		BUG();
-	}
-
-	return memcmp(addr1->address, addr2->address, sz);
-}
-
-static int pcs_netaddr_cmp(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2)
-{
-	return netaddr_cmp(addr1, addr2, 0);
-}
-
 /* Return locked cs */
 struct pcs_cs *pcs_cs_find_create(struct pcs_cs_set *csset, PCS_NODE_ID_T *id, PCS_NET_ADDR_T *addr, int flags)
 {
@@ -502,6 +471,7 @@ static void cs_connect(struct pcs_rpc *ep)
 	connect_start(ep); /* TODO: rewrite to use pcs_netconnect callback */
 	return;
 fail:
+	pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);
 	pcs_rpc_reset(ep);
 	return;
 }
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index af008e63294c..c77c77212718 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -34,6 +34,7 @@
 #include "pcs_rpc.h"
 #include "fuse_ktrace.h"
 #include "fuse_prometheus.h"
+#include "pcs_net_addr.h"
 
 unsigned int pcs_loglevel = LOG_TRACE;
 module_param(pcs_loglevel, uint, 0644);
@@ -1243,6 +1244,8 @@ static void kpcs_req_send(struct fuse_req *req, bool bg)
 	return;
 }
 
+static void fuse_rpc_error_metrics_clean(struct fuse_error_metrics *metrics);
+
 static void fuse_trace_free(struct fuse_ktrace *tr)
 {
 	relay_close(tr->rchan);
@@ -1256,6 +1259,11 @@ static void fuse_trace_free(struct fuse_ktrace *tr)
 	debugfs_remove(tr->dir);
 	if (tr->fc)
 		fuse_conn_put(tr->fc);
+
+	if (tr->error_metrics) {
+		fuse_rpc_error_metrics_clean(tr->error_metrics);
+		kfree(tr->error_metrics);
+	}
 	kfree(tr);
 }
 
@@ -1359,6 +1367,83 @@ void fuse_stat_account(struct fuse_conn *fc, int op, u64 val)
 	}
 }
 
+static void fuse_rpc_error_metrics_clean(struct fuse_error_metrics *metrics)
+{
+	struct fuse_rpc_error_metric *entry, *next;
+
+	mutex_lock(&metrics->mutex);
+	list_for_each_entry_safe(entry, next,
+			&metrics->fuse_rpc_error_metric_list, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+	mutex_unlock(&metrics->mutex);
+}
+
+void fuse_rpc_error_account(struct fuse_error_metrics *metrics,
+		PCS_NET_ADDR_T const *addr, unsigned int err, u64 val)
+{
+	struct fuse_rpc_error_metric *metric, *entry;
+
+	if (!metrics || err >= PCS_RPC_ERR_MAX) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	metric = NULL;
+	mutex_lock(&metrics->mutex);
+	list_for_each_entry(entry, &metrics->fuse_rpc_error_metric_list, list) {
+		if (pcs_netaddr_cmp_ignore_port(&entry->m.addr, addr) == 0) {
+			metric = entry;
+			break;
+		}
+	}
+
+	if (!metric) {
+		metric = kzalloc(sizeof(*metric), GFP_KERNEL);
+		if (!metric)
+			goto out;
+		metric->m.addr = *addr;
+		list_add_tail(&metric->list, &metrics->fuse_rpc_error_metric_list);
+	}
+
+	metric->m.err[err] += val;
+
+out:
+	mutex_unlock(&metrics->mutex);
+}
+
+static void fuse_rpc_error_copy_first_to_stat(struct fuse_error_metrics *metrics,
+				struct kfuse_metrics *stats)
+{
+	struct fuse_rpc_error_metric *entry;
+
+	mutex_lock(&metrics->mutex);
+	if (!list_empty(&metrics->fuse_rpc_error_metric_list)) {
+		entry = list_first_entry(&metrics->fuse_rpc_error_metric_list,
+				struct fuse_rpc_error_metric, list);
+		pcs_format_netaddr_ignore_port(stats->rpc_error.address,
+				MAX_RPC_ADDR_LEN, &entry->m.addr);
+		memcpy(stats->rpc_error.error, entry->m.err, sizeof(stats->rpc_error.error));
+		stats->rpc_error.has_next = entry->list.next != NULL;
+	}
+	mutex_unlock(&metrics->mutex);
+}
+
+static void fuse_rpc_error_del_first(struct fuse_error_metrics *metrics)
+{
+	struct fuse_rpc_error_metric *entry;
+
+	mutex_lock(&metrics->mutex);
+	if (!list_empty(&metrics->fuse_rpc_error_metric_list)) {
+		entry = list_first_entry(&metrics->fuse_rpc_error_metric_list,
+				struct fuse_rpc_error_metric, list);
+		list_del(&entry->list);
+		kfree(entry);
+	}
+	mutex_unlock(&metrics->mutex);
+}
+
 static int prometheus_file_open(struct inode *inode, struct file *filp)
 {
 	struct fuse_ktrace * tr = inode->i_private;
@@ -1407,19 +1492,21 @@ static ssize_t prometheus_file_read(struct file *filp,
 	struct kfuse_metrics *stats;
 	int cpu;
 
+	if (!tr->prometheus_metrics)
+		return -EINVAL;
+
+	if (!tr->error_metrics)
+		return -EINVAL;
+
 	if (*ppos >= sizeof(struct kfuse_metrics))
 		return 0;
 	if (*ppos + count > sizeof(struct kfuse_metrics))
 		count = sizeof(struct kfuse_metrics) - *ppos;
 
-	stats = (void *)get_zeroed_page(GFP_KERNEL);
-	BUILD_BUG_ON(sizeof(*stats) > PAGE_SIZE);
+	stats = kzalloc(sizeof(struct kfuse_metrics), GFP_KERNEL);
 	if (!stats)
 		return -ENOMEM;
 
-	if (!tr->prometheus_metrics)
-		return -EINVAL;
-
 	for_each_possible_cpu(cpu) {
 		struct kfuse_metrics *m;
 
@@ -1446,12 +1533,16 @@ static ssize_t prometheus_file_read(struct file *filp,
 	pcs_kio_req_list(tr->fc, prometheus_req_iter, stats);
 	spin_unlock(&tr->fc->lock);
 
-	if (copy_to_user(buffer, (char *)stats + *ppos, count))
+	fuse_rpc_error_copy_first_to_stat(tr->error_metrics, stats);
+
+	if (copy_to_user(buffer, (char *)stats + *ppos, count)) {
 		count = -EFAULT;
-	else
+	} else {
 		*ppos += count;
+		fuse_rpc_error_del_first(tr->error_metrics);
+	}
 
-	free_page((unsigned long)stats);
+	kfree(stats);
 	return count;
 }
 
@@ -1468,6 +1559,7 @@ static int fuse_ktrace_setup(struct fuse_conn * fc)
 	struct fuse_ktrace * old_tr;
 	struct dentry * dir;
 	struct kfuse_metrics __percpu * metrics;
+	struct fuse_error_metrics * error_metrics;
 	int cpu;
 	char name[16];
 
@@ -1517,6 +1609,13 @@ static int fuse_ktrace_setup(struct fuse_conn * fc)
 
 	tr->buf = __alloc_percpu(KTRACE_LOG_BUF_SIZE, 16);
 
+	error_metrics = kzalloc(sizeof(struct fuse_error_metrics), GFP_KERNEL);
+	if (!error_metrics)
+		goto err;
+	INIT_LIST_HEAD(&error_metrics->fuse_rpc_error_metric_list);
+	mutex_init(&error_metrics->mutex);
+	tr->error_metrics = error_metrics;
+
 	atomic_set(&tr->refcnt, 1);
 
 	ret = -EBUSY;
diff --git a/fs/fuse/kio/pcs/pcs_net_addr.c b/fs/fuse/kio/pcs/pcs_net_addr.c
new file mode 100644
index 000000000000..f75b42e1e7c9
--- /dev/null
+++ b/fs/fuse/kio/pcs/pcs_net_addr.c
@@ -0,0 +1,93 @@
+/*
+ *  fs/fuse/kio/pcs/pcs_net_addr.c
+ *
+ *  Copyright (c) 2023 Virtuozzo International GmbH. All rights reserved.
+ *
+ */
+
+#include <net/sock.h>
+
+#include "pcs_types.h"
+
+int pcs_netaddr2sockaddr(PCS_NET_ADDR_T const *addr, struct sockaddr *sa, int *salen)
+{
+	BUG_ON(!sa);
+	if (addr->type == PCS_ADDRTYPE_IP || addr->type == PCS_ADDRTYPE_RDMA) {
+		struct sockaddr_in *saddr4 = (struct sockaddr_in *)sa;
+		*saddr4 = (struct sockaddr_in) {
+			.sin_family = AF_INET,
+			.sin_port = (u16)addr->port,
+		};
+		memcpy(&saddr4->sin_addr, addr->address, sizeof(saddr4->sin_addr));
+		*salen = sizeof(*saddr4);
+	} else if (addr->type == PCS_ADDRTYPE_IP6) {
+		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)sa;
+		*saddr6 = (struct sockaddr_in6) {
+			.sin6_family = AF_INET6,
+			.sin6_port = (u16)addr->port,
+		};
+		memcpy(&saddr6->sin6_addr, addr->address, sizeof(saddr6->sin6_addr));
+		*salen = sizeof(*saddr6);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static inline int netaddr_cmp(PCS_NET_ADDR_T const *addr1,
+		PCS_NET_ADDR_T const *addr2, int ignore_port)
+{
+	unsigned int d;
+	size_t sz = 0;
+
+	d = addr1->type - addr2->type;
+	if (d)
+		return d;
+	d = addr1->port - addr2->port;
+	if (!ignore_port && d)
+		return d;
+
+	switch (addr1->type) {
+	case PCS_ADDRTYPE_IP:
+	case PCS_ADDRTYPE_RDMA:
+		sz = sizeof(struct in_addr);
+		break;
+	case PCS_ADDRTYPE_IP6:
+		sz = sizeof(struct in6_addr);
+		break;
+	default:
+		BUG();
+	}
+
+	return memcmp(addr1->address, addr2->address, sz);
+}
+
+int pcs_netaddr_cmp(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2)
+{
+	return netaddr_cmp(addr1, addr2, 0);
+}
+
+int pcs_netaddr_cmp_ignore_port(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2)
+{
+	return netaddr_cmp(addr1, addr2, 1);
+}
+
+int pcs_format_netaddr_ignore_port(char *str, int len, PCS_NET_ADDR_T const *addr)
+{
+	int ret;
+
+	switch (addr->type) {
+	case PCS_ADDRTYPE_IP:
+	case PCS_ADDRTYPE_RDMA:
+		ret = snprintf(str, len, "%pI4", addr->address);
+		break;
+	case PCS_ADDRTYPE_IP6:
+		ret = snprintf(str, len, "%pI6", addr->address);
+		break;
+	default:
+		ret = snprintf(str, len, "unknown");
+		break;
+	}
+
+	return ret;
+}
diff --git a/fs/fuse/kio/pcs/pcs_net_addr.h b/fs/fuse/kio/pcs/pcs_net_addr.h
new file mode 100644
index 000000000000..032d265472fd
--- /dev/null
+++ b/fs/fuse/kio/pcs/pcs_net_addr.h
@@ -0,0 +1,16 @@
+/*
+ *  fs/fuse/kio/pcs/pcs_net_addr.h
+ *
+ *  Copyright (c) 2023 Virtuozzo International GmbH. All rights reserved.
+ *
+ */
+
+#ifndef __PCS_NET_ADDR_H__
+#define __PCS_NET_ADDR_H__ 1
+
+int pcs_netaddr2sockaddr(PCS_NET_ADDR_T const *addr, struct sockaddr *sa, int *salen);
+int pcs_netaddr_cmp(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2);
+int pcs_netaddr_cmp_ignore_port(PCS_NET_ADDR_T const *addr1, PCS_NET_ADDR_T const *addr2);
+int pcs_format_netaddr_ignore_port(char *str, int len, PCS_NET_ADDR_T const *addr);
+
+#endif /* __PCS_NET_ADDR_H__ */
diff --git a/fs/fuse/kio/pcs/pcs_rdma_conn.c b/fs/fuse/kio/pcs/pcs_rdma_conn.c
index 8d27c9b8f7ec..8ba7c60fb9b2 100644
--- a/fs/fuse/kio/pcs/pcs_rdma_conn.c
+++ b/fs/fuse/kio/pcs/pcs_rdma_conn.c
@@ -130,18 +130,21 @@ void pcs_rdmaconnect_start(struct pcs_rpc *ep)
 				 RDMA_PS_TCP, IB_QPT_RC);
 	if (IS_ERR(rc.cmid)) {
 		TRACE("rdma_create_id failed: %ld\n", PTR_ERR(rc.cmid));
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);
 		goto fail;
 	}
 
 	ret = rdma_resolve_addr(rc.cmid, NULL, sa, RESOLVE_TIMEOUT_MS);
 	if (ret) {
 		TRACE("rdma_resolve_addr failed: %d\n", ret);
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);
 		goto fail_cm;
 	}
 
 	wait_for_completion(&rc.cm_done);
 	if (rc.cm_event != RDMA_CM_EVENT_ESTABLISHED) {
 		TRACE("rdma connection failed: %d\n", rc.cm_event);
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);
 		goto fail_cm;
 	}
 
@@ -168,6 +171,7 @@ void pcs_rdmaconnect_start(struct pcs_rpc *ep)
 	if (ret < 0) {
 		TRACE("rdma authorization failed: %d, rio: 0x%p",
 		      ret, rc.rio);
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_AUTH_ERR);
 		goto fail; /* since ep->conn is initialized,
 			    * rio will be freed in pcs_rpc_reset()
 			    */
diff --git a/fs/fuse/kio/pcs/pcs_rpc.c b/fs/fuse/kio/pcs/pcs_rpc.c
index 7f8d4b250277..9c1b1d3950bf 100644
--- a/fs/fuse/kio/pcs/pcs_rpc.c
+++ b/fs/fuse/kio/pcs/pcs_rpc.c
@@ -102,6 +102,17 @@ static void rpc_del_hash(struct pcs_rpc * ep)
 	}
 }
 
+void pcs_rpc_report_error(struct pcs_rpc *ep, unsigned int err)
+{
+	if (!ep->eng || !cc_from_rpc(ep->eng)->fc->ktrace) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	fuse_rpc_error_account(cc_from_rpc(ep->eng)->fc->ktrace->error_metrics,
+		&ep->addr, err, 1);
+}
+
 
 struct pcs_msg * pcs_rpc_lookup_xid(struct pcs_rpc * ep, PCS_XID_T * xid)
 {
@@ -230,12 +241,15 @@ void rpc_abort(struct pcs_rpc * ep, int fatal, int error)
 		queue_delayed_work(cc->wq, &ep->timer_work, ep->params.holddown_timeout);
 	}
 
-	while (!list_empty(&failed_list)) {
-		struct pcs_msg * msg = list_first_entry(&failed_list, struct pcs_msg, list);
-		list_del_init(&msg->list);
-		pcs_set_rpc_error(&msg->error, error, ep);
-		BUG_ON(!hlist_unhashed(&msg->kill_link));
-		msg->done(msg);
+	if (!list_empty(&failed_list)) {
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_ABORTED);
+		while (!list_empty(&failed_list)) {
+			struct pcs_msg * msg = list_first_entry(&failed_list, struct pcs_msg, list);
+			list_del_init(&msg->list);
+			pcs_set_rpc_error(&msg->error, error, ep);
+			BUG_ON(!hlist_unhashed(&msg->kill_link));
+			msg->done(msg);
+		}
 	}
 
 	if (ep->state != PCS_RPC_ABORT)
@@ -1279,6 +1293,7 @@ static void timer_work(struct work_struct *w)
 	case PCS_RPC_WORK: {
 		int err = list_empty(&ep->pending_queue) ? PCS_ERR_RESPONSE_TIMEOUT : PCS_ERR_WRITE_TIMEOUT;
 
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_RESPONSE_TOUT);
 		FUSE_KTRACE(cc_from_rpc(ep->eng)->fc, "rpc timer expired, killing connection to " PEER_FMT ", %d",
 		      PEER_ARGS(ep), err);
 		rpc_abort(ep, 0, err);
diff --git a/fs/fuse/kio/pcs/pcs_rpc.h b/fs/fuse/kio/pcs/pcs_rpc.h
index 7427fe4c4257..6e9f75145bcc 100644
--- a/fs/fuse/kio/pcs/pcs_rpc.h
+++ b/fs/fuse/kio/pcs/pcs_rpc.h
@@ -12,6 +12,7 @@
 #include "pcs_rpc_prot.h"
 #include "pcs_net.h"
 #include "pcs_sock_io.h"
+#include "fuse_prometheus.h"
 
 struct pcs_msg;
 
@@ -316,4 +317,6 @@ static inline struct pcs_rpc *pcs_rpc_from_work(struct work_struct *wr)
 
 const char* pcs_rpc_state_name(unsigned state);
 
+void pcs_rpc_report_error(struct pcs_rpc *ep, unsigned int err);
+
 #endif /* _PCS_RPC_H_ */
diff --git a/fs/fuse/kio/pcs/pcs_sock_conn.c b/fs/fuse/kio/pcs/pcs_sock_conn.c
index f463c1ecef9d..13823da22a9d 100644
--- a/fs/fuse/kio/pcs/pcs_sock_conn.c
+++ b/fs/fuse/kio/pcs/pcs_sock_conn.c
@@ -33,31 +33,6 @@ static inline void pcs_sock_cork(struct socket *sock)
 	tcp_sock_set_cork(sock->sk, true);
 }
 
-int pcs_netaddr2sockaddr(PCS_NET_ADDR_T const* addr, struct sockaddr *sa, int *salen)
-{
-	BUG_ON(!sa);
-	if (addr->type == PCS_ADDRTYPE_IP || addr->type == PCS_ADDRTYPE_RDMA) {
-		struct sockaddr_in *saddr4 = (struct sockaddr_in *)sa;
-		*saddr4 = (struct sockaddr_in) {
-			.sin_family = AF_INET,
-			.sin_port = (u16)addr->port,
-		};
-		memcpy(&saddr4->sin_addr, addr->address, sizeof(saddr4->sin_addr));
-		*salen = sizeof(*saddr4);
-	} else if (addr->type == PCS_ADDRTYPE_IP6) {
-		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)sa;
-		*saddr6 = (struct sockaddr_in6) {
-			.sin6_family = AF_INET6,
-			.sin6_port = (u16)addr->port,
-		};
-		memcpy(&saddr6->sin6_addr, addr->address, sizeof(saddr6->sin6_addr));
-		*salen = sizeof(*saddr6);
-	} else
-		return -EINVAL;
-
-	return 0;
-}
-
 void pcs_sockconnect_start(struct pcs_rpc *ep)
 {
 	struct pcs_sockio *sio;
@@ -70,6 +45,7 @@ void pcs_sockconnect_start(struct pcs_rpc *ep)
 	sio = kzalloc(sizeof(struct pcs_sockio) + alloc_max, GFP_NOIO);
 	if (!sio) {
 		TRACE("Can't allocate sio\n");
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);
 		goto fail;
 	}
 
@@ -82,6 +58,7 @@ void pcs_sockconnect_start(struct pcs_rpc *ep)
 	err = sock_create(sa->sa_family, SOCK_STREAM, 0, &sock);
 	if (err < 0) {
 		TRACE("Can't create socket: %d\n", err);
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);
 		goto fail2;
 	}
 	pcs_clear_error(&sio->error);
@@ -90,6 +67,7 @@ void pcs_sockconnect_start(struct pcs_rpc *ep)
 	if (err != 0 && err != -EINPROGRESS) {
 		TRACE("Failed connection: %d\n", err);
 		sock_release(sock);
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);
 		goto fail2;
 	}
 	pcs_sock_keepalive(sock);
@@ -122,6 +100,7 @@ void pcs_sockconnect_start(struct pcs_rpc *ep)
 	if (err < 0) {
 		FUSE_KLOG(cc_from_rpc(ep->eng)->fc, LOG_ERR,
 			  "Authorization failed: %d", err);
+		pcs_rpc_report_error(ep, PCS_RPC_ERR_AUTH_ERR);
 		goto fail; /* since ep->conn is initialized,
 			    * sio will be freed in pcs_rpc_reset()
 			    */
diff --git a/fs/fuse/kio/pcs/pcs_sock_conn.h b/fs/fuse/kio/pcs/pcs_sock_conn.h
index bf39a29f78e9..554958b419d0 100644
--- a/fs/fuse/kio/pcs/pcs_sock_conn.h
+++ b/fs/fuse/kio/pcs/pcs_sock_conn.h
@@ -9,6 +9,5 @@
 #define _PCS_SOCK_CONN_H_ 1
 
 void pcs_sockconnect_start(struct pcs_rpc *ep);
-int pcs_netaddr2sockaddr(PCS_NET_ADDR_T const* addr, struct sockaddr *sa, int *salen);
 
 #endif /* _PCS_SOCK_CONN_H_ */
-- 
2.34.1



More information about the Devel mailing list