87c3ef
From 1bde083cbd1e06be66d00e4ca52075687cee0d60 Mon Sep 17 00:00:00 2001
87c3ef
From: Csaba Henk <csaba@redhat.com>
87c3ef
Date: Fri, 8 May 2020 23:01:04 +0200
87c3ef
Subject: [PATCH 441/449] fuse: occasional logging for fuse device 'weird'
87c3ef
 write errors
87c3ef
87c3ef
This change is a followup to
87c3ef
I510158843e4b1d482bdc496c2e97b1860dc1ba93.
87c3ef
87c3ef
In referred change we pushed log messages about 'weird'
87c3ef
write errors to fuse device out of sight, by reporting
87c3ef
them at Debug loglevel instead of Error (where
87c3ef
'weird' means errno is not POSIX compliant but having
87c3ef
meaningful semantics for FUSE protocol).
87c3ef
87c3ef
This solved the issue of spurious error reporting.
87c3ef
And so far so good: these messages don't indicate
87c3ef
an error condition by themselves. However, when they
87c3ef
come in high repetitions, that indicates a suboptimal
87c3ef
condition which should be reported.[1]
87c3ef
87c3ef
Therefore now we shall emit a Warning if a certain
87c3ef
errno occurs a certain number of times[2] as the
87c3ef
outcome of a write to the fuse device.
87c3ef
87c3ef
___
87c3ef
[1] typically ENOENTs and ENOTDIRs accumulate
87c3ef
when glusterfs' inode invalidation lags behind
87c3ef
the kernel's internal inode garbage collection
87c3ef
(in this case above errnos mean that the inode
87c3ef
which we requested to be invalidated is not found
87c3ef
in kernel). This can be mitigated with the
87c3ef
invalidate-limit command line / mount option,
87c3ef
cf. bz#1732717.
87c3ef
87c3ef
[2] 256, as of the current implementation.
87c3ef
87c3ef
Upstream on https://review.gluster.org/24415
87c3ef
> Change-Id: I8cc7fe104da43a88875f93b0db49d5677cc16045
87c3ef
> Updates: #1000
87c3ef
> Signed-off-by: Csaba Henk <csaba@redhat.com>
87c3ef
87c3ef
BUG: 1839137
87c3ef
Change-Id: I8448d6d328d47cb01d560cd99a2f43cd8dab312d
87c3ef
Signed-off-by: Csaba Henk <csaba@redhat.com>
87c3ef
Reviewed-on: https://code.engineering.redhat.com/gerrit/202646
87c3ef
Tested-by: RHGS Build Bot <nigelb@redhat.com>
87c3ef
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
87c3ef
---
87c3ef
 xlators/mount/fuse/src/fuse-bridge.c | 36 +++++++++++++++++++++++++++++++++++-
87c3ef
 xlators/mount/fuse/src/fuse-bridge.h | 18 ++++++++++++++++++
87c3ef
 2 files changed, 53 insertions(+), 1 deletion(-)
