summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCsaba Henk <csaba@gluster.com>2010-06-01 17:27:18 +0000
committerAnand V. Avati <avati@dev.gluster.com>2010-06-07 10:34:56 -0700
commitc4ebd25a176d6d51d702b1009e261c3c27237a48 (patch)
tree119df05127afee492115694f5cce86d132660bc8
parentd23ae73d0e34010b464454ce81f53f44901ca544 (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.c10
-rw-r--r--glusterfsd/src/glusterfsd.h2
-rw-r--r--libglusterfs/src/glusterfs.h1
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c170
4 files changed, 143 insertions, 40 deletions
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c
index fa4e1a005..cf486d84f 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 ec068ec00..929e27d70 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 181f7f943..f4134d9ea 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 984479b32..74087fc6d 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
},