e7a346
From 9f4564e55b1e515743a1f80d18989681d5d3b59f Mon Sep 17 00:00:00 2001
e7a346
From: Kotresh HR <khiremat@redhat.com>
e7a346
Date: Thu, 15 Feb 2018 01:46:29 -0500
e7a346
Subject: [PATCH 164/180] geo-rep: Remove lazy umount and use mount namespaces
e7a346
e7a346
Lazy umounting the master volume by worker causes
e7a346
issues with rsync's usage of getcwd. Henc removing
e7a346
the lazy umount and using private mount namespace
e7a346
for the same. On the slave, the lazy umount is
e7a346
retained as we can't use private namespace in non
e7a346
root geo-rep setup because gsyncd is spawned as
e7a346
non-privileged user.
e7a346
e7a346
Backport of https://review.gluster.org/#/c/19544/
e7a346
e7a346
Change-Id: I851e8dc2b8523dc5668a97e87ef619ab70471dfd
e7a346
BUG: 1544382
e7a346
Signed-off-by: Kotresh HR <khiremat@redhat.com>
e7a346
Reviewed-on: https://code.engineering.redhat.com/gerrit/130468
e7a346
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e7a346
Reviewed-by: Aravinda Vishwanathapura Krishna Murthy <avishwan@redhat.com>
e7a346
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
e7a346
---
e7a346
 geo-replication/syncdaemon/gconf.py      |  3 +++
e7a346
 geo-replication/syncdaemon/gsyncd.py     | 13 ++++++-----
e7a346
 geo-replication/syncdaemon/monitor.py    | 38 ++++++++++++++++++++------------
e7a346
 geo-replication/syncdaemon/resource.py   | 20 ++++++++++++-----
e7a346
 geo-replication/syncdaemon/syncdutils.py | 12 +++++-----
e7a346
 glusterfs.spec.in                        |  4 ++++
e7a346
 6 files changed, 59 insertions(+), 31 deletions(-)
e7a346
e7a346
diff --git a/geo-replication/syncdaemon/gconf.py b/geo-replication/syncdaemon/gconf.py
e7a346
index 97395b4..2280f44 100644
e7a346
--- a/geo-replication/syncdaemon/gconf.py
e7a346
+++ b/geo-replication/syncdaemon/gconf.py
e7a346
@@ -28,5 +28,8 @@ class GConf(object):
e7a346
     active_earlier = False
e7a346
     passive_earlier = False
e7a346
     mgmt_lock_fd = None
e7a346
+    mountbroker = False
e7a346
+    mount_point = None
e7a346
+    mbr_umount_cmd = []
e7a346
 
e7a346
 gconf = GConf()
e7a346
diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py
e7a346
index d77b90f..629e8b7 100644
e7a346
--- a/geo-replication/syncdaemon/gsyncd.py
e7a346
+++ b/geo-replication/syncdaemon/gsyncd.py
e7a346
@@ -276,6 +276,7 @@ def main_i():
e7a346
     op.add_option('--georep-session-working-dir', metavar='STATF',
e7a346
                   type=str, action='callback', callback=store_abs)
e7a346
     op.add_option('--access-mount', default=False, action='store_true')
e7a346
+    op.add_option('--slave-access-mount', default=False, action='store_true')
e7a346
     op.add_option('--ignore-deletes', default=False, action='store_true')
e7a346
     op.add_option('--isolated-slave', default=False, action='store_true')
e7a346
     op.add_option('--use-rsync-xattrs', default=False, action='store_true')
e7a346
@@ -431,7 +432,7 @@ def main_i():
e7a346
                     o.get_opt_string() not in ('--version', '--help'))]
e7a346
     remote_tunables = ['listen', 'go_daemon', 'timeout',
e7a346
                        'session_owner', 'config_file', 'use_rsync_xattrs',
e7a346
-                       'local_id', 'local_node', 'access_mount']
e7a346
+                       'local_id', 'local_node', 'slave_access_mount']
e7a346
     rq_remote_tunables = {'listen': True}
