7c2869
From fa2086eaa9545b472acd3fcc07be776d9f2cb38a Mon Sep 17 00:00:00 2001
7c2869
From: Kotresh HR <khiremat@redhat.com>
7c2869
Date: Thu, 15 Feb 2018 01:46:29 -0500
7c2869
Subject: [PATCH 646/646] geo-rep: Remove lazy umount and use mount namespaces
7c2869
7c2869
Lazy umounting the master volume by worker causes
7c2869
issues with rsync's usage of getcwd. Henc removing
7c2869
the lazy umount and using private mount namespace
7c2869
for the same. On the slave, the lazy umount is
7c2869
retained as we can't use private namespace in non
7c2869
root geo-rep setup because gsyncd is spawned as
7c2869
non privileged user.
7c2869
7c2869
Backport of https://review.gluster.org/#/c/19544/
7c2869
7c2869
Change-Id: I851e8dc2b8523dc5668a97e87ef619ab70471dfd
7c2869
BUG: 1547931
7c2869
Signed-off-by: Kotresh HR <khiremat@redhat.com>
7c2869
Reviewed-on: https://code.engineering.redhat.com/gerrit/131128
7c2869
Tested-by: RHGS Build Bot <nigelb@redhat.com>
7c2869
Reviewed-by: Aravinda Vishwanathapura Krishna Murthy <avishwan@redhat.com>
7c2869
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
7c2869
---
7c2869
 geo-replication/syncdaemon/gconf.py      |  3 +++
7c2869
 geo-replication/syncdaemon/gsyncd.py     | 14 +++++++-----
7c2869
 geo-replication/syncdaemon/monitor.py    | 38 ++++++++++++++++++++------------
7c2869
 geo-replication/syncdaemon/resource.py   | 16 ++++++++++++--
7c2869
 geo-replication/syncdaemon/syncdutils.py | 18 ++++++++++++++-
7c2869
 glusterfs.spec.in                        |  4 ++++
7c2869
 6 files changed, 70 insertions(+), 23 deletions(-)
7c2869
7c2869
diff --git a/geo-replication/syncdaemon/gconf.py b/geo-replication/syncdaemon/gconf.py
7c2869
index 97395b4..2280f44 100644
7c2869
--- a/geo-replication/syncdaemon/gconf.py
7c2869
+++ b/geo-replication/syncdaemon/gconf.py
7c2869
@@ -28,5 +28,8 @@ class GConf(object):
7c2869
     active_earlier = False
7c2869
     passive_earlier = False
7c2869
     mgmt_lock_fd = None
7c2869
+    mountbroker = False
7c2869
+    mount_point = None
7c2869
+    mbr_umount_cmd = []
7c2869
 
7c2869
 gconf = GConf()
7c2869
diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py
7c2869
index f9471e4..96256cf 100644
7c2869
--- a/geo-replication/syncdaemon/gsyncd.py
7c2869
+++ b/geo-replication/syncdaemon/gsyncd.py
7c2869
@@ -269,6 +269,8 @@ def main_i():
7c2869
                   type=str, action='callback', callback=store_abs)
7c2869
     op.add_option('--georep-session-working-dir', metavar='STATF',
7c2869
                   type=str, action='callback', callback=store_abs)
7c2869
+    op.add_option('--access-mount', default=False, action='store_true')
7c2869
+    op.add_option('--slave-access-mount', default=False, action='store_true')
7c2869
     op.add_option('--ignore-deletes', default=False, action='store_true')
7c2869
     op.add_option('--isolated-slave', default=False, action='store_true')
7c2869
     op.add_option('--use-rsync-xattrs', default=False, action='store_true')
7c2869
@@ -414,7 +416,7 @@ def main_i():
7c2869
                     o.get_opt_string() not in ('--version', '--help'))]
7c2869
     remote_tunables = ['listen', 'go_daemon', 'timeout',
7c2869
                        'session_owner', 'config_file', 'use_rsync_xattrs',
7c2869
-                       'local_id', 'local_node']
7c2869
+                       'local_id', 'local_node', 'slave_access_mount']
7c2869
     rq_remote_tunables = {'listen': True}
7c2869
 
7c2869
     # precedence for sources of values: 1) commandline, 2) cfg file, 3)
7c2869
@@ -748,15 +750,15 @@ def main_i():
7c2869
     else:
7c2869
         log_file = gconf.log_file
7c2869
     if be_monitor:
7c2869
-        label = 'monitor'
7c2869
+        gconf.label = 'monitor'
7c2869
     elif be_agent:
7c2869
-        label = gconf.local_path
7c2869
+        gconf.label = gconf.local_path
7c2869
     elif remote:
7c2869
         # master
7c2869
-        label = gconf.local_path
7c2869
+        gconf.label = gconf.local_path
7c2869
     else:
7c2869
-        label = 'slave'
7c2869
-    startup(go_daemon=go_daemon, log_file=log_file, label=label)
7c2869
+        gconf.label = 'slave'
7c2869
+    startup(go_daemon=go_daemon, log_file=log_file, label=gconf.label)
7c2869
     resource.Popen.init_errhandler()
