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