summaryrefslogtreecommitdiffstats
path: root/contrib/fuse-lib/mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/fuse-lib/mount.c')
-rw-r--r--contrib/fuse-lib/mount.c312
1 files changed, 107 insertions, 205 deletions
diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c
index fde9f31..759014f 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
@@ -611,7 +562,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");
@@ -621,75 +572,25 @@ fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param, pid_t *mt
}
#endif /* __NetBSD__ */
- 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) {
@@ -698,45 +599,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