7c2869
 
7c2869
     if be_agent:
7c2869
diff --git a/geo-replication/syncdaemon/monitor.py b/geo-replication/syncdaemon/monitor.py
7c2869
index dc0211e..087a202 100644
7c2869
--- a/geo-replication/syncdaemon/monitor.py
7c2869
+++ b/geo-replication/syncdaemon/monitor.py
7c2869
@@ -24,7 +24,7 @@ import random
7c2869
 from gconf import gconf
7c2869
 from syncdutils import select, waitpid, errno_wrap
7c2869
 from syncdutils import set_term_handler, is_host_local, GsyncdError
7c2869
-from syncdutils import escape, Thread, finalize, memoize
7c2869
+from syncdutils import escape, Thread, finalize, memoize, boolify
7c2869
 from syncdutils import gf_event, EVENT_GEOREP_FAULTY
7c2869
 
7c2869
 from gsyncdstatus import GeorepStatus, set_monitor_status
7c2869
@@ -301,19 +301,29 @@ class Monitor(object):
7c2869
                 os.close(pr)
7c2869
                 os.close(ra)
7c2869
                 os.close(wa)
7c2869
-                os.execv(sys.executable, argv + ['--feedback-fd', str(pw),
7c2869
-                                                 '--local-path', w[0]['dir'],
7c2869
-                                                 '--local-node', w[0]['host'],
7c2869
-                                                 '--local-node-id',
7c2869
-                                                 w[0]['uuid'],
7c2869
-                                                 '--local-id',
7c2869
-                                                 '.' + escape(w[0]['dir']),
7c2869
-                                                 '--rpc-fd',
7c2869
-                                                 ','.join([str(rw), str(ww),
7c2869
-                                                           str(ra), str(wa)]),
7c2869
-                                                 '--subvol-num', str(w[2])] +
7c2869
-                         (['--is-hottier'] if w[3] else []) +
7c2869
-                         ['--resource-remote', remote_host])
7c2869
+                args_to_worker = argv + ['--feedback-fd', str(pw),
7c2869
+                                         '--local-path', w[0]['dir'],
7c2869
+                                         '--local-node', w[0]['host'],
7c2869
+                                         '--local-node-id',
7c2869
+                                         w[0]['uuid'],
7c2869
+                                         '--local-id',
7c2869
+                                         '.' + escape(w[0]['dir']),
7c2869
+                                         '--rpc-fd',
7c2869
+                                         ','.join([str(rw), str(ww),
7c2869
+                                         str(ra), str(wa)]),
7c2869
+                                         '--subvol-num', str(w[2])]
7c2869
+
7c2869
+                if w[3]:
7c2869
+                    args_to_worker.append('--is-hottier')
7c2869
+                args_to_worker += ['--resource-remote', remote_host]
7c2869
+
7c2869
+                access_mount = boolify(gconf.access_mount)
7c2869
+                if access_mount:
7c2869
+                    os.execv(sys.executable, args_to_worker)
7c2869
+                else:
7c2869
+                    unshare_cmd = ['unshare', '-m', '--propagation', 'private']
7c2869
+                    cmd = unshare_cmd + args_to_worker
7c2869
+                    os.execvp("unshare", cmd)
7c2869
 
7c2869
             cpids.add(cpid)
7c2869
             agents.add(apid)
7c2869
diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py
7c2869
index 943e3ec..39d537b 100644
7c2869
--- a/geo-replication/syncdaemon/resource.py
7c2869
+++ b/geo-replication/syncdaemon/resource.py
7c2869
@@ -989,6 +989,8 @@ class SlaveRemote(object):
7c2869
             extra_opts += ['--local-node', ln]
7c2869
         if boolify(gconf.use_rsync_xattrs):
7c2869
             extra_opts.append('--use-rsync-xattrs')
