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

Alexey Kuznetsov kuznet at acronis.com
Tue Aug 1 15:08:18 MSK 2023


Ack

On Fri, Jul 28, 2023 at 12:52 AM Yuriy Vasilev
<yuriy.vasilev at virtuozzo.com> wrote:
>
> 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.
>
> v3: Fixed copying. Now, copying and removal occur in one place. First,
> under mutex an error record is removed from list, and this record is
> copied to stat struct. fuse_error_metrics is now part of fuse_ktrace,
> unnecessary memory management code for it has been removed.
> ---
>  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     | 87 ++++++++++++++++++++++--
>  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, 264 insertions(+), 71 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..72342342b8da 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..706da8e536c9 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);
> @@ -1254,6 +1257,7 @@ static void fuse_trace_free(struct fuse_ktrace *tr)
>                 free_percpu(tr->prometheus_metrics);
>         free_percpu(tr->buf);
>         debugfs_remove(tr->dir);
> +       fuse_rpc_error_metrics_clean(&tr->error_metrics);
>         if (tr->fc)
>                 fuse_conn_put(tr->fc);
>         kfree(tr);
> @@ -1359,6 +1363,73 @@ 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_remove_first_and_copy_to_stat(struct fuse_error_metrics *metrics,
> +                               struct kfuse_metrics *stats)
> +{
> +       struct fuse_rpc_error_metric *entry;
> +
> +       mutex_lock(&metrics->mutex);
> +       entry = list_first_entry_or_null(&metrics->fuse_rpc_error_metric_list,
> +                       struct fuse_rpc_error_metric, list);
> +       if (!entry) {
> +               mutex_unlock(&metrics->mutex);
> +               return;
> +       }
> +       list_del(&entry->list);
> +       mutex_unlock(&metrics->mutex);
> +
> +       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;
> +       kfree(entry);
> +}
> +
>  static int prometheus_file_open(struct inode *inode, struct file *filp)
>  {
>         struct fuse_ktrace * tr = inode->i_private;
> @@ -1407,19 +1478,18 @@ static ssize_t prometheus_file_read(struct file *filp,
>         struct kfuse_metrics *stats;
>         int cpu;
>
> +       if (!tr->prometheus_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 +1516,14 @@ static ssize_t prometheus_file_read(struct file *filp,
>         pcs_kio_req_list(tr->fc, prometheus_req_iter, stats);
>         spin_unlock(&tr->fc->lock);
>
> +       fuse_rpc_error_remove_first_and_copy_to_stat(&tr->error_metrics, stats);
> +
>         if (copy_to_user(buffer, (char *)stats + *ppos, count))
>                 count = -EFAULT;
>         else
>                 *ppos += count;
>
> -       free_page((unsigned long)stats);
> +       kfree(stats);
>         return count;
>  }
>
> @@ -1517,6 +1589,9 @@ static int fuse_ktrace_setup(struct fuse_conn * fc)
>
>         tr->buf = __alloc_percpu(KTRACE_LOG_BUF_SIZE, 16);
>
> +       INIT_LIST_HEAD(&tr->error_metrics.fuse_rpc_error_metric_list);
> +       mutex_init(&tr->error_metrics.mutex);
> +
>         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..4f49b4eb60dd 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
>
> _______________________________________________
> Devel mailing list
> Devel at openvz.org
> https://lists.openvz.org/mailman/listinfo/devel



More information about the Devel mailing list