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