summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--glusterfsd/src/glusterfsd.c28
-rw-r--r--glusterfsd/src/glusterfsd.h3
-rw-r--r--libglusterfs/src/glusterfs/glusterfs.h2
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c22
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h2
-rwxr-xr-xxlators/mount/fuse/utils/mount.glusterfs.in7
6 files changed, 63 insertions, 1 deletions
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c
index cf6d9a7215c..968b97c2eac 100644
--- a/glusterfsd/src/glusterfsd.c
+++ b/glusterfsd/src/glusterfsd.c
@@ -276,6 +276,9 @@ static struct argp_option gf_options[] = {
"attribute, dentry and page-cache. "
"Disable this only if same files/directories are not accessed across "
"two different mounts concurrently [default: \"on\"]"},
+ {"fuse-dev-eperm-ratelimit-ns", ARGP_FUSE_DEV_EPERM_RATELIMIT_NS_KEY,
+ "OPTIONS", OPTION_HIDDEN,
+ "rate limit reading from fuse device upon EPERM failure"},
{"brick-mux", ARGP_BRICK_MUX_KEY, 0, 0, "Enable brick mux. "},
{0, 0, 0, 0, "Miscellaneous Options:"},
{
@@ -707,6 +710,16 @@ set_fuse_mount_options(glusterfs_ctx_t *ctx, dict_t *options)
goto err;
}
}
+ if (cmd_args->fuse_dev_eperm_ratelimit_ns) {
+ ret = dict_set_uint32(options, "fuse-dev-eperm-ratelimit-ns",
+ cmd_args->fuse_dev_eperm_ratelimit_ns);
+ if (ret < 0) {
+ gf_msg("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4,
+ "failed to set dict value for key "
+ "fuse-dev-eperm-ratelimit-ns");
+ goto err;
+ }
+ }
ret = 0;
err:
@@ -1536,6 +1549,21 @@ parse_opts(int key, char *arg, struct argp_state *state)
argp_failure(state, -1, 0,
"Invalid value for global threading \"%s\"", arg);
break;
+
+ case ARGP_FUSE_DEV_EPERM_RATELIMIT_NS_KEY:
+ if (gf_string2uint32(arg, &cmd_args->fuse_dev_eperm_ratelimit_ns)) {
+ argp_failure(state, -1, 0,
+ "Non-numerical value for "
+ "'fuse-dev-eperm-ratelimit-ns' option %s",
+ arg);
+ } else if (cmd_args->fuse_dev_eperm_ratelimit_ns > 1000000000) {
+ argp_failure(state, -1, 0,
+ "Invalid 'fuse-dev-eperm-ratelimit-ns' value %s. "
+ "Valid range: [\"0, 1000000000\"]",
+ arg);
+ }
+
+ break;
}
return 0;
}
diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h
index dc7d995e778..8a7c034ce40 100644
--- a/glusterfsd/src/glusterfsd.h
+++ b/glusterfsd/src/glusterfsd.h
@@ -112,7 +112,8 @@ enum argp_option_keys {
ARGP_FUSE_LRU_LIMIT_KEY = 190,
ARGP_FUSE_AUTO_INVAL_KEY = 191,
ARGP_GLOBAL_THREADING_KEY = 192,
- ARGP_BRICK_MUX_KEY = 193
+ ARGP_BRICK_MUX_KEY = 193,
+ ARGP_FUSE_DEV_EPERM_RATELIMIT_NS_KEY = 194,
};
struct _gfd_vol_top_priv {
diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h
index 967bf5b40e7..d59306508b2 100644
--- a/libglusterfs/src/glusterfs/glusterfs.h
+++ b/libglusterfs/src/glusterfs/glusterfs.h
@@ -573,6 +573,8 @@ struct _cmd_args {
bool global_threading;
bool brick_mux;
+
+ uint32_t fuse_dev_eperm_ratelimit_ns;
};
typedef struct _cmd_args cmd_args_t;
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index c1ce008eace..3a779625a08 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -5976,6 +5976,16 @@ fuse_thread_proc(void *data)
"glusterfs-fuse: read from "
"/dev/fuse returned -1 (%s)",
strerror(errno));
+ if (errno == EPERM) {
+ /*
+ * sleep a while to avoid busy looping
+ * on EPERM condition
+ */
+ nanosleep(
+ &(struct timespec){0,
+ priv->fuse_dev_eperm_ratelimit_ns},
+ NULL);
+ }
}
goto cont_err;
@@ -6692,6 +6702,9 @@ init(xlator_t *this_xl)
GF_OPTION_INIT("flush-handle-interrupt", priv->flush_handle_interrupt, bool,
cleanup_exit);
+ GF_OPTION_INIT("fuse-dev-eperm-ratelimit-ns",
+ priv->fuse_dev_eperm_ratelimit_ns, uint32, cleanup_exit);
+
/* user has set only background-qlen, not congestion-threshold,
use the fuse kernel driver formula to set congestion. ie, 75% */
if (dict_get(this_xl->options, "background-qlen") &&
@@ -7023,6 +7036,15 @@ struct volume_options options[] = {
"if same files/directories are not accessed across "
"two different mounts concurrently",
},
+ {
+ .key = {"fuse-dev-eperm-ratelimit-ns"},
+ .type = GF_OPTION_TYPE_INT,
+ .default_value = "10000000", /* 0.01 sec */
+ .min = 0,
+ .max = 1000000000,
+ .description = "Rate limit reading from fuse device upon EPERM "
+ "failure.",
+ },
{.key = {NULL}},
};
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
index 697bd8848e1..8d25bed0481 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -191,6 +191,8 @@ struct fuse_private {
/* LRU Limit, if not set, default is 128k for now */
uint32_t lru_limit;
+
+ uint32_t fuse_dev_eperm_ratelimit_ns;
};
typedef struct fuse_private fuse_private_t;
diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in
index 29906316266..21cc018eaa5 100755
--- a/xlators/mount/fuse/utils/mount.glusterfs.in
+++ b/xlators/mount/fuse/utils/mount.glusterfs.in
@@ -362,6 +362,10 @@ start_glusterfs ()
cmd_line=$(echo "$cmd_line --subdir-mount=/$subdir_mount");
fi
+ if [ -n "$fuse_dev_eperm_ratelimit_ns" ]; then
+ cmd_line=$(echo "$cmd_line --fuse-dev-eperm-ratelimit-ns=$fuse_dev_eperm_ratelimit_ns");
+ fi
+
cmd_line=$(echo "$cmd_line $mount_point");
$cmd_line;
if [ $? -ne 0 ]; then
@@ -571,6 +575,9 @@ with_options()
"fuse-flush-handle-interrupt")
fuse_flush_handle_interrupt=$value
;;
+ "fuse-dev-eperm-ratelimit-ns")
+ fuse_dev_eperm_ratelimit_ns=$value
+ ;;
"context"|"fscontext"|"defcontext"|"rootcontext")
# standard SElinux mount options to pass to the kernel
[ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts,"