e7a346
 
e7a346
     # precedence for sources of values: 1) commandline, 2) cfg file, 3)
e7a346
@@ -768,15 +769,15 @@ def main_i():
e7a346
     else:
e7a346
         log_file = gconf.log_file
e7a346
     if be_monitor:
e7a346
-        label = 'monitor'
e7a346
+        gconf.label = 'monitor'
e7a346
     elif be_agent:
e7a346
-        label = gconf.local_path
e7a346
+        gconf.label = gconf.local_path
e7a346
     elif remote:
e7a346
         # master
e7a346
-        label = gconf.local_path
e7a346
+        gconf.label = gconf.local_path
e7a346
     else:
e7a346
-        label = 'slave'
e7a346
-    startup(go_daemon=go_daemon, log_file=log_file, label=label)
e7a346
+        gconf.label = 'slave'
e7a346
+    startup(go_daemon=go_daemon, log_file=log_file, label=gconf.label)
e7a346
     resource.Popen.init_errhandler()
e7a346
 
e7a346
     if be_agent:
e7a346
diff --git a/geo-replication/syncdaemon/monitor.py b/geo-replication/syncdaemon/monitor.py
e7a346
index 4da9330..0f43c4f 100644
e7a346
--- a/geo-replication/syncdaemon/monitor.py
e7a346
+++ b/geo-replication/syncdaemon/monitor.py
e7a346
@@ -24,7 +24,7 @@ import random
e7a346
 from gconf import gconf
e7a346
 from syncdutils import select, waitpid, errno_wrap, lf
e7a346
 from syncdutils import set_term_handler, is_host_local, GsyncdError
e7a346
-from syncdutils import escape, Thread, finalize, memoize
e7a346
+from syncdutils import escape, Thread, finalize, memoize, boolify
e7a346
 from syncdutils import gf_event, EVENT_GEOREP_FAULTY
e7a346
 
e7a346
 from gsyncdstatus import GeorepStatus, set_monitor_status
e7a346
@@ -306,19 +306,29 @@ class Monitor(object):
e7a346
                 os.close(pr)
e7a346
                 os.close(ra)
e7a346
                 os.close(wa)
e7a346
-                os.execv(sys.executable, argv + ['--feedback-fd', str(pw),
e7a346
-                                                 '--local-path', w[0]['dir'],
e7a346
-                                                 '--local-node', w[0]['host'],
e7a346
-                                                 '--local-node-id',
e7a346
-                                                 w[0]['uuid'],
e7a346
-                                                 '--local-id',
e7a346
-                                                 '.' + escape(w[0]['dir']),
e7a346
-                                                 '--rpc-fd',
e7a346
-                                                 ','.join([str(rw), str(ww),
e7a346
-                                                           str(ra), str(wa)]),
e7a346
-                                                 '--subvol-num', str(w[2])] +
e7a346
-                         (['--is-hottier'] if w[3] else []) +
e7a346
-                         ['--resource-remote', remote_host])
e7a346
+                args_to_worker = argv + ['--feedback-fd', str(pw),
e7a346
+                                         '--local-path', w[0]['dir'],
e7a346
+                                         '--local-node', w[0]['host'],
e7a346
+                                         '--local-node-id',
e7a346
+                                         w[0]['uuid'],
e7a346
+                                         '--local-id',
e7a346
+                                         '.' + escape(w[0]['dir']),
e7a346
+                                         '--rpc-fd',
e7a346
+                                         ','.join([str(rw), str(ww),
e7a346
+                                         str(ra), str(wa)]),
e7a346
+                                         '--subvol-num', str(w[2])]
e7a346
+
e7a346
+                if w[3]:
e7a346
+                    args_to_worker.append('--is-hottier')
e7a346
+                args_to_worker += ['--resource-remote', remote_host]
e7a346
+
e7a346
+                access_mount = boolify(gconf.access_mount)
e7a346
+                if access_mount:
e7a346
+                    os.execv(sys.executable, args_to_worker)
e7a346
+                else:
e7a346
+                    unshare_cmd = ['unshare', '-m', '--propagation', 'private']
e7a346
+                    cmd = unshare_cmd + args_to_worker
e7a346
+                    os.execvp("unshare", cmd)
e7a346
 
