diff options
| -rw-r--r-- | doc/glusterfs.8 | 6 | ||||
| -rw-r--r-- | doc/mount.glusterfs.8 | 6 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd.c | 70 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd.h | 2 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 4 | ||||
| -rw-r--r-- | libglusterfs/src/xlator.h | 1 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 50 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 4 | ||||
| -rwxr-xr-x | xlators/mount/fuse/utils/mount.glusterfs.in | 14 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-inode-fd-ops.c | 17 | 
10 files changed, 170 insertions, 4 deletions
diff --git a/doc/glusterfs.8 b/doc/glusterfs.8 index 985f30a5865..592dedb6759 100644 --- a/doc/glusterfs.8 +++ b/doc/glusterfs.8 @@ -109,6 +109,9 @@ Mount subdirectory instead of the '/' of volume.  .PP  .TP +\fB\-\-attr\-times\-granularity=NANOSECONDS\fR +Declare supported granularity of file attribute times (default is 0 which kernel handles as unspecified; valid real values are between 1 and 1000000000). +.TP  \fB\-\-attribute\-timeout=SECONDS\fR  Set attribute timeout to SECONDS for inodes in fuse kernel module (the default is 1).  .TP @@ -130,6 +133,9 @@ Set entry timeout to SECONDS in fuse kernel module (the default is 1).  \fB\-\-gid\-timeout=SECONDS\fR  Set auxiliary group list timeout to SECONDS for fuse translator (the default is 0).  .TP +\fB\-\-kernel-writeback-cache=BOOL\fR +Enable fuse in-kernel writeback cache. +.TP  \fB\-\-negative\-timeout=SECONDS\fR  Set negative timeout to SECONDS in fuse kernel module (the default is 0).  .TP diff --git a/doc/mount.glusterfs.8 b/doc/mount.glusterfs.8 index 6a51fc9aef0..0cc7a6f8535 100644 --- a/doc/mount.glusterfs.8 +++ b/doc/mount.glusterfs.8 @@ -133,6 +133,12 @@ enable root squashing for the trusted client [default: on]  .TP  \fBuse\-readdirp=\fRBOOL  Use readdirp() mode in fuse kernel module [default: on] +.TP +\fBkernel\-writeback\-cache=\fRBOOL +Enable fuse in-kernel writeback cache [default: off] +.TP +\fBattr\-times\-granularity=\fRNS +Declare supported granularity of file attribute [default: 0]  .PP  .SH FILES  .TP diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index b5b8e4d30a7..3de12bc125f 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -256,6 +256,11 @@ static struct argp_option gf_options[] = {           OPTION_ARG_OPTIONAL, "disable/enable fuse event-history"},          {"reader-thread-count", ARGP_READER_THREAD_COUNT_KEY, "INTEGER",           OPTION_ARG_OPTIONAL, "set fuse reader thread count"}, +        {"kernel-writeback-cache", ARGP_KERNEL_WRITEBACK_CACHE_KEY, "BOOL", +         OPTION_ARG_OPTIONAL, "enable fuse in-kernel writeback cache"}, +        {"attr-times-granularity", ARGP_ATTR_TIMES_GRANULARITY_KEY, "NS", +         OPTION_ARG_OPTIONAL, "declare supported granularity of file attribute" +         " times in nanoseconds"},          {0, 0, 0, 0, "Miscellaneous Options:"},          {0, }  }; @@ -617,6 +622,44 @@ set_fuse_mount_options (glusterfs_ctx_t *ctx, dict_t *options)                          goto err;                  }          } +        switch (cmd_args->kernel_writeback_cache) { +        case GF_OPTION_ENABLE: +                ret = dict_set_static_ptr(options, "kernel-writeback-cache", +                        "on"); +                if (ret < 0) { +                        gf_msg ("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4, +                                "failed to set dict value for key " +                                "kernel-writeback-cache"); +                        goto err; +                } +                break; +        case GF_OPTION_DISABLE: +                ret = dict_set_static_ptr(options, "kernel-writeback-cache", +                        "off"); +                if (ret < 0) { +                        gf_msg ("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4, +                                "failed to set dict value for key " +                                "kernel-writeback-cache"); +                        goto err; +                } +                break; +        case GF_OPTION_DEFERRED: /* default */ +        default: +                gf_msg_debug ("glusterfsd", 0, "kernel-writeback-cache mode %d", +                              cmd_args->kernel_writeback_cache); +                break; +        } +        if (cmd_args->attr_times_granularity) { +                ret = dict_set_uint32 (options, "attr-times-granularity", +                                       cmd_args->attr_times_granularity); +                if (ret < 0) { +                        gf_msg ("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4, +                                "failed to set dict value for key " +                                "attr-times-granularity"); +                        goto err; +                } +        } +          ret = 0;  err: @@ -1385,6 +1428,32 @@ no_oom_api:                  break; +        case ARGP_KERNEL_WRITEBACK_CACHE_KEY: +                if (!arg) +                        arg = "yes"; + +                if (gf_string2boolean (arg, &b) == 0) { +                        cmd_args->kernel_writeback_cache = b; + +                        break; +                } + +                argp_failure (state, -1, 0, +                              "unknown kernel writeback cache setting \"%s\"", arg); +                break; +        case ARGP_ATTR_TIMES_GRANULARITY_KEY: +                if (gf_string2uint32 (arg, &cmd_args->attr_times_granularity)) { +                        argp_failure (state, -1, 0, +                                      "unknown attribute times granularity option %s", +                                      arg); +                } else if (cmd_args->attr_times_granularity > 1000000000) { +                        argp_failure (state, -1, 0, +                                      "Invalid attribute times granularity value %s. " +                                      "Valid range: [\"0, 1000000000\"]", arg); +                } + +                break; +  	}          return 0;  } @@ -1690,6 +1759,7 @@ glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)          cmd_args->fuse_attribute_timeout = -1;          cmd_args->fuse_entry_timeout = -1;  	cmd_args->fopen_keep_cache = GF_OPTION_DEFERRED; +        cmd_args->kernel_writeback_cache = GF_OPTION_DEFERRED;          if (ctx->mem_acct_enable)                  cmd_args->mem_acct = 1; diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h index 2a03ec09fa2..496a4d95352 100644 --- a/glusterfsd/src/glusterfsd.h +++ b/glusterfsd/src/glusterfsd.h @@ -105,6 +105,8 @@ enum argp_option_keys {          ARGP_PRINT_XLATORDIR_KEY          = 183,          ARGP_PRINT_STATEDUMPDIR_KEY       = 184,          ARGP_PRINT_LOGDIR_KEY             = 185, +        ARGP_KERNEL_WRITEBACK_CACHE_KEY   = 186, +        ARGP_ATTR_TIMES_GRANULARITY_KEY   = 187,  };  struct _gfd_vol_top_priv { diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 904d4b60d75..90f2762b990 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -532,6 +532,10 @@ struct _cmd_args {          char              *event_history;          int                thin_client;          uint32_t           reader_thread_count; + +        /* FUSE writeback cache support */ +        int                kernel_writeback_cache; +        uint32_t           attr_times_granularity;  };  typedef struct _cmd_args cmd_args_t; diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index 4f18d1cd2a9..d476cf26442 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -33,6 +33,7 @@  #define GF_SET_ATTR_SIZE  0x8  #define GF_SET_ATTR_ATIME 0x10  #define GF_SET_ATTR_MTIME 0x20 +#define GF_SET_ATTR_CTIME 0x40  #define gf_attr_mode_set(mode)  ((mode) & GF_SET_ATTR_MODE)  #define gf_attr_uid_set(mode)   ((mode) & GF_SET_ATTR_UID) diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index f509d84a15b..322b4deeffa 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -1233,6 +1233,11 @@ fattr_to_gf_set_attr (int32_t valid)          if (valid & FATTR_MTIME)                  gf_valid |= GF_SET_ATTR_MTIME; +#if FUSE_KERNEL_MINOR_VERSION >= 23 +        if (valid & FATTR_CTIME) +                gf_valid |= GF_SET_ATTR_CTIME; +#endif +          if (valid & FATTR_SIZE)                  gf_valid |= GF_SET_ATTR_SIZE; @@ -1271,7 +1276,11 @@ fuse_setattr_resume (fuse_state_t *state)          if ((state->valid & (FATTR_MASK)) != FATTR_SIZE) {                  if (state->fd &&                      !((state->valid & FATTR_ATIME) || -                      (state->valid & FATTR_MTIME))) { +                      (state->valid & FATTR_MTIME) +#if FUSE_KERNEL_MINOR_VERSION >= 23 +                       || (state->valid & FATTR_CTIME) +#endif +                     )) {                          /*                              there is no "futimes" call, so don't send                              fsetattr if ATIME or MTIME is set @@ -1346,8 +1355,14 @@ fuse_setattr (xlator_t *this, fuse_in_header_t *finh, void *msg,                  state->attr.ia_size  = fsi->size;                  state->attr.ia_atime = fsi->atime;                  state->attr.ia_mtime = fsi->mtime; +#if FUSE_KERNEL_MINOR_VERSION >= 23 +                state->attr.ia_ctime = fsi->ctime; +#endif                  state->attr.ia_atime_nsec = fsi->atimensec;                  state->attr.ia_mtime_nsec = fsi->mtimensec; +#if FUSE_KERNEL_MINOR_VERSION >= 23 +                state->attr.ia_ctime_nsec = fsi->ctimensec; +#endif                  state->attr.ia_prot = ia_prot_from_st_mode (fsi->mode);                  state->attr.ia_uid  = fsi->uid; @@ -4253,14 +4268,23 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg,  	if (fini->flags & FUSE_ASYNC_DIO)  		fino.flags |= FUSE_ASYNC_DIO;  #endif + +        size = sizeof (fino); +#if FUSE_KERNEL_MINOR_VERSION >= 23          /* FUSE 7.23 and newer added attributes to the fuse_init_out struct */ -        if (fini->minor > 22) { -                size = sizeof (fino); -        } else { +        if (fini->minor < 23) {                  /* reduce the size, chop off unused attributes from &fino */                  size = FUSE_COMPAT_22_INIT_OUT_SIZE;          } +        /* Writeback cache support */ +        if (fini->minor >= 23) { +                if (priv->kernel_writeback_cache) +                        fino.flags |= FUSE_WRITEBACK_CACHE; +                fino.time_gran = priv->attr_times_granularity; +        } +#endif +          ret = send_fuse_data (this, finh, &fino, size);          if (ret == 0)                  gf_log ("glusterfs-fuse", GF_LOG_INFO, @@ -5770,6 +5794,12 @@ init (xlator_t *this_xl)          GF_OPTION_INIT("thin-client", priv->thin_client, bool,                         cleanup_exit); +        /* Writeback cache support */ +        GF_OPTION_INIT("kernel-writeback-cache", priv->kernel_writeback_cache, +                       bool, cleanup_exit); +        GF_OPTION_INIT("attr-times-granularity", priv->attr_times_granularity, +	               int32, 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") && @@ -6093,5 +6123,17 @@ struct volume_options options[] = {            .max = 64,            .description = "Sets fuse reader thread count.",          }, +        { .key = {"kernel-writeback-cache"}, +          .type = GF_OPTION_TYPE_BOOL, +          .default_value = "false", +          .description = "Enables fuse in-kernel writeback cache.", +        }, +        { .key = {"attr-times-granularity"}, +          .type = GF_OPTION_TYPE_INT, +          .default_value = "0", +          .min = 0, +          .max = 1000000000, +          .description = "Supported granularity of file attribute times.", +        },          { .key = {NULL} },  }; diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index 6cf9d2f7cf8..b26b5e21109 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -147,6 +147,10 @@ struct fuse_private {          gf_boolean_t         mount_finished;          gf_boolean_t         handle_graph_switch;          pthread_cond_t       migrate_cond; + +        /* Writeback cache support */ +        gf_boolean_t         kernel_writeback_cache; +        int                  attr_times_granularity;  };  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 6890ff00121..9d9069aa1f7 100755 --- a/xlators/mount/fuse/utils/mount.glusterfs.in +++ b/xlators/mount/fuse/utils/mount.glusterfs.in @@ -269,6 +269,14 @@ start_glusterfs ()          cmd_line=$(echo "$cmd_line --xlator-option=$xlator_option");      fi +    if [ -n "$kernel_writeback_cache" ]; then +        cmd_line=$(echo "$cmd_line --kernel-writeback-cache=$kernel_writeback_cache"); +    fi + +    if [ -n "$attr_times_granularity" ]; then +        cmd_line=$(echo "$cmd_line --attr-times-granularity=$attr_times_granularity"); +    fi +      if [ -n "$process_name" ]; then          cmd_line=$(echo "$cmd_line --process-name fuse.$process_name");      else @@ -520,6 +528,12 @@ with_options()                  [ $value = "false" ] ; then                  no_root_squash=1;              fi ;; +        "kernel-writeback-cache") +            kernel_writeback_cache=$value +            ;; +        "attr-times-granularity") +            attr_times_granularity=$value +            ;;          "context"|"fscontext"|"defcontext"|"rootcontext")              # standard SElinux mount options to pass to the kernel              [ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts," diff --git a/xlators/storage/posix/src/posix-inode-fd-ops.c b/xlators/storage/posix/src/posix-inode-fd-ops.c index 496f6a7905b..4aa70baf3bd 100644 --- a/xlators/storage/posix/src/posix-inode-fd-ops.c +++ b/xlators/storage/posix/src/posix-inode-fd-ops.c @@ -357,6 +357,23 @@ posix_setattr (call_frame_t *frame, xlator_t *this,                  }          } +        if (valid & GF_SET_ATTR_CTIME) { +                /* +                 * At the moment we have no means to associate an arbitrary +                 * ctime with the file, so we ignore the ctime payload +                 * and update the file ctime to current time (which POSIX +                 * lets us to do). +                 */ +                op_ret = PATH_SET_TIMESPEC_OR_TIMEVAL (real_path, NULL); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_msg (this->name, GF_LOG_ERROR, errno, +                                P_MSG_UTIMES_FAILED, "setattr (utimes) on %s " +                                "failed", real_path); +                        goto out; +                } +        } +          if (!valid) {                  op_ret = sys_lchown (real_path, -1, -1);                  if (op_ret == -1) {  | 
