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