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 }, |