d1681e
From 77d79754d914ce7d15d02d5fc9d9785609094850 Mon Sep 17 00:00:00 2001
d1681e
From: Kotresh HR <khiremat@redhat.com>
d1681e
Date: Thu, 7 Jun 2018 06:32:36 -0400
d1681e
Subject: [PATCH 305/305] geo-rep: Fix geo-rep for older versions of unshare
d1681e
d1681e
Geo-rep mounts are private to worker. It uses
d1681e
mount namespace using unshare command to achieve
d1681e
the same. Well, the unshare command has to support
d1681e
'--propagation' option. So geo-rep breaks on the
d1681e
systems with older unshare version. The patch
d1681e
makes it fall back to lazy umount behaviour if
d1681e
the unshare does not support propagation option.
d1681e
d1681e
Backpor of:
d1681e
  > Patch: https://review.gluster.org/20221
d1681e
  > fixes: bz#1589782
d1681e
  > Change-Id: Ia614f068aede288d63ac62fea4461b1865066054
d1681e
  > Signed-off-by: Kotresh HR <khiremat@redhat.com>
d1681e
d1681e
BUG: 1569312
d1681e
Change-Id: Ia614f068aede288d63ac62fea4461b1865066054
d1681e
Signed-off-by: Kotresh HR <khiremat@redhat.com>
d1681e
Reviewed-on: https://code.engineering.redhat.com/gerrit/142613
d1681e
Tested-by: RHGS Build Bot <nigelb@redhat.com>
d1681e
Reviewed-by: Aravinda Vishwanathapura Krishna Murthy <avishwan@redhat.com>
d1681e
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
d1681e
---
d1681e
 geo-replication/syncdaemon/gsyncd.py     |  1 +
d1681e
 geo-replication/syncdaemon/monitor.py    | 15 +++++++++++----
d1681e
 geo-replication/syncdaemon/resource.py   | 21 ++++++++++++++++++---
d1681e
 geo-replication/syncdaemon/syncdutils.py | 18 ++++++++++++++++++
d1681e
 4 files changed, 48 insertions(+), 7 deletions(-)
d1681e
d1681e
diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py
d1681e
index b0ed0ae..fff193b 100644
d1681e
--- a/geo-replication/syncdaemon/gsyncd.py
d1681e
+++ b/geo-replication/syncdaemon/gsyncd.py
d1681e
@@ -775,6 +775,7 @@ def main_i():
d1681e
     elif remote:
d1681e
         # master
d1681e
         gconf.label = gconf.local_path
d1681e
+        gconf.worker = True
d1681e
     else:
d1681e
         gconf.label = 'slave'
d1681e
     startup(go_daemon=go_daemon, log_file=log_file, label=gconf.label)
d1681e
diff --git a/geo-replication/syncdaemon/monitor.py b/geo-replication/syncdaemon/monitor.py
d1681e
index 55f8330..9245572 100644
d1681e
--- a/geo-replication/syncdaemon/monitor.py
d1681e
+++ b/geo-replication/syncdaemon/monitor.py
d1681e
@@ -29,7 +29,7 @@ from syncdutils import gf_event, EVENT_GEOREP_FAULTY
d1681e
 from syncdutils import Volinfo, Popen
d1681e
 
d1681e
 from gsyncdstatus import GeorepStatus, set_monitor_status
d1681e
-
d1681e
+from syncdutils import unshare_propagation_supported
d1681e
 
d1681e
 ParseError = XET.ParseError if hasattr(XET, 'ParseError') else SyntaxError
d1681e
 
d1681e
@@ -247,9 +247,16 @@ class Monitor(object):
d1681e
                 if access_mount:
d1681e
                     os.execv(sys.executable, args_to_worker)
d1681e
                 else:
d1681e
-                    unshare_cmd = ['unshare', '-m', '--propagation', 'private']
d1681e
-                    cmd = unshare_cmd + args_to_worker
d1681e
-                    os.execvp("unshare", cmd)
d1681e
+                    if unshare_propagation_supported():
d1681e
+                        logging.debug("Worker would mount volume privately")
d1681e
+                        unshare_cmd = ['unshare', '-m', '--propagation',
d1681e
+                                       'private']
d1681e
+                        cmd = unshare_cmd + args_to_worker
d1681e
+                        os.execvp("unshare", cmd)
d1681e
+                    else:
d1681e
+                        logging.debug("Mount is not private. It would be lazy"
d1681e
+                                      " umounted")
d1681e
+                        os.execv(sys.executable, args_to_worker)
d1681e
 
d1681e
             cpids.add(cpid)
