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