e7a346
             cpids.add(cpid)
e7a346
             agents.add(apid)
e7a346
diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py
e7a346
index 5ad5b97..4b2a266 100644
e7a346
--- a/geo-replication/syncdaemon/resource.py
e7a346
+++ b/geo-replication/syncdaemon/resource.py
e7a346
@@ -43,7 +43,7 @@ from syncdutils import CHANGELOG_AGENT_CLIENT_VERSION
e7a346
 from syncdutils import GX_GFID_CANONICAL_LEN
e7a346
 from gsyncdstatus import GeorepStatus
e7a346
 from syncdutils import get_master_and_slave_data_from_args
e7a346
-from syncdutils import mntpt_list, lf
e7a346
+from syncdutils import lf
e7a346
 from syncdutils import Xattr, matching_disk_gfid, get_gfid_from_mnt
e7a346
 
e7a346
 UrlRX = re.compile('\A(\w+)://([^ *?[]*)\Z')
e7a346
@@ -1047,8 +1047,8 @@ class SlaveRemote(object):
e7a346
             extra_opts += ['--local-node', ln]
e7a346
         if boolify(gconf.use_rsync_xattrs):
e7a346
             extra_opts.append('--use-rsync-xattrs')
e7a346
-        if boolify(gconf.access_mount):
e7a346
-            extra_opts.append('--access-mount')
e7a346
+        if boolify(gconf.slave_access_mount):
e7a346
+            extra_opts.append('--slave-access-mount')
e7a346
         po = Popen(rargs + gconf.remote_gsyncd.split() + extra_opts +
e7a346
                    ['-N', '--listen', '--timeout', str(gconf.timeout),
e7a346
                     slave],
e7a346
@@ -1333,6 +1333,7 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
e7a346
         def __init__(self, params):
e7a346
             self.params = params
e7a346
             self.mntpt = None
e7a346
+            self.umount_cmd = []
e7a346
 
e7a346
         @classmethod
e7a346
         def get_glusterprog(cls):
e7a346
@@ -1424,13 +1425,15 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
e7a346
                         assert(mntdata[-1] == '\0')
e7a346
                         mntpt = mntdata[:-1]
e7a346
                         assert(mntpt)
e7a346
-                        if mounted and not boolify(gconf.access_mount):
e7a346
+                        if mounted and gconf.label == 'slave' \
e7a346
+                           and not boolify(gconf.slave_access_mount):
e7a346
                             po = self.umount_l(mntpt)
e7a346
                             po.terminate_geterr(fail_on_err=False)
e7a346
                             if po.returncode != 0:
e7a346
                                 po.errlog()
e7a346
                                 rv = po.returncode
e7a346
-                        if not boolify(gconf.access_mount):
e7a346
+                        if gconf.label == 'slave' \
e7a346
+                           and not boolify(gconf.slave_access_mount):
e7a346
                             self.cleanup_mntpt(mntpt)
e7a346
                 except:
e7a346
                     logging.exception('mount cleanup failure:')
e7a346
@@ -1451,7 +1454,7 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
e7a346
 
e7a346
         def make_mount_argv(self):
e7a346
             self.mntpt = tempfile.mkdtemp(prefix='gsyncd-aux-mount-')
e7a346
-            mntpt_list.append(self.mntpt)
e7a346
+            gconf.mount_point = self.mntpt
e7a346
             return [self.get_glusterprog()] + \
e7a346
                 ['--' + p for p in self.params] + [self.mntpt]
e7a346
 
e7a346
@@ -1483,6 +1486,11 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
e7a346
 
e7a346
         def handle_mounter(self, po):
e7a346
             self.mntpt = po.stdout.readline()[:-1]
e7a346
+            gconf.mount_point = self.mntpt
e7a346
+            gconf.mountbroker = True
e7a346
+            self.umount_cmd = self.make_cli_argv() + ['umount']
e7a346
+            gconf.mbr_umount_cmd = self.umount_cmd
e7a346
+
e7a346
             po.stdout.close()
e7a346
             sup(self, po)
e7a346
             if po.returncode != 0:
e7a346
diff --git a/geo-replication/syncdaemon/syncdutils.py b/geo-replication/syncdaemon/syncdutils.py
e7a346
index 269f301..2b57f83 100644
e7a346
--- a/geo-replication/syncdaemon/syncdutils.py
e7a346
+++ b/geo-replication/syncdaemon/syncdutils.py
e7a346
@@ -23,7 +23,6 @@ from errno import EINTR, ENOENT, EPERM, ESTALE, EBUSY, errorcode
e7a346
 from signal import signal, SIGTERM
e7a346
 import select as oselect
e7a346
 from os import waitpid as owaitpid
e7a346
-import subprocess
e7a346
 
e7a346
 from conf import GLUSTERFS_LIBEXECDIR, UUID_FILE
e7a346
 sys.path.insert(1, GLUSTERFS_LIBEXECDIR)
e7a346
@@ -209,7 +208,6 @@ def grabpidfile(fname=None, setpid=True):
e7a346
 
e7a346
 final_lock = Lock()
e7a346
 
e7a346
-mntpt_list = []
e7a346
 def finalize(*a, **kw):
e7a346
     """all those messy final steps we go trough upon termination
e7a346
 
e7a346
@@ -256,12 +254,16 @@ def finalize(*a, **kw):
e7a346
                 pass
e7a346
 
e7a346
     """ Unmount if not done """
e7a346
-    for mnt in mntpt_list:
e7a346
-        p0 = subprocess.Popen (["umount", "-l", mnt], stderr=subprocess.PIPE)
e7a346
+    if gconf.mount_point:
e7a346
+        if gconf.mountbroker:
e7a346
+            umount_cmd = gconf.mbr_umount_cmd + [gconf.mount_point, 'lazy']
e7a346
+        else:
e7a346
+            umount_cmd = ['umount', '-l', gconf.mount_point]
e7a346
+        p0 = subprocess.Popen(umount_cmd, stderr=subprocess.PIPE)
e7a346
         _, errdata = p0.communicate()
e7a346
         if p0.returncode == 0:
e7a346
             try:
e7a346
-                os.rmdir(mnt)
e7a346
+                os.rmdir(gconf.mount_point)
e7a346
             except OSError:
e7a346
                 pass
e7a346
         else:
e7a346
diff --git a/glusterfs.spec.in b/glusterfs.spec.in
e7a346
index 3181d72..8379f64 100644
e7a346
--- a/glusterfs.spec.in
e7a346
+++ b/glusterfs.spec.in
e7a346
@@ -453,6 +453,7 @@ BuildRequires:    python-ctypes
e7a346
 %endif
e7a346
 Requires:         python2-gluster = %{version}-%{release}
e7a346
 Requires:         rsync
e7a346
+Requires:         util-linux
e7a346
 
e7a346
 %description geo-replication
e7a346
 GlusterFS is a distributed file-system capable of scaling to several
e7a346
@@ -2147,6 +2148,9 @@ fi
e7a346
 %endif
e7a346
 
e7a346
 %changelog
e7a346
+* Thu Feb 22 2018 Kotresh HR <khiremat@redhat.com>
e7a346
+- Added util-linux as dependency to georeplication rpm (#1544382)
e7a346
+
e7a346
 * Wed Jan 17 2018 Milind Changire <mchangir@redhat.com>
e7a346
 - DOWNSTREAM ONLY - Removed pretrans script for glusterfs-ganesha - (#1410719)
e7a346
 
e7a346
-- 
e7a346
1.8.3.1
e7a346