diff options
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.patch | 223 |
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 + |