7c2869
+        if boolify(gconf.slave_access_mount):
7c2869
+            extra_opts.append('--slave-access-mount')
7c2869
         po = Popen(rargs + gconf.remote_gsyncd.split() + extra_opts +
7c2869
                    ['-N', '--listen', '--timeout', str(gconf.timeout),
7c2869
                     slave],
7c2869
@@ -1258,6 +1260,7 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
7c2869
         def __init__(self, params):
7c2869
             self.params = params
7c2869
             self.mntpt = None
7c2869
+            self.umount_cmd = []
7c2869
 
7c2869
         @classmethod
7c2869
         def get_glusterprog(cls):
7c2869
@@ -1348,13 +1351,16 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
7c2869
                         assert(mntdata[-1] == '\0')
7c2869
                         mntpt = mntdata[:-1]
7c2869
                         assert(mntpt)
7c2869
-                        if mounted:
7c2869
+                        if mounted and gconf.label == 'slave' \
7c2869
+                           and not boolify(gconf.slave_access_mount):
7c2869
                             po = self.umount_l(mntpt)
7c2869
                             po.terminate_geterr(fail_on_err=False)
7c2869
                             if po.returncode != 0:
7c2869
                                 po.errlog()
7c2869
                                 rv = po.returncode
7c2869
-                        self.cleanup_mntpt(mntpt)
7c2869
+                        if gconf.label == 'slave' \
7c2869
+                           and not boolify(gconf.slave_access_mount):
7c2869
+                            self.cleanup_mntpt(mntpt)
7c2869
                 except:
7c2869
                     logging.exception('mount cleanup failure:')
7c2869
                     rv = 200
7c2869
@@ -1374,6 +1380,7 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
7c2869
 
7c2869
         def make_mount_argv(self):
7c2869
             self.mntpt = tempfile.mkdtemp(prefix='gsyncd-aux-mount-')
7c2869
+            gconf.mount_point = self.mntpt
7c2869
             return [self.get_glusterprog()] + \
7c2869
                 ['--' + p for p in self.params] + [self.mntpt]
7c2869
 
7c2869
@@ -1405,6 +1412,11 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
7c2869
 
7c2869
         def handle_mounter(self, po):
7c2869
             self.mntpt = po.stdout.readline()[:-1]
7c2869
+            gconf.mount_point = self.mntpt
7c2869
+            gconf.mountbroker = True
7c2869
+            self.umount_cmd = self.make_cli_argv() + ['umount']
7c2869
+            gconf.mbr_umount_cmd = self.umount_cmd
7c2869
+
7c2869
             po.stdout.close()
7c2869
             sup(self, po)
7c2869
             if po.returncode != 0:
7c2869
diff --git a/geo-replication/syncdaemon/syncdutils.py b/geo-replication/syncdaemon/syncdutils.py
7c2869
index a22289e..8dc6c96 100644
7c2869
--- a/geo-replication/syncdaemon/syncdutils.py
7c2869
+++ b/geo-replication/syncdaemon/syncdutils.py
7c2869
@@ -16,6 +16,7 @@ import fcntl
7c2869
 import shutil
7c2869
 import logging
7c2869
 import socket
7c2869
+import subprocess
7c2869
 from threading import Lock, Thread as baseThread
7c2869
 from errno import EACCES, EAGAIN, EPIPE, ENOTCONN, ECONNABORTED
7c2869
 from errno import EINTR, ENOENT, EPERM, ESTALE, EBUSY, errorcode
7c2869
@@ -188,7 +189,6 @@ def grabpidfile(fname=None, setpid=True):
7c2869
 
7c2869
 final_lock = Lock()
7c2869
 
7c2869
-
7c2869
 def finalize(*a, **kw):
7c2869
     """all those messy final steps we go trough upon termination
7c2869
 
7c2869
@@ -233,6 +233,22 @@ def finalize(*a, **kw):
7c2869
             if sys.exc_info()[0] == OSError:
7c2869
                 pass
7c2869
 
7c2869
+    """ Unmount if not done """
7c2869
+    if gconf.mount_point:
7c2869
+        if gconf.mountbroker:
7c2869
+            umount_cmd = gconf.mbr_umount_cmd + [gconf.mount_point, 'lazy']
7c2869
+        else:
7c2869
+            umount_cmd = ['umount', '-l', gconf.mount_point]
7c2869
+        p0 = subprocess.Popen(umount_cmd, stderr=subprocess.PIPE)
7c2869
+        _, errdata = p0.communicate()
7c2869
+        if p0.returncode == 0:
7c2869
+            try:
7c2869
+                os.rmdir(gconf.mount_point)
7c2869
+            except OSError:
7c2869
+                pass
7c2869
+        else:
7c2869
+            pass
7c2869
+
7c2869
     if gconf.log_exit:
7c2869
         logging.info("exiting.")
7c2869
     sys.stdout.flush()
7c2869
diff --git a/glusterfs.spec.in b/glusterfs.spec.in
7c2869
index fc9125b..b7bfcac 100644
7c2869
--- a/glusterfs.spec.in
7c2869
+++ b/glusterfs.spec.in
7c2869
@@ -439,6 +439,7 @@ Requires:         %{name}%{?_isa} = %{version}-%{release}
7c2869
 Requires:         %{name}-server%{?_isa} = %{version}-%{release}
7c2869
 Requires:         python python-ctypes
7c2869
 Requires:         rsync
7c2869
+Requires:         util-linux
7c2869
 
7c2869
 %description geo-replication
7c2869
 GlusterFS is a distributed file-system capable of scaling to several
7c2869
@@ -2067,6 +2068,9 @@ fi
7c2869
 %endif
7c2869
 
7c2869
 %changelog
7c2869
+* Thu Feb 22 2018 Kotresh HR <khiremat@redhat.com>
7c2869
+- Added util-linux as dependency to georeplication rpm (#1544382)
7c2869
+
7c2869
 * Wed Dec 20 2017 Milind Changire <mchangir@redhat.com>
7c2869
 - Remove ExclusiveArch directive to help building on non-x86_64 arches (#1527772)
7c2869
 
7c2869
-- 
7c2869
1.8.3.1
7c2869