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