summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCsaba Henk <csaba@redhat.com>2017-05-09 19:26:40 +0200
committerShyamsundar Ranganathan <srangana@redhat.com>2017-06-20 13:44:39 +0000
commitcd5c913ebc964c6a2907ef1c11aff1d2015a14b1 (patch)
tree478a088a6c2a3575d62a16e6d1ed6d69083b70ad
parent8f658c9501245bc0730e1724b016ca28f6ddfb3b (diff)
fuse: implement "-oauto_unmount"
libfuse has an auto_unmount option which, if enabled, ensures that the file system is unmounted at FUSE server termination by running a separate monitor process that performs the unmount when that occurs. (This feature would probably better be called "robust auto-unmount", as FUSE servers usually do try to unmount their file systems upon termination, it's just this mechanism is not crash resilient.) This change implements that option and behavior for glusterfs. Note that "auto unmount" (robust or not) is a leaky abstraction, as the kernel cannot guarantee that at the path where the FUSE fs is mounted is actually the toplevel mount at the time of the umount(2) call, for multiple reasons, among others, see: fuse-devel: "fuse: feasible to distinguish between umount and abort?" http://fuse.996288.n3.nabble.com/fuse-feasible-to-distinguish-between-umount-and-abort-tt14358.html https://github.com/libfuse/libfuse/issues/122 Updates #153 > Change-Id: Ia4432580c9fd2c156d9c73c3a44f4bfd42437599 > Signed-off-by: Csaba Henk <csaba@redhat.com> > Reviewed-on: https://review.gluster.org/17230 > Tested-by: Amar Tumballi <amarts@redhat.com> > CentOS-regression: Gluster Build System <jenkins@build.gluster.org> > Smoke: Gluster Build System <jenkins@build.gluster.org> > Reviewed-by: Amar Tumballi <amarts@redhat.com> > NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> (cherry picked from commit 461888bb63b2409f8245c7766aa799ca22f734e6) Change-Id: Ia4432580c9fd2c156d9c73c3a44f4bfd42437599 Signed-off-by: Csaba Henk <csaba@redhat.com> Reviewed-on: https://review.gluster.org/17573 Smoke: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Amar Tumballi <amarts@redhat.com> Tested-by: Amar Tumballi <amarts@redhat.com> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
-rw-r--r--contrib/fuse-include/fuse-mount.h1
-rw-r--r--contrib/fuse-lib/mount.c46
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c34
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h3
-rwxr-xr-xxlators/mount/fuse/utils/mount.glusterfs.in2
5 files changed, 82 insertions, 4 deletions
diff --git a/contrib/fuse-include/fuse-mount.h b/contrib/fuse-include/fuse-mount.h
index 7a3756d..7d28462 100644
--- a/contrib/fuse-include/fuse-mount.h
+++ b/contrib/fuse-include/fuse-mount.h
@@ -8,5 +8,6 @@
*/
void gf_fuse_unmount (const char *mountpoint, int fd);
+int gf_fuse_unmount_daemon (const char *mountpoint, int fd);
int gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param,
pid_t *mtab_pid, int status_fd);
diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c
index 5bdf454..05d04b7 100644
--- a/contrib/fuse-lib/mount.c
+++ b/contrib/fuse-lib/mount.c
@@ -75,6 +75,52 @@ gf_fuse_unmount (const char *mountpoint, int fd)
/* gluster-specific routines */
+/* Unmounting in a daemon that lurks 'till main process exits */
+int
+gf_fuse_unmount_daemon (const char *mountpoint, int fd)
+{
+ int ret = -1;
+ pid_t pid = -1;
+
+ if (fd == -1)
+ return -1;
+
+ int ump[2] = {0,};
+
+ ret = pipe(ump);
+ if (ret == -1) {
+ close (fd);
+ return -1;
+ }
+
+ pid = fork ();
+ switch (pid) {
+ char c = 0;
+ sigset_t sigset;
+ case 0:
+
+ close_fds_except (ump, 1);
+
+ setsid();
+ chdir("/");
+ sigfillset(&sigset);
+ sigprocmask(SIG_BLOCK, &sigset, NULL);
+
+ read (ump[0], &c, 1);
+
+ gf_fuse_unmount (mountpoint, fd);
+ exit (0);
+ case -1:
+ close (fd);
+ fd = -1;
+ ret = -1;
+ close (ump[1]);
+ }
+ close (ump[0]);
+
+ return ret;
+}
+
static char *
escape (char *s)
{
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index 0c40926..ca08185 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -5150,7 +5150,7 @@ fuse_thread_proc (void *data)
ZR_MOUNTPOINT_OPT));
if (mount_point) {
gf_log (this->name, GF_LOG_INFO,
- "unmounting %s", mount_point);
+ "initating unmount of %s", mount_point);
}
/* Kill the whole process, not just this thread. */
@@ -5775,6 +5775,24 @@ init (xlator_t *this_xl)
if (!mnt_args)
goto cleanup_exit;
+ {
+ char *mnt_tok = NULL;
+ token_iter_t tit = {0,};
+ gf_boolean_t iter_end = _gf_false;
+
+ for (mnt_tok = token_iter_init (mnt_args, ',', &tit) ;;) {
+ iter_end = next_token (&mnt_tok, &tit);
+
+ if (strcmp (mnt_tok, "auto_unmount") == 0) {
+ priv->auto_unmount = _gf_true;
+ drop_token (mnt_tok, &tit);
+ }
+
+ if (iter_end)
+ break;
+ }
+ }
+
if (pipe(priv->status_pipe) < 0) {
gf_log (this_xl->name, GF_LOG_ERROR,
"could not create pipe to separate mount process");
@@ -5786,6 +5804,11 @@ init (xlator_t *this_xl)
priv->status_pipe[1]);
if (priv->fd == -1)
goto cleanup_exit;
+ if (priv->auto_unmount) {
+ ret = gf_fuse_unmount_daemon (priv->mount_point, priv->fd);
+ if (ret ==-1)
+ goto cleanup_exit;
+ }
event = eh_new (FUSE_EVENT_HISTORY_SIZE, _gf_false, NULL);
if (!event) {
@@ -5863,10 +5886,15 @@ fini (xlator_t *this_xl)
mount_point = data_to_str (dict_get (this_xl->options,
ZR_MOUNTPOINT_OPT));
if (mount_point != NULL) {
+ if (!priv->auto_unmount) {
+ gf_log (this_xl->name, GF_LOG_INFO,
+ "Unmounting '%s'.", mount_point);
+ gf_fuse_unmount (mount_point, priv->fd);
+ }
+
gf_log (this_xl->name, GF_LOG_INFO,
- "Unmounting '%s'.", mount_point);
+ "Closing fuse connection to '%s'.", mount_point);
- gf_fuse_unmount (mount_point, priv->fd);
sys_close (priv->fuse_dump_fd);
dict_del (this_xl->options, ZR_MOUNTPOINT_OPT);
}
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
index e4075c8..201b7f6 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -134,6 +134,9 @@ struct fuse_private {
/* Enable or disable capability support */
gf_boolean_t capability;
+
+ /* whether to run the unmount daemon */
+ gf_boolean_t auto_unmount;
};
typedef struct fuse_private fuse_private_t;
diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in
index b5c90ba..66dd7cd 100755
--- a/xlators/mount/fuse/utils/mount.glusterfs.in
+++ b/xlators/mount/fuse/utils/mount.glusterfs.in
@@ -562,7 +562,7 @@ without_options()
"atime"|"noatime"|"diratime"|"nodiratime"|\
"relatime"|"norelatime"|\
"strictatime"|"nostrictatime"|"lazyatime"|"nolazyatime"|\
- "dev"|"nodev"|"exec"|"noexec"|"suid"|"nosuid")
+ "dev"|"nodev"|"exec"|"noexec"|"suid"|"nosuid"|"auto_unmount")
[ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts,"
fuse_mountopts="${fuse_mountopts}${option}"
;;