21ab4e
From 7d1da6b73706ce2cbbfa9eac302d415757167d57 Mon Sep 17 00:00:00 2001
3604df
From: Amar Tumballi <amarts@redhat.com>
3604df
Date: Mon, 29 May 2017 17:26:35 +0530
21ab4e
Subject: [PATCH 476/486] fuse: implement "-oauto_unmount"
3604df
3604df
libfuse has an auto_unmount option which,
3604df
if enabled, ensures that the file system
3604df
is unmounted at FUSE server termination
3604df
by running a separate monitor process
3604df
that performs the unmount when that
3604df
occurs. (This feature would probably
3604df
better be called "robust auto-unmount",
3604df
as FUSE servers usually do try to unmount
3604df
their file systems upon termination,
3604df
it's just this mechanism is not crash
3604df
resilient.)
3604df
3604df
This change implements that option and
3604df
behavior for glusterfs.
3604df
3604df
Note that "auto unmount" (robust or not) is
3604df
a leaky abstraction, as the kernel cannot
3604df
guarantee that at the path where the FUSE
3604df
fs is mounted is actually the toplevel mount
3604df
at the time of the umount(2) call, for
3604df
multiple reasons, among others, see:
3604df
3604df
  fuse-devel: "fuse: feasible to distinguish between umount and abort?"
3604df
  http://fuse.996288.n3.nabble.com/fuse-feasible-to-distinguish-between-umount-and-abort-tt14358.html
3604df
  https://github.com/libfuse/libfuse/issues/122
3604df
3604df
> Change-Id: Ia4432580c9fd2c156d9c73c3a44f4bfd42437599
3604df
> Signed-off-by: Csaba Henk <csaba@redhat.com>
3604df
> Reviewed-on: https://review.gluster.org/17230
3604df
> Tested-by: Amar Tumballi <amarts@redhat.com>
3604df
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
3604df
> Smoke: Gluster Build System <jenkins@build.gluster.org>
3604df
> Reviewed-by: Amar Tumballi <amarts@redhat.com>
3604df
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
3604df
21ab4e
BUG: 1424680
3604df
Change-Id: I4bae611254bad749b02abaf18d0ed6f447aec7b8
3604df
Signed-off-by: Amar Tumballi <amarts@redhat.com>
21ab4e
Reviewed-on: https://code.engineering.redhat.com/gerrit/107571
3604df
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
3604df
---
3604df
 contrib/fuse-include/fuse-mount.h           |  1 +
3604df
 contrib/fuse-lib/mount.c                    | 46 +++++++++++++++++++++++++++++
3604df
 xlators/mount/fuse/src/fuse-bridge.c        | 34 +++++++++++++++++++--
3604df
 xlators/mount/fuse/src/fuse-bridge.h        |  3 ++
3604df
 xlators/mount/fuse/utils/mount.glusterfs.in |  2 +-
3604df
 5 files changed, 82 insertions(+), 4 deletions(-)
3604df
3604df
diff --git a/contrib/fuse-include/fuse-mount.h b/contrib/fuse-include/fuse-mount.h
3604df
index 9358ac8..f2f08e3 100644
3604df
--- a/contrib/fuse-include/fuse-mount.h
3604df
+++ b/contrib/fuse-include/fuse-mount.h
3604df
@@ -8,6 +8,7 @@
3604df
 */
3604df
 
3604df
 void gf_fuse_unmount (const char *mountpoint, int fd);
3604df
+int gf_fuse_unmount_daemon (const char *mountpoint, int fd);
3604df
 int gf_fuse_mount (const char *mountpoint, char *fsname,
3604df
                    unsigned long mountflags, char *mnt_param,
3604df
                    pid_t *mtab_pid, int status_fd);
3604df
diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c
3604df
index 5e0b4dd..876ac90 100644
3604df
--- a/contrib/fuse-lib/mount.c
3604df
+++ b/contrib/fuse-lib/mount.c
3604df
@@ -75,6 +75,52 @@ gf_fuse_unmount (const char *mountpoint, int fd)
3604df
 
3604df
 /* gluster-specific routines */
3604df
 
3604df
+/* Unmounting in a daemon that lurks 'till main process exits */
3604df
+int
3604df
+gf_fuse_unmount_daemon (const char *mountpoint, int fd)
3604df
+{
3604df
+        int   ret = -1;
3604df
+        pid_t pid = -1;
3604df
+
3604df
+        if (fd == -1)
3604df
+                return -1;
3604df
+
3604df
+        int ump[2] = {0,};
3604df
+
3604df
+        ret = pipe(ump);
3604df
+        if (ret == -1) {
3604df
+                close (fd);
3604df
+                return -1;
3604df
+        }
3604df
+
3604df
+        pid = fork ();
3604df
+        switch (pid) {
3604df
+                char c = 0;
3604df
+                sigset_t sigset;
3604df
+        case 0:
3604df
+
3604df
+                close_fds_except (ump, 1);
3604df
+
3604df
+                setsid();
3604df
+                chdir("/");
3604df
+                sigfillset(&sigset);
3604df
+                sigprocmask(SIG_BLOCK, &sigset, NULL);
3604df
+
3604df
+                read (ump[0], &c, 1);
3604df
+
3604df
+                gf_fuse_unmount (mountpoint, fd);
3604df
+                exit (0);
3604df
+        case -1:
3604df
+                close (fd);
3604df
+                fd = -1;
3604df
+                ret = -1;
3604df
+                close (ump[1]);
3604df
+        }
3604df
+        close (ump[0]);
3604df
+
3604df
+        return ret;
3604df
+}
3604df
+
3604df
 static char *
