summaryrefslogtreecommitdiff
path: root/0346-fuse-degrade-logging-of-write-failure-to-fuse-device.patch
diff options
context:
space:
mode:
Diffstat (limited to '0346-fuse-degrade-logging-of-write-failure-to-fuse-device.patch')
-rw-r--r--0346-fuse-degrade-logging-of-write-failure-to-fuse-device.patch223
1 files changed, 223 insertions, 0 deletions
diff --git a/0346-fuse-degrade-logging-of-write-failure-to-fuse-device.patch b/0346-fuse-degrade-logging-of-write-failure-to-fuse-device.patch
new file mode 100644
index 0000000..9fca79e
--- /dev/null
+++ b/0346-fuse-degrade-logging-of-write-failure-to-fuse-device.patch
@@ -0,0 +1,223 @@
+From e2af9793014ad67859aa73088765a52307cbe466 Mon Sep 17 00:00:00 2001
+From: Csaba Henk <csaba@redhat.com>
+Date: Tue, 7 Jan 2020 19:43:05 +0100
+Subject: [PATCH 346/346] fuse: degrade logging of write failure to fuse device
+
+Problem:
+
+FUSE uses failures of communicating with /dev/fuse with various
+errnos to indicate in-kernel conditions to userspace. Some of these
+shouldn't be handled as an application error. Also the standard
+POSIX errno description should not be shown as they are misleading
+in this context.
+
+Solution:
+
+When writing to the fuse device, the caller of the respective
+convenience routine can mask those errnos which don't qualify to
+be an error for the application in that context, so then those
+shall be reported at DEBUG level.
+
+The possible non-standard errnos are reported with their
+POSIX name instead of their description to avoid confusion.
+(Eg. for ENOENT we don't log "no such file or directory",
+we log indeed literal "ENOENT".)
+
+Upstream on https://review.gluster.org/23974
+> Change-Id: I510158843e4b1d482bdc496c2e97b1860dc1ba93
+> updates: bz#1193929
+> Signed-off-by: Csaba Henk <csaba@redhat.com>
+
+BUG: 1763208
+Change-Id: Ib1676bb334ed153ce74ae1c0413fc0e58fb388c7
+Signed-off-by: Csaba Henk <csaba@redhat.com>
+Reviewed-on: https://code.engineering.redhat.com/gerrit/189056
+Tested-by: RHGS Build Bot <nigelb@redhat.com>
+Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
+---
+ xlators/mount/fuse/src/fuse-bridge.c | 78 +++++++++++++++++++++++++++++++++---
+ xlators/mount/fuse/src/fuse-bridge.h | 9 ++++-
+ 2 files changed, 80 insertions(+), 7 deletions(-)
+
+diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
+index ebe5c28..6e99053 100644
+--- a/xlators/mount/fuse/src/fuse-bridge.c
++++ b/xlators/mount/fuse/src/fuse-bridge.c
+@@ -198,7 +198,7 @@ fusedump_setup_meta(struct iovec *iovs, char *dir,
+
+ static int
+ check_and_dump_fuse_W(fuse_private_t *priv, struct iovec *iov_out, int count,
+- ssize_t res)
++ ssize_t res, errnomask_t errnomask)
+ {
+ char w = 'W';
+ struct iovec diov[4] = {
+@@ -216,8 +216,59 @@ check_and_dump_fuse_W(fuse_private_t *priv, struct iovec *iov_out, int count,
+ struct fuse_out_header *fouh = NULL;
+
+ if (res == -1) {
+- gf_log_callingfn("glusterfs-fuse", GF_LOG_ERROR,
+- "writing to fuse device failed: %s", strerror(errno));
++ const char *errdesc = NULL;
++ gf_loglevel_t loglevel = GF_LOG_ERROR;
++
++ /* If caller masked the errno, then it
++ * does not indicate an error at the application
++ * level, so we degrade the log severity to DEBUG.
++ */
++ if (errnomask && errno < ERRNOMASK_MAX &&
++ GET_ERRNO_MASK(errnomask, errno))
++ loglevel = GF_LOG_DEBUG;
++
++ switch (errno) {
++ /* The listed errnos are FUSE status indicators,
++ * not legit values according to POSIX (see write(3p)),
++ * so resolving them according to the standard
++ * POSIX interpretation would be misleading.
++ */
++ case ENOENT:
++ errdesc = "ENOENT";
++ break;
++ case ENOTDIR:
++ errdesc = "ENOTDIR";
++ break;
++ case ENODEV:
++ errdesc = "ENODEV";
++ break;
++ case EPERM:
++ errdesc = "EPERM";
++ break;
++ case ENOMEM:
++ errdesc = "ENOMEM";
++ break;
++ case ENOTCONN:
++ errdesc = "ENOTCONN";
++ break;
++ case ECONNREFUSED:
++ errdesc = "ECONNREFUSED";
++ break;
++ case EOVERFLOW:
++ errdesc = "EOVERFLOW";
++ break;
++ case EBUSY:
++ errdesc = "EBUSY";
++ break;
++ case ENOTEMPTY:
++ errdesc = "ENOTEMPTY";
++ break;
++ default:
++ errdesc = strerror(errno);
++ }
++
++ gf_log_callingfn("glusterfs-fuse", loglevel,
++ "writing to fuse device failed: %s", errdesc);
+ return errno;
+ }
+
+@@ -282,7 +333,7 @@ send_fuse_iov(xlator_t *this, fuse_in_header_t *finh, struct iovec *iov_out,
+ gf_log("glusterfs-fuse", GF_LOG_TRACE, "writev() result %d/%d %s", res,
+ fouh->len, res == -1 ? strerror(errno) : "");
+
+- return check_and_dump_fuse_W(priv, iov_out, count, res);
++ return check_and_dump_fuse_W(priv, iov_out, count, res, NULL);
+ }
+
+ static int
+@@ -353,6 +404,15 @@ fuse_invalidate_entry(xlator_t *this, uint64_t fuse_ino)
+ fouh->unique = 0;
+ fouh->error = FUSE_NOTIFY_INVAL_ENTRY;
+
++ if (ENOENT < ERRNOMASK_MAX)
++ MASK_ERRNO(node->errnomask, ENOENT);
++ if (ENOTDIR < ERRNOMASK_MAX)
++ MASK_ERRNO(node->errnomask, ENOTDIR);
++ if (EBUSY < ERRNOMASK_MAX)
++ MASK_ERRNO(node->errnomask, EBUSY);
++ if (ENOTEMPTY < ERRNOMASK_MAX)
++ MASK_ERRNO(node->errnomask, ENOTEMPTY);
++
+ if (dentry->name) {
+ nlen = strlen(dentry->name);
+ fouh->len = sizeof(*fouh) + sizeof(*fnieo) + nlen + 1;
+@@ -437,6 +497,9 @@ fuse_invalidate_inode(xlator_t *this, uint64_t fuse_ino)
+ fniio->off = 0;
+ fniio->len = -1;
+
++ if (ENOENT < ERRNOMASK_MAX)
++ MASK_ERRNO(node->errnomask, ENOENT);
++
+ fuse_log_eh(this, "Invalidated inode %" PRIu64 " (gfid: %s)", fuse_ino,
+ uuid_utoa(inode->gfid));
+ gf_log("glusterfs-fuse", GF_LOG_TRACE,
+@@ -482,6 +545,7 @@ fuse_timed_message_new(void)
+ /* should be NULL if not set */
+ dmsg->fuse_message_body = NULL;
+ INIT_LIST_HEAD(&dmsg->next);
++ memset(dmsg->errnomask, 0, sizeof(dmsg->errnomask));
+
+ return dmsg;
+ }
+@@ -680,6 +744,8 @@ fuse_interrupt(xlator_t *this, fuse_in_header_t *finh, void *msg,
+ dmsg->fuse_out_header.unique = finh->unique;
+ dmsg->fuse_out_header.len = sizeof(dmsg->fuse_out_header);
+ dmsg->fuse_out_header.error = -EAGAIN;
++ if (ENOENT < ERRNOMASK_MAX)
++ MASK_ERRNO(dmsg->errnomask, ENOENT);
+ timespec_now(&dmsg->scheduled_ts);
+ timespec_adjust_delta(&dmsg->scheduled_ts,
+ (struct timespec){0, 10000000});
+@@ -4848,7 +4914,7 @@ notify_kernel_loop(void *data)
+ iov_out.iov_base = node->inval_buf;
+ iov_out.iov_len = len;
+ rv = sys_writev(priv->fd, &iov_out, 1);
+- check_and_dump_fuse_W(priv, &iov_out, 1, rv);
++ check_and_dump_fuse_W(priv, &iov_out, 1, rv, node->errnomask);
+
+ GF_FREE(node);
+
+@@ -4940,7 +5006,7 @@ timed_response_loop(void *data)
+ iovs[1] = (struct iovec){dmsg->fuse_message_body,
+ len - sizeof(struct fuse_out_header)};
+ rv = sys_writev(priv->fd, iovs, 2);
+- check_and_dump_fuse_W(priv, iovs, 2, rv);
++ check_and_dump_fuse_W(priv, iovs, 2, rv, dmsg->errnomask);
+
+ fuse_timed_message_free(dmsg);
+
+diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
+index cf4479c..d2d462c 100644
+--- a/xlators/mount/fuse/src/fuse-bridge.h
++++ b/xlators/mount/fuse/src/fuse-bridge.h
+@@ -195,14 +195,20 @@ struct fuse_private {
+ };
+ typedef struct fuse_private fuse_private_t;
+
++typedef uint64_t errnomask_t[2];
++#define MASK_ERRNO(mask, n) ((mask)[(n) >> 6] |= ((uint64_t)1 << ((n)&63)))
++#define GET_ERRNO_MASK(mask, n) ((mask)[(n) >> 6] & ((uint64_t)1 << ((n)&63)))
++#define ERRNOMASK_MAX (64 * (sizeof(errnomask_t) / sizeof(uint64_t)))
++
+ #define INVAL_BUF_SIZE \
+ (sizeof(struct fuse_out_header) + \
+ max(sizeof(struct fuse_notify_inval_inode_out), \
+ sizeof(struct fuse_notify_inval_entry_out) + NAME_MAX + 1))
+
+ struct fuse_invalidate_node {
+- char inval_buf[INVAL_BUF_SIZE];
++ errnomask_t errnomask;
+ struct list_head next;
++ char inval_buf[INVAL_BUF_SIZE];
+ };
+ typedef struct fuse_invalidate_node fuse_invalidate_node_t;
+
+@@ -210,6 +216,7 @@ struct fuse_timed_message {
+ struct fuse_out_header fuse_out_header;
+ void *fuse_message_body;
+ struct timespec scheduled_ts;
++ errnomask_t errnomask;
+ struct list_head next;
+ };
+ typedef struct fuse_timed_message fuse_timed_message_t;
+--
+1.8.3.1
+