From 61b09562b934b53dadcd566f6feb72301097933c Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Thu, 11 Jul 2013 12:52:11 +0530 Subject: mount/fuse: Provide option to use/not use kernel-readdirp By default fuse kernel readdirp usage in fuse xlator is off. When mount option use-readdirp=yes is provided it starts using fuse-kernel's readdirp. Change-Id: Id37edc53b1adc1638186d956c2f74c1e4e48aa59 BUG: 983477 Signed-off-by: Pranith Kumar K Reviewed-on: http://review.gluster.org/5322 Tested-by: Gluster Build System Reviewed-by: Raghavendra Bhat Reviewed-by: Vijay Bellur --- glusterfsd/src/glusterfsd.c | 32 ++++++++++++++++++++ glusterfsd/src/glusterfsd.h | 1 + libglusterfs/src/glusterfs.h | 1 + tests/bugs/bug-983477.t | 45 +++++++++++++++++++++++++++++ xlators/mount/fuse/src/fuse-bridge.c | 13 +++++++-- xlators/mount/fuse/src/fuse-bridge.h | 3 ++ xlators/mount/fuse/utils/mount.glusterfs.in | 5 ++++ 7 files changed, 98 insertions(+), 2 deletions(-) create mode 100755 tests/bugs/bug-983477.t diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index 1c746d9c..213b589a 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -198,6 +198,9 @@ static struct argp_option gf_options[] = { "Enable internal memory accounting"}, {"fuse-mountopts", ARGP_FUSE_MOUNTOPTS_KEY, "OPTIONS", OPTION_HIDDEN, "Extra mount options to pass to FUSE"}, + {"use-readdirp", ARGP_FUSE_USE_READDIRP_KEY, "BOOL", OPTION_ARG_OPTIONAL, + "Use readdirp mode in fuse kernel module" + " [default: \"off\"]"}, {0, 0, 0, 0, "Miscellaneous Options:"}, {0, } }; @@ -440,6 +443,16 @@ set_fuse_mount_options (glusterfs_ctx_t *ctx, dict_t *options) goto err; } } + + if (cmd_args->use_readdirp) { + ret = dict_set_str (options, "use-readdirp", + cmd_args->use_readdirp); + if (ret < 0) { + gf_log ("glusterfsd", GF_LOG_ERROR, "failed to set dict" + " value for key use-readdirp"); + goto err; + } + } ret = 0; err: return ret; @@ -949,6 +962,25 @@ parse_opts (int key, char *arg, struct argp_state *state) case ARGP_FUSE_MOUNTOPTS_KEY: cmd_args->fuse_mountopts = gf_strdup (arg); break; + + case ARGP_FUSE_USE_READDIRP_KEY: + if (!arg) + arg = "no"; + + if (gf_string2boolean (arg, &b) == 0) { + if (b) { + cmd_args->use_readdirp = "yes"; + } else { + cmd_args->use_readdirp = "no"; + } + + break; + } + + argp_failure (state, -1, 0, + "unknown use-readdirp setting \"%s\"", arg); + break; + } return 0; diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h index 5b5805d1..be91ce54 100644 --- a/glusterfsd/src/glusterfsd.h +++ b/glusterfsd/src/glusterfsd.h @@ -84,6 +84,7 @@ enum argp_option_keys { ARGP_FUSE_CONGESTION_THRESHOLD_KEY = 162, ARGP_INODE32_KEY = 163, ARGP_FUSE_MOUNTOPTS_KEY = 164, + ARGP_FUSE_USE_READDIRP_KEY = 165, }; struct _gfd_vol_top_priv_t { diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index a50cc7fb..fbf4722c 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -321,6 +321,7 @@ struct _cmd_args { /* fuse options */ int fuse_direct_io_mode; + char *use_readdirp; int volfile_check; double fuse_entry_timeout; double fuse_negative_timeout; diff --git a/tests/bugs/bug-983477.t b/tests/bugs/bug-983477.t new file mode 100755 index 00000000..dfb0f381 --- /dev/null +++ b/tests/bugs/bug-983477.t @@ -0,0 +1,45 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +#This script checks if use-readdirp option works as accepted in mount options + +function get_use_readdirp_value { + local vol=$1 + local statedump=$(generate_mount_statedump $vol) + local val=$(grep "use_readdirp=" $statedump | cut -f2 -d'=' | tail -1) + rm -f $statedump + echo $val +} +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0} +TEST $CLI volume start $V0 +#If readdirp is enabled statedump should reflect it +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 --use-readdirp=yes +TEST cd $M0 +EXPECT_WITHIN 20 "1" get_use_readdirp_value $V0 +TEST cd - +TEST umount $M0 + +#If readdirp is enabled statedump should reflect it +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 --use-readdirp=no +TEST cd $M0 +EXPECT_WITHIN 20 "0" get_use_readdirp_value $V0 +TEST cd - +TEST umount $M0 + +#By default it is disabled. +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 +TEST cd $M0 +EXPECT_WITHIN 20 "0" get_use_readdirp_value $V0 +TEST cd - +TEST umount $M0 + +#Invalid values for use-readdirp should not be accepted +TEST ! glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 --use-readdirp=please-fail + +cleanup diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 5b6fed9f..ce33009d 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -3752,8 +3752,10 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg) if (fini->minor < 9) *priv->msg0_len_p = sizeof(*finh) + FUSE_COMPAT_WRITE_IN_SIZE; #endif - if (fini->flags & FUSE_DO_READDIRPLUS) - fino.flags |= FUSE_DO_READDIRPLUS; + if (priv->use_readdirp) { + if (fini->flags & FUSE_DO_READDIRPLUS) + fino.flags |= FUSE_DO_READDIRPLUS; + } if (fini->flags & FUSE_ASYNC_DIO) fino.flags |= FUSE_ASYNC_DIO; @@ -4728,6 +4730,7 @@ fuse_priv_dump (xlator_t *this) (int)private->strict_volfile_check); gf_proc_dump_write("reverse_thread_started", "%d", (int)private->reverse_fuse_thread_started); + gf_proc_dump_write("use_readdirp", "%d", private->use_readdirp); return 0; } @@ -5115,6 +5118,8 @@ init (xlator_t *this_xl) GF_OPTION_INIT ("enable-ino32", priv->enable_ino32, bool, cleanup_exit); + GF_OPTION_INIT ("use-readdirp", priv->use_readdirp, bool, cleanup_exit); + priv->fuse_dump_fd = -1; ret = dict_get_str (options, "dump-fuse", &value_string); if (ret == 0) { @@ -5394,5 +5399,9 @@ struct volume_options options[] = { { .key = {"fuse-mountopts"}, .type = GF_OPTION_TYPE_STR }, + { .key = {"use-readdirp"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "no" + }, { .key = {NULL} }, }; diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index d90b85e7..2626638d 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -119,6 +119,9 @@ struct fuse_private { /* for fuse queue length and congestion threshold */ int background_qlen; int congestion_threshold; + + /* for using fuse-kernel readdirp*/ + gf_boolean_t use_readdirp; }; 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 3fedb8ce..c0a2ed1a 100755 --- a/xlators/mount/fuse/utils/mount.glusterfs.in +++ b/xlators/mount/fuse/utils/mount.glusterfs.in @@ -135,6 +135,10 @@ start_glusterfs () cmd_line=$(echo "$cmd_line --direct-io-mode=$direct_io_mode"); fi + if [ -n "$use_readdirp" ]; then + cmd_line=$(echo "$cmd_line --use-readdirp=$use_readdirp"); + fi + if [ -n "$volume_name" ]; then cmd_line=$(echo "$cmd_line --volume-name=$volume_name"); fi @@ -376,6 +380,7 @@ main () "congestion-threshold") cong_threshold=$value ;; "xlator-option") xlator_option=$xlator_option" "$pair ;; "fuse-mountopts") fuse_mountopts=$value ;; + "use-readdirp") use_readdirp=$value ;; *) # Passthru [ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts," -- cgit