diff options
-rw-r--r-- | contrib/fuse-lib/mount.c | 312 | ||||
-rw-r--r-- | contrib/fuse-util/fusermount.c | 60 | ||||
-rw-r--r-- | glusterfsd/src/glusterfsd.c | 10 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs.h | 2 | ||||
-rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 28 | ||||
-rwxr-xr-x | xlators/mount/fuse/utils/mount.glusterfs.in | 55 |
6 files changed, 182 insertions, 285 deletions
diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c index 8c5da3d619f..bbc05f28683 100644 --- a/contrib/fuse-lib/mount.c +++ b/contrib/fuse-lib/mount.c @@ -26,7 +26,6 @@ #endif /* __NetBSD__ */ #include <sys/stat.h> #include <sys/poll.h> -#include <sys/socket.h> #include <sys/un.h> #include <sys/wait.h> #include <sys/mount.h> @@ -56,7 +55,7 @@ #else #define FUSERMOUNT_PROG "fusermount" #endif -#define FUSE_COMMFD_ENV "_FUSE_COMMFD" +#define FUSE_DEVFD_ENV "_FUSE_DEVFD" #define GFFUSE_LOGERR(...) \ gf_log ("glusterfs-fuse", GF_LOG_ERROR, ## __VA_ARGS__) @@ -115,8 +114,7 @@ static #endif int fuse_mnt_add_mount (const char *progname, const char *fsname, - const char *mnt, const char *type, const char *opts, - pid_t *mtab_pid) + const char *mnt, const char *type, const char *opts) { int res; int status; @@ -144,24 +142,6 @@ fuse_mnt_add_mount (const char *progname, const char *fsname, char templ[] = "/tmp/fusermountXXXXXX"; char *tmp; - if (!mtab_pid) { - /* mtab update done async, just log if fails */ - res = fork (); - if (res) - exit (res == -1 ? 1 : 0); - res = fork (); - if (res) { - if (res != -1) { - if (!(res == waitpid (res, &status, 0) - && status == 0)) - GFFUSE_LOGERR ("%s: /etc/mtab " - "update failed", - progname); - } - exit (0); - } - } - sigprocmask (SIG_SETMASK, &oldmask, NULL); setuid (geteuid ()); @@ -187,15 +167,11 @@ fuse_mnt_add_mount (const char *progname, const char *fsname, progname, _PATH_MOUNT, strerror (errno)); exit (1); } - if (mtab_pid) { - *mtab_pid = res; - res = 0; - } else { - if (!(res == waitpid (res, &status, 0) && status == 0)) - res = -1; - } + + res = waitpid (res, &status, 0); if (res == -1) GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno)); + res = (res != -1 && status == 0) ? 0 : -1; out_restore: sigprocmask (SIG_SETMASK, &oldmask, NULL); @@ -273,76 +249,75 @@ char } #ifndef FUSE_UTIL -/* return value: - * >= 0 => fd - * -1 => error - */ -static int -receive_fd (int fd) +static char * +escape (char *s) { - struct msghdr msg; - struct iovec iov; - char buf[1]; - int rv; - size_t ccmsg[CMSG_SPACE (sizeof (int)) / sizeof (size_t)]; - struct cmsghdr *cmsg; - int *recv_fd; - - iov.iov_base = buf; - iov.iov_len = 1; - - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - /* old BSD implementations should use msg_accrights instead of - * msg_control; the interface is different. */ - msg.msg_control = ccmsg; - msg.msg_controllen = sizeof (ccmsg); - - while (((rv = recvmsg (fd, &msg, 0)) == -1) && errno == EINTR); - if (rv == -1) { - GFFUSE_LOGERR ("recvmsg failed: %s", strerror (errno)); - return -1; - } - if (!rv) { - /* EOF */ - return -1; + size_t len = 0; + char *p = NULL; + char *q = NULL; + char *e = NULL; + + for (p = s; *p; p++) { + if (*p == ',') + len++; + len++; } - cmsg = CMSG_FIRSTHDR (&msg); - /* - * simplify condition expression - */ - if (cmsg->cmsg_type != SCM_RIGHTS) { - GFFUSE_LOGERR ("got control message of unknown type %d", - cmsg->cmsg_type); - return -1; + e = CALLOC (1, len + 1); + if (!e) + return NULL; + + for (p = s, q = e; *p; p++, q++) { + if (*p == ',') { + *q = '\\'; + q++; + } + *q = *p; } - recv_fd = (int *) CMSG_DATA (cmsg); - return (*recv_fd); + return e; } static int -fuse_mount_fusermount (const char *mountpoint, const char *opts) +fuse_mount_fusermount (const char *mountpoint, char *fsname, char *mnt_param, + int fd) { - int fds[2], pid; - int res; - int rv; + int pid = -1; + int res = 0; + int ret = -1; + char *fm_mnt_params = NULL; + char *efsname = NULL; + +#ifndef GF_FUSERMOUNT + GFFUSE_LOGERR ("Mounting via helper utility " + "(unprivileged mounting) is supported " + "only if glusterfs is compiled with " + "--enable-fusermount"); + return -1; +#endif + + efsname = escape (fsname); + if (!efsname) { + GFFUSE_LOGERR ("Out of memory"); - res = socketpair (PF_UNIX, SOCK_STREAM, 0, fds); - if (res == -1) { - GFFUSE_LOGERR ("socketpair() failed: %s", strerror (errno)); return -1; } + ret = asprintf (&fm_mnt_params, + "%s,fsname=%s,nonempty,subtype=glusterfs", + mnt_param, efsname); + FREE (efsname); + if (ret == -1) { + GFFUSE_LOGERR ("Out of memory"); + + goto out; + } + /* fork to exec fusermount */ pid = fork (); if (pid == -1) { GFFUSE_LOGERR ("fork() failed: %s", strerror (errno)); - close (fds[0]); - close (fds[1]); - return -1; + ret = -1; + goto out; } if (pid == 0) { @@ -351,30 +326,25 @@ fuse_mount_fusermount (const char *mountpoint, const char *opts) int a = 0; argv[a++] = FUSERMOUNT_PROG; - if (opts) { - argv[a++] = "-o"; - argv[a++] = opts; - } + argv[a++] = "-o"; + argv[a++] = fm_mnt_params; argv[a++] = "--"; argv[a++] = mountpoint; argv[a++] = NULL; - close (fds[1]); - fcntl (fds[0], F_SETFD, 0); - snprintf (env, sizeof (env), "%i", fds[0]); - setenv (FUSE_COMMFD_ENV, env, 1); + snprintf (env, sizeof (env), "%i", fd); + setenv (FUSE_DEVFD_ENV, env, 1); execvp (FUSERMOUNT_PROG, (char **)argv); GFFUSE_LOGERR ("failed to exec fusermount: %s", strerror (errno)); _exit (1); } - close (fds[0]); - rv = receive_fd (fds[1]); - close (fds[1]); - waitpid (pid, NULL, 0); /* bury zombie */ - - return rv; + ret = waitpid (pid, &res, 0); + ret = (ret == pid && res == 0) ? 0 : -1; + out: + FREE (fm_mnt_params); + return ret; } #endif @@ -544,26 +514,13 @@ gf_fuse_unmount (const char *mountpoint, int fd) #ifndef FUSE_UTIL static int -fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param, pid_t *mtab_pid, int in_fd, int status_fd) +fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param, int fd) { - int fd = -1, ret = -1; + int ret = -1; unsigned mounted = 0; char *mnt_param_mnt = NULL; char *fstype = "fuse.glusterfs"; char *source = fsname; - pid_t mypid = -1; - - if (in_fd >= 0) { - fd = in_fd; - } - else { - fd = open ("/dev/fuse", O_RDWR); - if (fd == -1) { - GFFUSE_LOGERR ("cannot open /dev/fuse (%s)", - strerror (errno)); - return -1; - } - } ret = asprintf (&mnt_param_mnt, "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i", @@ -573,14 +530,8 @@ fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param, pid_t *mt goto out; } - ret = fork(); - if (ret != 0) { - goto parent_out; - } - GFFUSE_LOGERR("calling mount"); ret = mount (source, mountpoint, fstype, 0, mnt_param_mnt); - GFFUSE_LOGERR("mount returned %d",ret); if (ret == -1 && errno == ENODEV) { /* fs subtype support was added by 79c0b2df aka v2.6.21-3159-g79c0b2d. Probably we have an @@ -610,7 +561,7 @@ fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param, pid_t *mt } ret = fuse_mnt_add_mount ("fuse", source, newmnt, fstype, - mnt_param, mtab_pid); + mnt_param); FREE (newmnt); if (ret == -1) { GFFUSE_LOGERR ("failed to add mtab entry"); @@ -619,75 +570,25 @@ fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param, pid_t *mt } } - ret = 0; out: - if (status_fd >= 0) { - GFFUSE_LOGERR("writing status"); - (void)write(status_fd,&ret,sizeof(ret)); - mypid = getpid(); - /* - * This seems awkward, but the alternative would be to add - * or change return values for functions in multiple layers, - * just so they can store the value for later retrieval by - * the code already running in the right context at the other - * end of this pipe. That's a lot of disruption for nothing. - */ - (void)write(status_fd,&mypid,sizeof(mypid)); - } - GFFUSE_LOGERR("Mount child exiting"); - exit(0); - -parent_out: if (ret == -1) { if (mounted) umount2 (mountpoint, 2); /* lazy umount */ - if (fd != in_fd) { - close (fd); - } - fd = -1; } FREE (mnt_param_mnt); if (source != fsname) FREE (source); - return fd; -} - -static char * -escape (char *s) -{ - size_t len = 0; - char *p = NULL; - char *q = NULL; - char *e = NULL; - for (p = s; *p; p++) { - if (*p == ',') - len++; - len++; - } - - e = CALLOC (1, len + 1); - if (!e) - return NULL; - - for (p = s, q = e; *p; p++, q++) { - if (*p == ',') { - *q = '\\'; - q++; - } - *q = *p; - } - - return e; + return ret; } int gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param, - pid_t *mtab_pid, int status_fd) + pid_t *mnt_pid, int status_fd) { - int fd = -1, rv = -1; - char *fm_mnt_params = NULL, *p = NULL; - char *efsname = NULL; + int fd = -1; + pid_t pid = -1; + int ret = -1; fd = open ("/dev/fuse", O_RDWR); if (fd == -1) { @@ -696,45 +597,46 @@ gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param, return -1; } - fd = fuse_mount_sys (mountpoint, fsname, mnt_param, mtab_pid, fd, - status_fd); - if (fd == -1) { - gf_log ("glusterfs-fuse", GF_LOG_INFO, - "direct mount failed (%s), " - "retry to mount via fusermount", - strerror (errno)); - - efsname = escape (fsname); - if (!efsname) { - GFFUSE_LOGERR ("Out of memory"); - - return -1; + /* start mount agent */ + pid = fork(); + switch (pid) { + case 0: + /* hello it's mount agent */ + if (!mnt_pid) { + /* daemonize mount agent, caller is + * not interested in waiting for it + */ + pid = fork (); + if (pid) + exit (pid == -1 ? 1 : 0); } - rv = asprintf (&fm_mnt_params, - "%s,fsname=%s,nonempty,subtype=glusterfs", - mnt_param, efsname); - FREE (efsname); - if (rv == -1) { - GFFUSE_LOGERR ("Out of memory"); - return -1; - } - - fd = fuse_mount_fusermount (mountpoint, fm_mnt_params); - if (fd == -1) { - p = fm_mnt_params + strlen (fm_mnt_params); - while (*--p != ','); - *p = '\0'; + ret = fuse_mount_sys (mountpoint, fsname, mnt_param, fd); + if (ret == -1) { + gf_log ("glusterfs-fuse", GF_LOG_INFO, + "direct mount failed (%s), " + "retry to mount via fusermount", + strerror (errno)); - fd = fuse_mount_fusermount (mountpoint, fm_mnt_params); + ret = fuse_mount_fusermount (mountpoint, fsname, + mnt_param, fd); } - FREE (fm_mnt_params); + if (ret == -1) + GFFUSE_LOGERR ("mount failed"); - if (fd == -1) - GFFUSE_LOGERR ("mount failed"); + if (status_fd >= 0) + (void)write (status_fd, &ret, sizeof (ret)); + exit (!!ret); + /* bye mount agent */ + case -1: + close (fd); + fd = -1; } + if (mnt_pid) + *mnt_pid = pid; + return fd; } #endif diff --git a/contrib/fuse-util/fusermount.c b/contrib/fuse-util/fusermount.c index 39da9b6a0b6..4e7e4f9501c 100644 --- a/contrib/fuse-util/fusermount.c +++ b/contrib/fuse-util/fusermount.c @@ -19,6 +19,7 @@ #include <errno.h> #include <fcntl.h> #include <pwd.h> +#include <limits.h> #include <mntent.h> #include <sys/wait.h> #include <sys/stat.h> @@ -28,6 +29,7 @@ #include <sys/utsname.h> #include <sched.h> +#define FUSE_DEVFD_ENV "_FUSE_DEVFD" #define FUSE_COMMFD_ENV "_FUSE_COMMFD" #define FUSE_DEV_OLD "/proc/fs/fuse/dev" @@ -1016,8 +1018,36 @@ static int open_fuse_device(char **devp) return -1; } +static int check_fuse_device(char *devfd, char **devp) +{ + int res; + char *devlink; + + res = asprintf(&devlink, "/proc/self/fd/%s", devfd); + if (res == -1) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + return -1; + } + + *devp = (char *) calloc(1, PATH_MAX + 1); + if (!*devp) { + fprintf(stderr, "%s: failed to allocate memory\n", progname); + free(devlink); + return -1; + } + + res = readlink (devlink, *devp, PATH_MAX); + free (devlink); + if (res == -1) { + fprintf(stderr, "%s: specified fuse fd is invalid\n", + progname); + return -1; + } + + return atoi(devfd); +} -static int mount_fuse(const char *mnt, const char *opts) +static int mount_fuse(const char *mnt, const char *opts, char *devfd) { int res; int fd; @@ -1030,7 +1060,7 @@ static int mount_fuse(const char *mnt, const char *opts) int currdir_fd = -1; int mountpoint_fd = -1; - fd = open_fuse_device(&dev); + fd = devfd ? check_fuse_device(devfd, &dev) : open_fuse_device(&dev); if (fd == -1) return -1; @@ -1154,6 +1184,7 @@ int main(int argc, char *argv[]) static int unmount = 0; static int lazy = 0; static int quiet = 0; + char *devfd; char *commfd; int cfd; const char *opts = ""; @@ -1242,21 +1273,26 @@ int main(int argc, char *argv[]) return 0; } - commfd = getenv(FUSE_COMMFD_ENV); - if (commfd == NULL) { - fprintf(stderr, "%s: old style mounting not supported\n", - progname); - exit(1); + devfd = getenv(FUSE_DEVFD_ENV); + if (devfd == NULL) { + commfd = getenv(FUSE_COMMFD_ENV); + if (commfd == NULL) { + fprintf(stderr, "%s: old style mounting not supported\n", + progname); + exit(1); + } } - fd = mount_fuse(mnt, opts); + fd = mount_fuse(mnt, opts, devfd); if (fd == -1) exit(1); - cfd = atoi(commfd); - res = send_fd(cfd, fd); - if (res == -1) - exit(1); + if (devfd == NULL) { + cfd = atoi(commfd); + res = send_fd(cfd, fd); + if (res == -1) + exit(1); + } return 0; } diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index 8fbbb2f8d40..903eac72ae6 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -386,7 +386,7 @@ create_fuse_mount (glusterfs_ctx_t *ctx) } if (!cmd_args->no_daemon_mode) { - ret = dict_set_static_ptr (master->options, "sync-mtab", + ret = dict_set_static_ptr (master->options, "sync-to-mount", "enable"); if (ret < 0) { gf_log ("glusterfsd", GF_LOG_ERROR, @@ -1502,11 +1502,11 @@ daemonize (glusterfs_ctx_t *ctx) case 0: break; default: - if (ctx->mtab_pid > 0) { - ret = waitpid (ctx->mtab_pid, &cstatus, 0); - if (!(ret == ctx->mtab_pid && cstatus == 0)) { + if (ctx->mnt_pid > 0) { + ret = waitpid (ctx->mnt_pid, &cstatus, 0); + if (!(ret == ctx->mnt_pid && cstatus == 0)) { gf_log ("daemonize", GF_LOG_ERROR, - "/etc/mtab update failed"); + "mount failed"); exit (1); } } diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 3eed8b163a5..0917ac1b586 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -357,7 +357,7 @@ struct _glusterfs_ctx { int graph_id; /* Incremented per graph, value should indicate how many times the graph has got changed */ - pid_t mtab_pid; /* pid of the process which updates the mtab */ + pid_t mnt_pid; /* pid of the mount agent */ int process_mode; /*mode in which process is runninng*/ struct syncenv *env; /* The env pointer to the synctasks */ diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index f14ccf5c178..42190083a27 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -3879,29 +3879,17 @@ int fuse_get_mount_status (xlator_t *this) { int kid_status = -1; - pid_t kid_pid = -1; fuse_private_t *priv = this->private; - int our_status = -1; if (read(priv->status_pipe[0],&kid_status, sizeof(kid_status)) < 0) { gf_log (this->name, GF_LOG_ERROR, "could not get mount status"); - goto out; + kid_status = -1; } gf_log (this->name, GF_LOG_DEBUG, "mount status is %d", kid_status); - if (read(priv->status_pipe[0],&kid_pid, sizeof(kid_pid)) < 0) { - gf_log (this->name, GF_LOG_ERROR, "could not get mount PID"); - goto out; - } - gf_log (this->name, GF_LOG_DEBUG, "mount PID is %d", kid_pid); - - (void)waitpid(kid_pid,NULL,0); - our_status = kid_status; - -out: close(priv->status_pipe[0]); close(priv->status_pipe[1]); - return our_status; + return kid_status; } static void * @@ -4384,7 +4372,7 @@ init (xlator_t *this_xl) int xl_name_allocated = 0; int fsname_allocated = 0; glusterfs_ctx_t *ctx = NULL; - gf_boolean_t sync_mtab = _gf_false; + gf_boolean_t sync_to_mount = _gf_false; char *mnt_args = NULL; if (this_xl == NULL) @@ -4532,11 +4520,11 @@ init (xlator_t *this_xl) priv->fuse_dump_fd = ret; } - sync_mtab = _gf_false; - ret = dict_get_str (options, "sync-mtab", &value_string); + sync_to_mount = _gf_false; + ret = dict_get_str (options, "sync-to-mount", &value_string); if (ret == 0) { ret = gf_string2boolean (value_string, - &sync_mtab); + &sync_to_mount); GF_ASSERT (ret == 0); } @@ -4582,7 +4570,7 @@ init (xlator_t *this_xl) } priv->fd = gf_fuse_mount (priv->mount_point, fsname, mnt_args, - sync_mtab ? &ctx->mtab_pid : NULL, + sync_to_mount ? &ctx->mnt_pid : NULL, priv->status_pipe[1]); if (priv->fd == -1) goto cleanup_exit; @@ -4694,7 +4682,7 @@ struct volume_options options[] = { { .key = {"uid-map-root"}, .type = GF_OPTION_TYPE_INT }, - { .key = {"sync-mtab"}, + { .key = {"sync-to-mount"}, .type = GF_OPTION_TYPE_BOOL }, { .key = {"read-only"}, diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in index 37cc2f9f60a..3ca09b03b1d 100755 --- a/xlators/mount/fuse/utils/mount.glusterfs.in +++ b/xlators/mount/fuse/utils/mount.glusterfs.in @@ -34,36 +34,6 @@ _init () UPDATEDBCONF=/etc/updatedb.conf } -# Mount happens asynchronously, so the command status alone will never be -# sufficient. Instead, we have to wait for multiple events representing -# different possible outcomes. -wait_for () -{ - local daemon_pid=$1 - local mount_point=$2 - - waited=0 - while true; do - kill -s 0 $daemon_pid - if [ $? != 0 ]; then - echo "Gluster client daemon exited unexpectedly." - umount $mount_point &> /dev/null - exit 1 - fi - inode=$(stat -c %i $mount_point 2>/dev/null); - if [ "$inode" = "1" ]; then - break - fi - if [ $waited -ge 10 ]; then - break - fi - sleep 1 - waited=$((waited+1)) - done - - echo "$inode" -} - start_glusterfs () { if [ -n "$log_level_str" ]; then @@ -151,33 +121,34 @@ start_glusterfs () cmd_line=$(echo "$cmd_line --volfile=$volfile_loc"); fi - cmd_line=$(echo "$cmd_line $mount_point") - err=0 - $cmd_line - daemon_pid=$$ + cmd_line=$(echo "$cmd_line $mount_point"); + err=0; + $cmd_line; + + + inode=$(stat -c %i $mount_point 2>/dev/null); - # Wait for the inode to change *or* for the daemon to exit (indicating a - # problem with the mount). - inode=$(wait_for $daemon_pid $mount_point) # this is required if the stat returns error if [ -z "$inode" ]; then - inode="0" + inode="0"; fi # retry the failover + # if [ $? != "0" ]; then # <--- TODO: Once glusterfs returns proper error code, change it. if [ $inode -ne 1 ]; then + err=1; if [ -n "$cmd_line1" ]; then cmd_line1=$(echo "$cmd_line1 $mount_point"); - $cmd_line1 - daemon_pid=$$ + $cmd_line1; + err=0; - inode=$(wait_for $daemon_pid $mount_point) + inode=$(stat -c %i $mount_point 2>/dev/null); # this is required if the stat returns error if [ -z "$inode" ]; then inode="0"; fi if [ $inode -ne 1 ]; then - err=1 + err=1; fi fi fi |