87c3ef
87c3ef
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
87c3ef
index 4264fad..2e7584c 100644
87c3ef
--- a/xlators/mount/fuse/src/fuse-bridge.c
87c3ef
+++ b/xlators/mount/fuse/src/fuse-bridge.c
87c3ef
@@ -218,14 +218,30 @@ check_and_dump_fuse_W(fuse_private_t *priv, struct iovec *iov_out, int count,
87c3ef
     if (res == -1) {
87c3ef
         const char *errdesc = NULL;
87c3ef
         gf_loglevel_t loglevel = GF_LOG_ERROR;
87c3ef
+        gf_boolean_t errno_degraded = _gf_false;
87c3ef
+        gf_boolean_t errno_promoted = _gf_false;
87c3ef
+
87c3ef
+#define ACCOUNT_ERRNO(eno)                                                     \
87c3ef
+    do {                                                                       \
87c3ef
+        if (errno_degraded) {                                                  \
87c3ef
+            pthread_mutex_lock(&priv->fusedev_errno_cnt_mutex);                \
87c3ef
+            {                                                                  \
87c3ef
+                if (!++priv->fusedev_errno_cnt[FUSEDEV_##eno])                 \
87c3ef
+                    errno_promoted = _gf_true;                                 \
87c3ef
+            }                                                                  \
87c3ef
+            pthread_mutex_unlock(&priv->fusedev_errno_cnt_mutex);              \
87c3ef
+        }                                                                      \
87c3ef
+    } while (0)
87c3ef
 
87c3ef
         /* If caller masked the errno, then it
87c3ef
          * does not indicate an error at the application
87c3ef
          * level, so we degrade the log severity to DEBUG.
87c3ef
          */
87c3ef
         if (errnomask && errno < ERRNOMASK_MAX &&
87c3ef
-            GET_ERRNO_MASK(errnomask, errno))
87c3ef
+            GET_ERRNO_MASK(errnomask, errno)) {
87c3ef
             loglevel = GF_LOG_DEBUG;
87c3ef
+            errno_degraded = _gf_true;
87c3ef
+        }
87c3ef
 
87c3ef
         switch (errno) {
87c3ef
             /* The listed errnos are FUSE status indicators,
87c3ef
@@ -235,33 +251,43 @@ check_and_dump_fuse_W(fuse_private_t *priv, struct iovec *iov_out, int count,
87c3ef
              */
87c3ef
             case ENOENT:
87c3ef
                 errdesc = "ENOENT";
87c3ef
+                ACCOUNT_ERRNO(ENOENT);
87c3ef
                 break;
87c3ef
             case ENOTDIR:
87c3ef
                 errdesc = "ENOTDIR";
87c3ef
+                ACCOUNT_ERRNO(ENOTDIR);
87c3ef
                 break;
87c3ef
             case ENODEV:
87c3ef
                 errdesc = "ENODEV";
87c3ef
+                ACCOUNT_ERRNO(ENODEV);
87c3ef
                 break;
87c3ef
             case EPERM:
87c3ef
                 errdesc = "EPERM";
87c3ef
+                ACCOUNT_ERRNO(EPERM);
87c3ef
                 break;
87c3ef
             case ENOMEM:
87c3ef
                 errdesc = "ENOMEM";
87c3ef
+                ACCOUNT_ERRNO(ENOMEM);
87c3ef
                 break;
87c3ef
             case ENOTCONN:
87c3ef
                 errdesc = "ENOTCONN";
87c3ef
+                ACCOUNT_ERRNO(ENOTCONN);
87c3ef
                 break;
87c3ef
             case ECONNREFUSED:
87c3ef
                 errdesc = "ECONNREFUSED";
87c3ef
+                ACCOUNT_ERRNO(ECONNREFUSED);
87c3ef
                 break;
87c3ef
             case EOVERFLOW:
87c3ef
                 errdesc = "EOVERFLOW";
87c3ef
+                ACCOUNT_ERRNO(EOVERFLOW);
87c3ef
                 break;
87c3ef
             case EBUSY:
87c3ef
                 errdesc = "EBUSY";
87c3ef
+                ACCOUNT_ERRNO(EBUSY);
87c3ef
                 break;
87c3ef
             case ENOTEMPTY:
87c3ef
                 errdesc = "ENOTEMPTY";
87c3ef
+                ACCOUNT_ERRNO(ENOTEMPTY);
87c3ef
                 break;
87c3ef
             default:
87c3ef
                 errdesc = strerror(errno);
87c3ef
@@ -269,7 +295,13 @@ check_and_dump_fuse_W(fuse_private_t *priv, struct iovec *iov_out, int count,
87c3ef
 
87c3ef
         gf_log_callingfn("glusterfs-fuse", loglevel,
87c3ef
                          "writing to fuse device failed: %s", errdesc);
87c3ef
+        if (errno_promoted)
87c3ef
+            gf_log("glusterfs-fuse", GF_LOG_WARNING,
87c3ef
+                   "writing to fuse device yielded %s %d times", errdesc,
87c3ef
+                   UINT8_MAX + 1);
87c3ef
         return errno;
87c3ef
+
87c3ef
+#undef ACCOUNT_ERRNO
87c3ef
     }
87c3ef
 
87c3ef
     fouh = iov_out[0].iov_base;
87c3ef
@@ -6584,6 +6616,8 @@ init(xlator_t *this_xl)
87c3ef
     INIT_LIST_HEAD(&priv->interrupt_list);
87c3ef
     pthread_mutex_init(&priv->interrupt_mutex, NULL);
87c3ef
 
87c3ef
+    pthread_mutex_init(&priv->fusedev_errno_cnt_mutex, NULL);
87c3ef
+
87c3ef
     /* get options from option dictionary */
87c3ef
     ret = dict_get_str(options, ZR_MOUNTPOINT_OPT, &value_string);
87c3ef
     if (ret == -1 || value_string == NULL) {
87c3ef
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
87c3ef
index d2d462c..2fb15a6 100644
87c3ef
--- a/xlators/mount/fuse/src/fuse-bridge.h
87c3ef
+++ b/xlators/mount/fuse/src/fuse-bridge.h
87c3ef
@@ -78,6 +78,20 @@ typedef struct fuse_in_header fuse_in_header_t;
87c3ef
 typedef void(fuse_handler_t)(xlator_t *this, fuse_in_header_t *finh, void *msg,
87c3ef
                              struct iobuf *iobuf);
87c3ef
 
87c3ef
+enum fusedev_errno {
87c3ef
+    FUSEDEV_ENOENT,
87c3ef
+    FUSEDEV_ENOTDIR,
87c3ef
+    FUSEDEV_ENODEV,
87c3ef
+    FUSEDEV_EPERM,
87c3ef
+    FUSEDEV_ENOMEM,
87c3ef
+    FUSEDEV_ENOTCONN,
87c3ef
+    FUSEDEV_ECONNREFUSED,
87c3ef
+    FUSEDEV_EOVERFLOW,
87c3ef
+    FUSEDEV_EBUSY,
87c3ef
+    FUSEDEV_ENOTEMPTY,
87c3ef
+    FUSEDEV_EMAXPLUS
87c3ef
+};
87c3ef
+
87c3ef
 struct fuse_private {
87c3ef
     int fd;
87c3ef
     uint32_t proto_minor;
87c3ef
@@ -192,6 +206,10 @@ struct fuse_private {
87c3ef
     /* LRU Limit, if not set, default is 64k for now */
87c3ef
     uint32_t lru_limit;
87c3ef
     uint32_t invalidate_limit;
87c3ef
+
87c3ef
+    /* counters for fusdev errnos */
87c3ef
+    uint8_t fusedev_errno_cnt[FUSEDEV_EMAXPLUS];
87c3ef
+    pthread_mutex_t fusedev_errno_cnt_mutex;
87c3ef
 };
87c3ef
 typedef struct fuse_private fuse_private_t;
87c3ef
 
87c3ef
-- 
87c3ef
1.8.3.1
87c3ef