From c5d781e05599e9e7ad736d42c9c1033992c76ded Mon Sep 17 00:00:00 2001 From: Csaba Henk Date: Sun, 15 May 2011 04:52:33 +0000 Subject: upon daemonizing, wait on mtab update to terminate in parent This fixes the race in between the mtab update attempts of mount and umount when we do a lazy umount right after mounting, in order to hide the given fs instance; yet this way we still avoid the deadlock of the fs and mount which we can hit if we wait unconditionally for the mtab update to terminate (cf. bz #511). Signed-off-by: Csaba Henk Signed-off-by: Anand Avati BUG: 2690 (race between mtab updates of mount and umount) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2690 --- contrib/apple/daemon.c | 26 +++++++++++++------- contrib/apple/daemon.h | 1 + contrib/fuse-include/fuse-mount.h | 3 ++- contrib/fuse-lib/mount.c | 52 ++++++++++++++++++++++----------------- contrib/macfuse/mount_darwin.c | 3 ++- 5 files changed, 52 insertions(+), 33 deletions(-) (limited to 'contrib') diff --git a/contrib/apple/daemon.c b/contrib/apple/daemon.c index 9389201a1af..07dbbc400b3 100644 --- a/contrib/apple/daemon.c +++ b/contrib/apple/daemon.c @@ -44,7 +44,7 @@ #include int -os_daemon(nochdir, noclose) +os_daemon_return(nochdir, noclose) int nochdir, noclose; { struct sigaction osa, sa; @@ -52,6 +52,7 @@ os_daemon(nochdir, noclose) pid_t newgrp; int oerrno; int osa_ok; + int ret; /* A SIGHUP may be thrown when the parent exits below. */ sigemptyset(&sa.sa_mask); @@ -59,14 +60,9 @@ os_daemon(nochdir, noclose) sa.sa_flags = 0; osa_ok = sigaction(SIGHUP, &sa, &osa); - switch (fork()) { - case -1: - return (-1); - case 0: - break; - default: - _exit(0); - } + ret = fork(); + if (ret) + return ret; newgrp = setsid(); oerrno = errno; @@ -90,3 +86,15 @@ os_daemon(nochdir, noclose) } return (0); } + +int +os_daemon(int nochdir, int noclose) +{ + int ret; + + ret = os_daemon_return(nochdir, noclose); + if (ret <= 0) + return ret; + + _exit(0); +} diff --git a/contrib/apple/daemon.h b/contrib/apple/daemon.h index 7a2824b6a47..aa88d9baa56 100644 --- a/contrib/apple/daemon.h +++ b/contrib/apple/daemon.h @@ -17,4 +17,5 @@ . */ +int os_daemon_return(int nochdir, int noclose); int os_daemon(int nochdir, int noclose); diff --git a/contrib/fuse-include/fuse-mount.h b/contrib/fuse-include/fuse-mount.h index ca571ce5e30..9f83faf02a0 100644 --- a/contrib/fuse-include/fuse-mount.h +++ b/contrib/fuse-include/fuse-mount.h @@ -8,4 +8,5 @@ */ void gf_fuse_unmount (const char *mountpoint, int fd); -int gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param); +int gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param, + pid_t *mtab_pid); diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c index 47592a62dd8..f922b07d44b 100644 --- a/contrib/fuse-lib/mount.c +++ b/contrib/fuse-lib/mount.c @@ -97,7 +97,8 @@ static #endif int fuse_mnt_add_mount (const char *progname, const char *fsname, - const char *mnt, const char *type, const char *opts) + const char *mnt, const char *type, const char *opts, + pid_t *mtab_pid) { int res; int status; @@ -125,19 +126,22 @@ fuse_mnt_add_mount (const char *progname, const char *fsname, char templ[] = "/tmp/fusermountXXXXXX"; char *tmp; - /* mtab update done async, just log if fails */ - res = fork (); - if (res) - exit (res == -1 ? 1 : 0); - res = fork (); - if (res) { - if (res != -1) - res = waitpid (res, &status, 0); - if (res == -1) - GFFUSE_LOGERR ("%s: /etc/mtab update failed", - progname); - - exit (0); + 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); @@ -165,13 +169,16 @@ fuse_mnt_add_mount (const char *progname, const char *fsname, progname, strerror (errno)); exit (1); } - res = waitpid (res, &status, 0); + if (mtab_pid) { + *mtab_pid = res; + res = 0; + } else { + if (!(res == waitpid (res, &status, 0) && status == 0)) + res = -1; + } if (res == -1) GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno)); - if (status != 0) - res = -1; - out_restore: sigprocmask (SIG_SETMASK, &oldmask, NULL); return res; @@ -519,7 +526,7 @@ gf_fuse_unmount (const char *mountpoint, int fd) #ifndef FUSE_UTIL static int -fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param) +fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param, pid_t *mtab_pid) { int fd = -1, ret = -1; unsigned mounted = 0; @@ -573,7 +580,7 @@ fuse_mount_sys (const char *mountpoint, char *fsname, char *mnt_param) } ret = fuse_mnt_add_mount ("fuse", source, newmnt, fstype, - mnt_param); + mnt_param, mtab_pid); FREE (newmnt); if (ret == -1) { GFFUSE_LOGERR ("failed to add mtab entry"); @@ -625,13 +632,14 @@ escape (char *s) } int -gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param) +gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param, + pid_t *mtab_pid) { int fd = -1, rv = -1; char *fm_mnt_params = NULL, *p = NULL; char *efsname = NULL; - fd = fuse_mount_sys (mountpoint, fsname, mnt_param); + fd = fuse_mount_sys (mountpoint, fsname, mnt_param, mtab_pid); if (fd == -1) { gf_log ("glusterfs-fuse", GF_LOG_INFO, "direct mount failed (%s), " diff --git a/contrib/macfuse/mount_darwin.c b/contrib/macfuse/mount_darwin.c index 9d87fca3596..c485583e96b 100644 --- a/contrib/macfuse/mount_darwin.c +++ b/contrib/macfuse/mount_darwin.c @@ -133,7 +133,8 @@ Return: } int -gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param) +gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param, + pid_t *mtab_pid /* not used on OS X */) { int fd, pid; int result; -- cgit