3604df
 escape (char *s)
3604df
 {
3604df
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
21ab4e
index a0eb146..a8d936d 100644
3604df
--- a/xlators/mount/fuse/src/fuse-bridge.c
3604df
+++ b/xlators/mount/fuse/src/fuse-bridge.c
21ab4e
@@ -5089,7 +5089,7 @@ fuse_thread_proc (void *data)
3604df
                                                      ZR_MOUNTPOINT_OPT));
3604df
         if (mount_point) {
3604df
                 gf_log (this->name, GF_LOG_INFO,
3604df
-                        "unmounting %s", mount_point);
3604df
+                        "initating unmount of %s", mount_point);
3604df
         }
3604df
 
3604df
         /* Kill the whole process, not just this thread. */
21ab4e
@@ -5711,6 +5711,24 @@ init (xlator_t *this_xl)
3604df
         if (!mnt_args)
3604df
                 goto cleanup_exit;
3604df
 
3604df
+        {
3604df
+                char *mnt_tok         = NULL;
3604df
+                token_iter_t tit      = {0,};
3604df
+                gf_boolean_t iter_end = _gf_false;
3604df
+
3604df
+                for (mnt_tok = token_iter_init (mnt_args, ',', &tit) ;;) {
3604df
+                        iter_end = next_token (&mnt_tok, &tit;;
3604df
+
3604df
+                        if (strcmp (mnt_tok, "auto_unmount") == 0) {
3604df
+                                priv->auto_unmount = _gf_true;
3604df
+                                drop_token (mnt_tok, &tit;;
3604df
+                        }
3604df
+
3604df
+                        if (iter_end)
3604df
+                                break;
3604df
+                }
3604df
+        }
3604df
+
3604df
         if (pipe(priv->status_pipe) < 0) {
3604df
                 gf_log (this_xl->name, GF_LOG_ERROR,
3604df
                         "could not create pipe to separate mount process");
21ab4e
@@ -5722,6 +5740,11 @@ init (xlator_t *this_xl)
3604df
                                   priv->status_pipe[1]);
3604df
         if (priv->fd == -1)
3604df
                 goto cleanup_exit;
3604df
+        if (priv->auto_unmount) {
3604df
+                ret = gf_fuse_unmount_daemon (priv->mount_point, priv->fd);
3604df
+                if (ret == -1)
3604df
+                        goto cleanup_exit;
3604df
+        }
3604df
 
3604df
         event = eh_new (FUSE_EVENT_HISTORY_SIZE, _gf_false, NULL);
3604df
         if (!event) {
21ab4e
@@ -5799,10 +5822,15 @@ fini (xlator_t *this_xl)
3604df
                 mount_point = data_to_str (dict_get (this_xl->options,
3604df
                                                      ZR_MOUNTPOINT_OPT));
3604df
         if (mount_point != NULL) {
3604df
+                if (!priv->auto_unmount) {
3604df
+                        gf_log (this_xl->name, GF_LOG_INFO,
3604df
+                                "Unmounting '%s'.", mount_point);
3604df
+                        gf_fuse_unmount (mount_point, priv->fd);
3604df
+                }
3604df
+
3604df
                 gf_log (this_xl->name, GF_LOG_INFO,
3604df
-                        "Unmounting '%s'.", mount_point);
3604df
+                        "Closing fuse connection to '%s'.", mount_point);
3604df
 
3604df
-                gf_fuse_unmount (mount_point, priv->fd);
3604df
                 sys_close (priv->fuse_dump_fd);
3604df
                 dict_del (this_xl->options, ZR_MOUNTPOINT_OPT);
3604df
         }
3604df
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
3604df
index 40bd17b..0c70189 100644
3604df
--- a/xlators/mount/fuse/src/fuse-bridge.h
3604df
+++ b/xlators/mount/fuse/src/fuse-bridge.h
3604df
@@ -134,6 +134,9 @@ struct fuse_private {
3604df
 
3604df
         /* Enable or disable capability support */
3604df
         gf_boolean_t         capability;
3604df
+
3604df
+        /* whether to run the unmount daemon */
3604df
+        gf_boolean_t auto_unmount;
3604df
 };
3604df
 typedef struct fuse_private fuse_private_t;
3604df
 
3604df
diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in
3604df
index 6c4cdfe..2c5e466 100755
3604df
--- a/xlators/mount/fuse/utils/mount.glusterfs.in
3604df
+++ b/xlators/mount/fuse/utils/mount.glusterfs.in
3604df
@@ -538,7 +538,7 @@ without_options()
3604df
         "atime"|"noatime"|"diratime"|"nodiratime"|\
3604df
         "relatime"|"norelatime"|\
3604df
         "strictatime"|"nostrictatime"|"lazyatime"|"nolazyatime"|\
3604df
-        "dev"|"nodev"|"exec"|"noexec"|"suid"|"nosuid")
3604df
+        "dev"|"nodev"|"exec"|"noexec"|"suid"|"nosuid"|"auto_unmount")
3604df
             [ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts,"
3604df
             fuse_mountopts="${fuse_mountopts}${option}"
3604df
             ;;
3604df
-- 
3604df
1.8.3.1
3604df