d1681e
             agents.add(apid)
d1681e
diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py
d1681e
index c4b5b53..00e62b7 100644
d1681e
--- a/geo-replication/syncdaemon/resource.py
d1681e
+++ b/geo-replication/syncdaemon/resource.py
d1681e
@@ -40,6 +40,7 @@ from gsyncdstatus import GeorepStatus
d1681e
 from syncdutils import get_master_and_slave_data_from_args
d1681e
 from syncdutils import lf, Popen, sup, Volinfo
d1681e
 from syncdutils import Xattr, matching_disk_gfid, get_gfid_from_mnt
d1681e
+from syncdutils import unshare_propagation_supported
d1681e
 
d1681e
 UrlRX = re.compile('\A(\w+)://([^ *?[]*)\Z')
d1681e
 HostRX = re.compile('[a-zA-Z\d](?:[a-zA-Z\d.-]*[a-zA-Z\d])?', re.I)
d1681e
@@ -1302,15 +1303,29 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
d1681e
                         assert(mntdata[-1] == '\0')
d1681e
                         mntpt = mntdata[:-1]
d1681e
                         assert(mntpt)
d1681e
-                        if mounted and gconf.label == 'slave' \
d1681e
+
d1681e
+                        umount_master = False
d1681e
+                        umount_slave = False
d1681e
+                        master_access_mount = getattr(gconf, 'access_mount',
d1681e
+                                                      False)
d1681e
+                        worker = getattr(gconf, 'worker', None)
d1681e
+
d1681e
+                        if worker \
d1681e
+                           and not unshare_propagation_supported() \
d1681e
+                           and not boolify(master_access_mount):
d1681e
+                            umount_master = True
d1681e
+                        if gconf.label == 'slave' \
d1681e
                            and not boolify(gconf.slave_access_mount):
d1681e
+                            umount_slave = True
d1681e
+
d1681e
+                        if mounted and (umount_master or umount_slave):
d1681e
                             po = self.umount_l(mntpt)
d1681e
                             po.terminate_geterr(fail_on_err=False)
d1681e
                             if po.returncode != 0:
d1681e
                                 po.errlog()
d1681e
                                 rv = po.returncode
d1681e
-                        if gconf.label == 'slave' \
d1681e
-                           and not boolify(gconf.slave_access_mount):
d1681e
+                            logging.debug("Lazy umount done: %s" % mntpt)
d1681e
+                        if umount_master or umount_slave:
d1681e
                             self.cleanup_mntpt(mntpt)
d1681e
                 except:
d1681e
                     logging.exception('mount cleanup failure:')
d1681e
diff --git a/geo-replication/syncdaemon/syncdutils.py b/geo-replication/syncdaemon/syncdutils.py
d1681e
index a493c37..6dafb0a 100644
d1681e
--- a/geo-replication/syncdaemon/syncdutils.py
d1681e
+++ b/geo-replication/syncdaemon/syncdutils.py
d1681e
@@ -76,6 +76,7 @@ CHANGELOG_AGENT_SERVER_VERSION = 1.0
d1681e
 CHANGELOG_AGENT_CLIENT_VERSION = 1.0
d1681e
 NodeID = None
d1681e
 rsync_version = None
d1681e
+unshare_mnt_propagation = None
d1681e
 SPACE_ESCAPE_CHAR = "%20"
d1681e
 NEWLINE_ESCAPE_CHAR = "%0A"
d1681e
 PERCENTAGE_ESCAPE_CHAR = "%25"
d1681e
@@ -637,6 +638,23 @@ def get_master_and_slave_data_from_args(args):
d1681e
     return (master_name, slave_data)
d1681e
 
d1681e
 
d1681e
+def unshare_propagation_supported():
d1681e
+    global unshare_mnt_propagation
d1681e
+    if unshare_mnt_propagation is not None:
d1681e
+        return unshare_mnt_propagation
d1681e
+
d1681e
+    unshare_mnt_propagation = False
d1681e
+    p = subprocess.Popen(["unshare", "--help"],
d1681e
+                         stderr=subprocess.PIPE,
d1681e
+                         stdout=subprocess.PIPE)
d1681e
+    out, err = p.communicate()
d1681e
+    if p.returncode == 0:
d1681e
+        if "propagation" in out:
d1681e
+            unshare_mnt_propagation = True
d1681e
+
d1681e
+    return unshare_mnt_propagation
d1681e
+
d1681e
+
d1681e
 def get_rsync_version(rsync_cmd):
d1681e
     global rsync_version
d1681e
     if rsync_version is not None:
d1681e
-- 
d1681e
1.8.3.1
d1681e