diff options
-rw-r--r-- | glusterfsd/src/glusterfsd.c | 6 | ||||
-rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 335 | ||||
-rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 4 |
3 files changed, 11 insertions, 334 deletions
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index 31fbaa9692b..bce5bfd4ca5 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -896,10 +896,14 @@ glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx) cmd_args->log_level = DEFAULT_LOG_LEVEL; #ifdef GF_DARWIN_HOST_OS cmd_args->mac_compat = GF_OPTION_DEFERRED; + /* On Darwin machines, O_APPEND is not handled, + * which may corrupt the data + */ + cmd_args->fuse_direct_io_mode = GF_OPTION_DISABLE; #else cmd_args->mac_compat = GF_OPTION_DISABLE; -#endif cmd_args->fuse_direct_io_mode = GF_OPTION_DEFERRED; +#endif cmd_args->fuse_attribute_timeout = -1; INIT_LIST_HEAD (&cmd_args->xlator_options); diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index e37d2e0c8da..aea0f88b0c1 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -29,7 +29,6 @@ static int gf_fuse_conn_err_log; static int gf_fuse_xattr_enotsup_log; -static int gf_fuse_pre_stuck_log; /* @@ -537,18 +536,7 @@ fuse_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this, foo.open_flags = 0; if (!IA_ISDIR (fd->inode->ia_type)) { - if (priv->direct_io_mode && - ( -#ifdef GF_LINUX_HOST_OS - (state->flags & O_ACCMODE) != O_RDONLY || -#endif -#ifdef GF_DARWIN_HOST_OS - /* On Darwin machines, O_APPEND is not handled, - * which may corrupt the data - */ - (state->flags & O_ACCMODE) == O_RDONLY && -#endif - priv->can_exec_directio)) + if (priv->direct_io_mode) foo.open_flags |= FOPEN_DIRECT_IO; #ifdef GF_DARWIN_HOST_OS /* In Linux: by default, buffer cache @@ -1442,15 +1430,7 @@ fuse_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret >= 0) { foo.fh = (uintptr_t) fd; - if (priv->direct_io_mode && - ( -#ifdef GF_LINUX_HOST_OS - (state->flags & O_ACCMODE) != O_RDONLY || -#endif -#ifdef GF_DARWIN_HOST_OS - (state->flags & O_ACCMODE) == O_RDONLY && -#endif - priv->can_exec_directio)) + if (priv->direct_io_mode) foo.open_flags |= FOPEN_DIRECT_IO; gf_log ("glusterfs-fuse", GF_LOG_TRACE, @@ -2818,9 +2798,6 @@ fuse_setlk (xlator_t *this, fuse_in_header_t *finh, void *msg) return; } - -static void *fuse_pre_test_directio_exec (void *arg); - static void fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg) { @@ -2829,9 +2806,6 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg) struct fuse_init_out fino; fuse_private_t *priv = NULL; int ret; -#ifndef GF_DARWIN_HOST_OS - pthread_t prethread = {0, }; -#endif priv = this->private; @@ -2893,20 +2867,6 @@ fuse_init (xlator_t *this, fuse_in_header_t *finh, void *msg) out: GF_FREE (finh); - -#ifdef GF_DARWIN_HOST_OS - /* MacFUSE applies a "mount comes after a succesful handshake" - * strategy, which was taken from early fuse4bsd. Linux (and recent - * fuse4bsd) is rather doing "mount, then handshake; if that fails, - * unmount" strategy. Therefore on OS X it would be too early to - * launch the pre-test thread here. To work this around, we launch - * it from the LOOKUP pre-test handler (that will come instantly, - * as OS X automatically checks for the presence of some files - * upon a new mount). - */ -#else - pthread_create (&prethread, NULL, &fuse_pre_test_directio_exec, this); -#endif } @@ -3075,9 +3035,11 @@ 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; this = data; priv = this->private; + fuse_ops = priv->fuse_ops; THIS = this; @@ -3192,7 +3154,7 @@ fuse_thread_proc (void *data) fuse_enosys (this, finh, msg); else #endif - priv->fuse_ops[finh->opcode] (this, finh, msg); + fuse_ops[finh->opcode] (this, finh, msg); iobuf_unref (iobuf); continue; @@ -3457,287 +3419,6 @@ fuse_dumper (xlator_t *this, fuse_in_header_t *finh, void *msg) } -/* - * FUSE pre-test stuff - * ------------------- - */ - -#define FUSE_PRE_TESTFILE ".__fuse_pre_testfile" -#define FUSE_PRE_TESTFILE1 ".__fuse_pre_testfile1" -#define FUSE_PRE_TESTFILE_ID ((uint64_t)-1) -#define FUSE_PRE_TESTFILE_FH ((uint64_t)1) - -#define FUSE_PRE_TEST_TEST do { \ - if (finh->uid != getuid () || \ - finh->nodeid != FUSE_PRE_TESTFILE_ID) \ - return fuse_std_fallback (this, finh, msg); \ -} while (0) - -static fuse_handler_t *fuse_std_ops[]; - -static void -fuse_std_fallback (xlator_t *this, fuse_in_header_t *finh, void *msg) -{ - static int fuse_pre_cnt; - - if (fuse_pre_cnt++ > 200) - GF_LOG_OCCASIONALLY (gf_fuse_pre_stuck_log, - "glusterfs-fuse", - GF_LOG_WARNING, - "fuse pre test does not complete"); - - return fuse_std_ops[finh->opcode] (this, finh, msg); -} - - -static void -fuse_pre_lookup (xlator_t *this, fuse_in_header_t *finh, void *msg) -{ - char *name = msg; - fuse_private_t *priv = NULL; - struct fuse_entry_out feo = {0, }; - unsigned pre_testfile[2] = {0, 0}; -#ifdef GF_DARWIN_HOST_OS - static int prethread_spawn; - pthread_t prethread = {0, }; - - if (!prethread_spawn) { - prethread_spawn = 1; - pthread_create (&prethread, NULL, &fuse_pre_test_directio_exec, - this); - } -#endif - - priv = this->private; - - pre_testfile[0] = !strcmp (name, FUSE_PRE_TESTFILE); - pre_testfile[1] = !strcmp (name, FUSE_PRE_TESTFILE1); - if (finh->uid != getuid () || - finh->nodeid != 1 || - !(pre_testfile[0] || pre_testfile[1])) - return fuse_std_fallback (this, finh, msg); - - if (priv->pre_test_stage == 0 && pre_testfile[1]) { - send_fuse_err (this, finh, ENOENT); - - return; - } - - memset (&feo, 0, sizeof (feo)); - feo.nodeid = FUSE_PRE_TESTFILE_ID; - feo.attr.ino = FUSE_PRE_TESTFILE_ID; - feo.attr.mode = (priv->pre_test_stage == 2 ? S_IFDIR : S_IFREG) | 0755; - feo.attr.nlink = 1; - -#if FUSE_KERNEL_MINOR_VERSION >= 9 - priv->proto_minor >= 9 ? - send_fuse_obj (this, finh, &feo) : - send_fuse_data (this, finh, &feo, - FUSE_COMPAT_ENTRY_OUT_SIZE); -#else - send_fuse_obj (this, finh, &feo); -#endif -} - - -static void -fuse_pre_getattr (xlator_t *this, fuse_in_header_t *finh, void *msg) -{ - fuse_private_t *priv = NULL; - struct fuse_attr_out fao = {0, }; - - priv = this->private; - - FUSE_PRE_TEST_TEST; - - fao.attr.mode = (priv->pre_test_stage == 2 ? S_IFDIR : S_IFREG) | 0755; - fao.attr.nlink = 1; - -#if FUSE_KERNEL_MINOR_VERSION >= 9 - priv->proto_minor >= 9 ? - send_fuse_obj (this, finh, &fao) : - send_fuse_data (this, finh, &fao, - FUSE_COMPAT_ATTR_OUT_SIZE); -#else - send_fuse_obj (this, finh, &fao); -#endif -} - - -static void -fuse_pre_open (xlator_t *this, fuse_in_header_t *finh, void *msg) -{ - struct fuse_open_out foo = {0, }; - - FUSE_PRE_TEST_TEST; - - foo.fh = FUSE_PRE_TESTFILE_FH; - foo.open_flags = FOPEN_DIRECT_IO; - - send_fuse_obj (this, finh, &foo); -} - - -static void -fuse_pre_deadpan (xlator_t *this, fuse_in_header_t *finh, void *msg) -{ - FUSE_PRE_TEST_TEST; - - send_fuse_err (this, finh, 0); -} - - -static void -fuse_pre_rename (xlator_t *this, fuse_in_header_t *finh, void *msg) -{ - struct fuse_rename_in *fri = msg; - char *oldname = (char *)(fri + 1); - char *newname = oldname + strlen (oldname) + 1; - - fuse_private_t *priv = NULL; - - if (finh->uid != getuid () || - finh->nodeid != 1 || - fri->newdir != 1 || - strcmp (oldname, FUSE_PRE_TESTFILE) != 0 || - strcmp (newname, FUSE_PRE_TESTFILE1) != 0) - return fuse_std_fallback (this, finh, msg); - - priv = this->private; - priv->pre_test_stage = 1; - - send_fuse_err (this, finh, 0); -} - - -static void -fuse_pre_release (xlator_t *this, fuse_in_header_t *finh, void *msg) -{ - if (finh->nodeid != FUSE_PRE_TESTFILE_ID) - return fuse_std_fallback (this, finh, msg); - - send_fuse_err (this, finh, 0); -} - - -static void -fuse_pre_forget (xlator_t *this, fuse_in_header_t *finh, void *msg) -{ - fuse_private_t *priv = NULL; - - if (finh->nodeid != FUSE_PRE_TESTFILE_ID) - return fuse_std_fallback (this, finh, msg); - - gf_log ("glusterfs-fuse", GF_LOG_DEBUG, - "terminating pre-test, switching to standard ops"); - priv = this->private; - *(priv->fuse_ops_flipped) = fuse_std_ops; -} - - -/* XXX Hope this will work out with xattr based ACL systems... */ -static void -fuse_pre_xattr (xlator_t *this, fuse_in_header_t *finh, void *msg) -{ - FUSE_PRE_TEST_TEST; - - send_fuse_err (this, finh, ENODATA); -} - - -static fuse_handler_t *fuse_pre_ops[FUSE_OP_HIGH] = { - [FUSE_LOOKUP] = fuse_pre_lookup, - [FUSE_FORGET] = fuse_pre_forget, - [FUSE_GETATTR] = fuse_pre_getattr, - [FUSE_ACCESS] = fuse_pre_deadpan, - [FUSE_RENAME] = fuse_pre_rename, - [FUSE_OPEN] = fuse_pre_open, - [FUSE_READ] = fuse_pre_deadpan, - [FUSE_FLUSH] = fuse_pre_deadpan, - [FUSE_RELEASE] = fuse_pre_release, - [FUSE_FSYNC] = fuse_pre_deadpan, - [FUSE_GETXATTR] = fuse_pre_xattr, - [FUSE_LISTXATTR] = fuse_pre_xattr, -}; - - -enum { - FUSE_DIOEXEC_OK, - FUSE_DIOEXEC_FAIL, - FUSE_DIOEXEC_DUNNO -}; - -static void * -fuse_pre_test_directio_exec (void *arg) -{ - fuse_private_t *priv = NULL; - pid_t pid = 0; - struct stat st = {0, }; - char pre_testfile[PATH_MAX]; - char pre_testfile1[PATH_MAX]; - int ret = 0; - xlator_t *this = NULL; - - this = arg; - priv = this->private; - - if (fstat (priv->fd, &st) == -1) - return NULL; - if (strlen (priv->mount_point) + - max (strlen (FUSE_PRE_TESTFILE), strlen (FUSE_PRE_TESTFILE1)) + 2 > - PATH_MAX) - return NULL; - strcat (strcat (strcpy (pre_testfile, priv->mount_point), "/"), - FUSE_PRE_TESTFILE); - strcat (strcat (strcpy (pre_testfile1, priv->mount_point), "/"), - FUSE_PRE_TESTFILE1); - - if ((pid = fork ()) == -1) - return NULL; - if (pid == 0) { - close (priv->fd); - execl (pre_testfile, FUSE_PRE_TESTFILE, NULL); - switch (errno) { - case ENOEXEC: - exit (FUSE_DIOEXEC_OK); - case EFAULT: - exit (FUSE_DIOEXEC_FAIL); - default: - fprintf (stderr, - "warning: fuse exec-on-diretio pre-test ended" - " unexpectedly (%s)\n", strerror (errno)); - exit (FUSE_DIOEXEC_DUNNO); - } - } - - if (waitpid (pid, &ret, 0) == pid && - WIFEXITED (ret)) { - switch (WEXITSTATUS (ret)) { - case FUSE_DIOEXEC_OK: - gf_log ("glusterfs-fuse", GF_LOG_DEBUG, - "exec on directio: OK"); - priv->can_exec_directio = 1; - break; - case FUSE_DIOEXEC_FAIL: - gf_log ("glusterfs-fuse", GF_LOG_DEBUG, - "exec on directio: FAIL"); - break; - default: - gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "exec on directio: uninterpretable result"); - } - } else - gf_log ("glusterfs-fuse", GF_LOG_WARNING, - "exec on directio: abnormal termination"); - - ret = rename (pre_testfile, pre_testfile1); - priv->pre_test_stage = 2; - stat (ret ? pre_testfile : pre_testfile1, &st); - - pthread_exit (0); -} - - int init (xlator_t *this_xl) { @@ -3906,15 +3587,11 @@ init (xlator_t *this_xl) fuse_std_ops[i] = fuse_enosys; if (!fuse_dump_ops[i]) fuse_dump_ops[i] = fuse_dumper; - if (!fuse_pre_ops[i]) - fuse_pre_ops[i] = fuse_std_fallback; } - priv->fuse_ops = fuse_pre_ops; - priv->fuse_ops_flipped = &priv->fuse_ops; + priv->fuse_ops = fuse_std_ops; if (priv->fuse_dump_fd != -1) { priv->fuse_ops0 = priv->fuse_ops; priv->fuse_ops = fuse_dump_ops; - priv->fuse_ops_flipped = &priv->fuse_ops0; } return 0; diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index 4929252e169..547cc895268 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -27,7 +27,6 @@ #include <dirent.h> #include <sys/mount.h> #include <sys/time.h> -#include <sys/wait.h> #include <fnmatch.h> #ifndef _CONFIG_H @@ -86,7 +85,6 @@ struct fuse_private { char fuse_thread_started; uint32_t direct_io_mode; - char can_exec_directio; size_t *msg0_len_p; double entry_timeout; @@ -102,10 +100,8 @@ struct fuse_private { fuse_handler_t **fuse_ops; fuse_handler_t **fuse_ops0; - fuse_handler_t ***fuse_ops_flipped; pthread_mutex_t fuse_dump_mutex; int fuse_dump_fd; - char pre_test_stage; glusterfs_graph_t *next_graph; xlator_t *active_subvol; |