diff options
| author | Csaba Henk <csaba@gluster.com> | 2010-06-01 17:27:18 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2010-06-07 10:34:56 -0700 | 
| commit | c4ebd25a176d6d51d702b1009e261c3c27237a48 (patch) | |
| tree | 119df05127afee492115694f5cce86d132660bc8 | |
| parent | d23ae73d0e34010b464454ce81f53f44901ca544 (diff) | |
fuse: add a built-in fuse traffic dumper mechanism
It makes fuse dumping possible on platforms where strace is not available (eg. OS X),
moreover it makes reporting of fuse related bugs more convenient.
Signed-off-by: Csaba Henk <csaba@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 972 (Metabug for misc. fuse features)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=972
| -rw-r--r-- | glusterfsd/src/glusterfsd.c | 10 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd.h | 2 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 170 | 
4 files changed, 143 insertions, 40 deletions
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index fa4e1a0054f..cf486d84f7e 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -163,6 +163,8 @@ static struct argp_option gf_options[] = {          {"attribute-timeout", ARGP_ATTRIBUTE_TIMEOUT_KEY, "SECONDS", 0,           "Set attribute timeout to SECONDS for inodes in fuse kernel module "           "[default: 1]"}, +        {"dump-fuse", ARGP_DUMP_FUSE_KEY, "PATH", 0, +         "Dump fuse traffic to PATH"},          {"volfile-check", ARGP_VOLFILE_CHECK_KEY, 0, 0,           "Enable strict volume file checking"},          {0, 0, 0, 0, "Miscellaneous Options:"}, @@ -338,6 +340,10 @@ _add_fuse_mount (xlator_t *graph)                  ret = dict_set_int32 (top->options, ZR_STRICT_VOLFILE_CHECK,                                        cmd_args->volfile_check); +        if (cmd_args->dump_fuse) +                ret = dict_set_static_ptr (top->options, ZR_DUMP_FUSE, +                                           cmd_args->dump_fuse); +  #ifdef GF_DARWIN_HOST_OS          /* On Darwin machines, O_APPEND is not handled,           * which may corrupt the data @@ -1001,6 +1007,10 @@ parse_opts (int key, char *arg, struct argp_state *state)                  cmd_args->mount_point = gf_strdup (arg);                  break; + +        case ARGP_DUMP_FUSE_KEY: +                cmd_args->dump_fuse = gf_strdup (arg); +                break;          }          return 0; diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h index ec068ec00c2..929e27d7037 100644 --- a/glusterfsd/src/glusterfsd.h +++ b/glusterfsd/src/glusterfsd.h @@ -51,6 +51,7 @@  #define ZR_ENTRY_TIMEOUT_OPT    "entry-timeout"  #define ZR_DIRECT_IO_OPT        "direct-io-mode"  #define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check" +#define ZR_DUMP_FUSE            "dump-fuse"  enum argp_option_keys {  	ARGP_VOLFILE_SERVER_KEY = 's',  @@ -79,6 +80,7 @@ enum argp_option_keys {          ARGP_LOG_SERVER_PORT_KEY = 147,          ARGP_READ_ONLY_KEY = 148,          ARGP_MAC_COMPAT_KEY = 149, +        ARGP_DUMP_FUSE_KEY = 150,  };  /* Moved here from fetch-spec.h */ diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 181f7f94376..f4134d9ea25 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -221,6 +221,7 @@ struct _cmd_args {  	char            *volume_name;  	int              fuse_nodev;  	int              fuse_nosuid; +	char            *dump_fuse;  	/* key args */  	char            *mount_point; diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 984479b32f2..74087fc6da4 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -104,7 +104,10 @@ struct fuse_private {          pthread_cond_t       child_up_cond;          pthread_mutex_t      child_up_mutex;          char                 child_up_value; - +        fuse_handler_t     **fuse_ops; +        fuse_handler_t     **fuse_ops0; +        pthread_mutex_t      fuse_dump_mutex; +        int                  fuse_dump_fd;  };  typedef struct fuse_private fuse_private_t; @@ -297,6 +300,22 @@ send_fuse_iov (xlator_t *this, fuse_in_header_t *finh, struct iovec *iov_out,                  return errno;          if (res != fouh->len)                  return EINVAL; + +        if (priv->fuse_dump_fd != -1) { +                char w = 'W'; + +                pthread_mutex_lock (&priv->fuse_dump_mutex); +                res = write (priv->fuse_dump_fd, &w, 1); +                if (res != -1) +                        res = writev (priv->fuse_dump_fd, iov_out, count); +                pthread_mutex_unlock (&priv->fuse_dump_mutex); + +                if (res == -1) +                        gf_log ("glusterfs-fuse", GF_LOG_ERROR, +                                "failed to dump fuse message (W): %s", +                                strerror (errno)); +        } +          return 0;  } @@ -2994,7 +3013,6 @@ fuse_destroy (xlator_t *this, fuse_in_header_t *finh, void *msg)          GF_FREE (finh);  } -static fuse_handler_t *fuse_ops[FUSE_OP_HIGH];  int  fuse_first_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -3079,6 +3097,7 @@ fuse_thread_proc (void *data)          struct iovec iov_in[2];          void *msg = NULL;          const size_t msg0_size = sizeof (*finh) + 128; +        fuse_handler_t **fuse_ops = NULL;          int             ret  = -1;          struct timeval  now; @@ -3086,6 +3105,7 @@ fuse_thread_proc (void *data)          this = data;          priv = this->private; +        fuse_ops = priv->fuse_ops;          THIS = this; @@ -3387,6 +3407,78 @@ mem_acct_init (xlator_t *this)          return ret;  } + +static fuse_handler_t *fuse_std_ops[FUSE_OP_HIGH] = { +        [FUSE_INIT]        = fuse_init, +        [FUSE_DESTROY]     = fuse_destroy, +        [FUSE_LOOKUP]      = fuse_lookup, +        [FUSE_FORGET]      = fuse_forget, +        [FUSE_GETATTR]     = fuse_getattr, +        [FUSE_SETATTR]     = fuse_setattr, +        [FUSE_OPENDIR]     = fuse_opendir, +        [FUSE_READDIR]     = fuse_readdir, +        [FUSE_RELEASEDIR]  = fuse_releasedir, +        [FUSE_ACCESS]      = fuse_access, +        [FUSE_READLINK]    = fuse_readlink, +        [FUSE_MKNOD]       = fuse_mknod, +        [FUSE_MKDIR]       = fuse_mkdir, +        [FUSE_UNLINK]      = fuse_unlink, +        [FUSE_RMDIR]       = fuse_rmdir, +        [FUSE_SYMLINK]     = fuse_symlink, +        [FUSE_RENAME]      = fuse_rename, +        [FUSE_LINK]        = fuse_link, +        [FUSE_CREATE]      = fuse_create, +        [FUSE_OPEN]        = fuse_open, +        [FUSE_READ]        = fuse_readv, +        [FUSE_WRITE]       = fuse_write, +        [FUSE_FLUSH]       = fuse_flush, +        [FUSE_RELEASE]     = fuse_release, +        [FUSE_FSYNC]       = fuse_fsync, +        [FUSE_FSYNCDIR]    = fuse_fsyncdir, +        [FUSE_STATFS]      = fuse_statfs, +        [FUSE_SETXATTR]    = fuse_setxattr, +        [FUSE_GETXATTR]    = fuse_getxattr, +        [FUSE_LISTXATTR]   = fuse_listxattr, +        [FUSE_REMOVEXATTR] = fuse_removexattr, +        [FUSE_GETLK]       = fuse_getlk, +        [FUSE_SETLK]       = fuse_setlk, +        [FUSE_SETLKW]      = fuse_setlk, +}; + + +static fuse_handler_t *fuse_dump_ops[FUSE_OP_HIGH] = { +}; + + +static void +fuse_dumper (xlator_t *this, fuse_in_header_t *finh, void *msg) +{ +        fuse_private_t *priv = NULL; +        struct iovec diov[3]; +        char r = 'R'; +        int ret = 0; + +        priv = this->private; + +        diov[0].iov_base = &r; +        diov[0].iov_len  = 1; +        diov[1].iov_base = finh; +        diov[1].iov_len  = sizeof (*finh); +        diov[2].iov_base = msg; +        diov[2].iov_len  = finh->len - sizeof (*finh); + +        pthread_mutex_lock (&priv->fuse_dump_mutex); +        ret = writev (priv->fuse_dump_fd, diov, 3); +        pthread_mutex_unlock (&priv->fuse_dump_mutex); +        if (ret == -1) +                gf_log ("glusterfs-fuse", GF_LOG_ERROR, +                        "failed to dump fuse message (R): %s", +                        strerror (errno)); + +        return priv->fuse_ops0[finh->opcode] (this, finh, msg); +} + +  int  init (xlator_t *this_xl)  { @@ -3483,17 +3575,34 @@ init (xlator_t *this_xl)          priv->direct_io_mode = 2;          ret = dict_get_str (options, ZR_DIRECT_IO_OPT, &value_string); -        if (value_string) { +        if (ret == 0) {                  ret = gf_string2boolean (value_string, &priv->direct_io_mode);          }          priv->strict_volfile_check = 0;          ret = dict_get_str (options, ZR_STRICT_VOLFILE_CHECK, &value_string); -        if (value_string) { +        if (ret == 0) {                  ret = gf_string2boolean (value_string,                                           &priv->strict_volfile_check);          } +        priv->fuse_dump_fd = -1; +        ret = dict_get_str (options, "dump-fuse", &value_string); +        if (ret == 0) { +                ret = unlink (value_string); +                if (ret != -1 || errno == ENOENT) +                        ret = open (value_string, O_RDWR|O_CREAT|O_EXCL, +                                    S_IRUSR|S_IWUSR); +                if (ret == -1) { +                        gf_log ("glusterfs-fuse", GF_LOG_ERROR, +                                "cannot open fuse dump file %s", +                                 value_string); + +                        goto cleanup_exit; +                } +                priv->fuse_dump_fd = ret; +        } +          fsname = this_xl->ctx->cmd_args.volume_file;          fsname = (fsname ? fsname : this_xl->ctx->cmd_args.volfile_server);          fsname = (fsname ? fsname : "glusterfs"); @@ -3516,46 +3625,22 @@ init (xlator_t *this_xl)          priv->first_call = 2; +        pthread_mutex_init (&priv->fuse_dump_mutex, NULL);          pthread_cond_init (&priv->child_up_cond, NULL);          pthread_mutex_init (&priv->child_up_mutex, NULL);          priv->child_up_value = 1; -        for (i = 0; i < FUSE_OP_HIGH; i++) -                fuse_ops[i] = fuse_enosys; -        fuse_ops[FUSE_INIT]        = fuse_init; -        fuse_ops[FUSE_DESTROY]     = fuse_destroy; -        fuse_ops[FUSE_LOOKUP]      = fuse_lookup; -        fuse_ops[FUSE_FORGET]      = fuse_forget; -        fuse_ops[FUSE_GETATTR]     = fuse_getattr; -        fuse_ops[FUSE_SETATTR]     = fuse_setattr; -        fuse_ops[FUSE_OPENDIR]     = fuse_opendir; -        fuse_ops[FUSE_READDIR]     = fuse_readdir; -        fuse_ops[FUSE_RELEASEDIR]  = fuse_releasedir; -        fuse_ops[FUSE_ACCESS]      = fuse_access; -        fuse_ops[FUSE_READLINK]    = fuse_readlink; -        fuse_ops[FUSE_MKNOD]       = fuse_mknod; -        fuse_ops[FUSE_MKDIR]       = fuse_mkdir; -        fuse_ops[FUSE_UNLINK]      = fuse_unlink; -        fuse_ops[FUSE_RMDIR]       = fuse_rmdir; -        fuse_ops[FUSE_SYMLINK]     = fuse_symlink; -        fuse_ops[FUSE_RENAME]      = fuse_rename; -        fuse_ops[FUSE_LINK]        = fuse_link; -        fuse_ops[FUSE_CREATE]      = fuse_create; -        fuse_ops[FUSE_OPEN]        = fuse_open; -        fuse_ops[FUSE_READ]        = fuse_readv; -        fuse_ops[FUSE_WRITE]       = fuse_write; -        fuse_ops[FUSE_FLUSH]       = fuse_flush; -        fuse_ops[FUSE_RELEASE]     = fuse_release; -        fuse_ops[FUSE_FSYNC]       = fuse_fsync; -        fuse_ops[FUSE_FSYNCDIR]    = fuse_fsyncdir; -        fuse_ops[FUSE_STATFS]      = fuse_statfs; -        fuse_ops[FUSE_SETXATTR]    = fuse_setxattr; -        fuse_ops[FUSE_GETXATTR]    = fuse_getxattr; -        fuse_ops[FUSE_LISTXATTR]   = fuse_listxattr; -        fuse_ops[FUSE_REMOVEXATTR] = fuse_removexattr; -        fuse_ops[FUSE_GETLK]       = fuse_getlk; -        fuse_ops[FUSE_SETLK]       = fuse_setlk; -        fuse_ops[FUSE_SETLKW]      = fuse_setlk; +        for (i = 0; i < FUSE_OP_HIGH; i++) { +                if (!fuse_std_ops[i]) +                        fuse_std_ops[i] = fuse_enosys; +                if (!fuse_dump_ops[i]) +                        fuse_dump_ops[i] = fuse_dumper; +        } +        priv->fuse_ops = fuse_std_ops; +        if (priv->fuse_dump_fd != -1) { +                priv->fuse_ops0 = priv->fuse_ops; +                priv->fuse_ops  = fuse_dump_ops; +        }          return 0; @@ -3567,6 +3652,7 @@ cleanup_exit:                  close (priv->fd);          }          GF_FREE (priv); +        close (priv->fuse_dump_fd);          return -1;  } @@ -3592,6 +3678,7 @@ fini (xlator_t *this_xl)                  dict_del (this_xl->options, ZR_MOUNTPOINT_OPT);                  gf_fuse_unmount (mount_point, priv->fd); +                close (priv->fuse_dump_fd);          }  } @@ -3614,6 +3701,9 @@ struct volume_options options[] = {          { .key  = {"mountpoint", "mount-point"},            .type = GF_OPTION_TYPE_PATH          }, +        { .key  = {"dump-fuse", "fuse-dumpfile"}, +          .type = GF_OPTION_TYPE_PATH +        },          { .key  = {"attribute-timeout"},            .type = GF_OPTION_TYPE_DOUBLE          },  | 
