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