Blob Blame History Raw
From 77d79754d914ce7d15d02d5fc9d9785609094850 Mon Sep 17 00:00:00 2001
From: Kotresh HR <khiremat@redhat.com>
Date: Thu, 7 Jun 2018 06:32:36 -0400
Subject: [PATCH 305/305] geo-rep: Fix geo-rep for older versions of unshare

Geo-rep mounts are private to worker. It uses
mount namespace using unshare command to achieve
the same. Well, the unshare command has to support
'--propagation' option. So geo-rep breaks on the
systems with older unshare version. The patch
makes it fall back to lazy umount behaviour if
the unshare does not support propagation option.

Backpor of:
  > Patch: https://review.gluster.org/20221
  > fixes: bz#1589782
  > Change-Id: Ia614f068aede288d63ac62fea4461b1865066054
  > Signed-off-by: Kotresh HR <khiremat@redhat.com>

BUG: 1569312
Change-Id: Ia614f068aede288d63ac62fea4461b1865066054
Signed-off-by: Kotresh HR <khiremat@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/142613
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Aravinda Vishwanathapura Krishna Murthy <avishwan@redhat.com>
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
---
 geo-replication/syncdaemon/gsyncd.py     |  1 +
 geo-replication/syncdaemon/monitor.py    | 15 +++++++++++----
 geo-replication/syncdaemon/resource.py   | 21 ++++++++++++++++++---
 geo-replication/syncdaemon/syncdutils.py | 18 ++++++++++++++++++
 4 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py
index b0ed0ae..fff193b 100644
--- a/geo-replication/syncdaemon/gsyncd.py
+++ b/geo-replication/syncdaemon/gsyncd.py
@@ -775,6 +775,7 @@ def main_i():
     elif remote:
         # master
         gconf.label = gconf.local_path
+        gconf.worker = True
     else:
         gconf.label = 'slave'
     startup(go_daemon=go_daemon, log_file=log_file, label=gconf.label)
diff --git a/geo-replication/syncdaemon/monitor.py b/geo-replication/syncdaemon/monitor.py
index 55f8330..9245572 100644
--- a/geo-replication/syncdaemon/monitor.py
+++ b/geo-replication/syncdaemon/monitor.py
@@ -29,7 +29,7 @@ from syncdutils import gf_event, EVENT_GEOREP_FAULTY
 from syncdutils import Volinfo, Popen
 
 from gsyncdstatus import GeorepStatus, set_monitor_status
-
+from syncdutils import unshare_propagation_supported
 
 ParseError = XET.ParseError if hasattr(XET, 'ParseError') else SyntaxError
 
@@ -247,9 +247,16 @@ class Monitor(object):
                 if access_mount:
                     os.execv(sys.executable, args_to_worker)
                 else:
-                    unshare_cmd = ['unshare', '-m', '--propagation', 'private']
-                    cmd = unshare_cmd + args_to_worker
-                    os.execvp("unshare", cmd)
+                    if unshare_propagation_supported():
+                        logging.debug("Worker would mount volume privately")
+                        unshare_cmd = ['unshare', '-m', '--propagation',
+                                       'private']
+                        cmd = unshare_cmd + args_to_worker
+                        os.execvp("unshare", cmd)
+                    else:
+                        logging.debug("Mount is not private. It would be lazy"
+                                      " umounted")
+                        os.execv(sys.executable, args_to_worker)
 
             cpids.add(cpid)
             agents.add(apid)
diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py
index c4b5b53..00e62b7 100644
--- a/geo-replication/syncdaemon/resource.py
+++ b/geo-replication/syncdaemon/resource.py
@@ -40,6 +40,7 @@ from gsyncdstatus import GeorepStatus
 from syncdutils import get_master_and_slave_data_from_args
 from syncdutils import lf, Popen, sup, Volinfo
 from syncdutils import Xattr, matching_disk_gfid, get_gfid_from_mnt
+from syncdutils import unshare_propagation_supported
 
 UrlRX = re.compile('\A(\w+)://([^ *?[]*)\Z')
 HostRX = re.compile('[a-zA-Z\d](?:[a-zA-Z\d.-]*[a-zA-Z\d])?', re.I)
@@ -1302,15 +1303,29 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote):
                         assert(mntdata[-1] == '\0')
                         mntpt = mntdata[:-1]
                         assert(mntpt)
-                        if mounted and gconf.label == 'slave' \
+
+                        umount_master = False
+                        umount_slave = False
+                        master_access_mount = getattr(gconf, 'access_mount',
+                                                      False)
+                        worker = getattr(gconf, 'worker', None)
+
+                        if worker \
+                           and not unshare_propagation_supported() \
+                           and not boolify(master_access_mount):
+                            umount_master = True
+                        if gconf.label == 'slave' \
                            and not boolify(gconf.slave_access_mount):
+                            umount_slave = True
+
+                        if mounted and (umount_master or umount_slave):
                             po = self.umount_l(mntpt)
                             po.terminate_geterr(fail_on_err=False)
                             if po.returncode != 0:
                                 po.errlog()
                                 rv = po.returncode
-                        if gconf.label == 'slave' \
-                           and not boolify(gconf.slave_access_mount):
+                            logging.debug("Lazy umount done: %s" % mntpt)
+                        if umount_master or umount_slave:
                             self.cleanup_mntpt(mntpt)
                 except:
                     logging.exception('mount cleanup failure:')
diff --git a/geo-replication/syncdaemon/syncdutils.py b/geo-replication/syncdaemon/syncdutils.py
index a493c37..6dafb0a 100644
--- a/geo-replication/syncdaemon/syncdutils.py
+++ b/geo-replication/syncdaemon/syncdutils.py
@@ -76,6 +76,7 @@ CHANGELOG_AGENT_SERVER_VERSION = 1.0
 CHANGELOG_AGENT_CLIENT_VERSION = 1.0
 NodeID = None
 rsync_version = None
+unshare_mnt_propagation = None
 SPACE_ESCAPE_CHAR = "%20"
 NEWLINE_ESCAPE_CHAR = "%0A"
 PERCENTAGE_ESCAPE_CHAR = "%25"
@@ -637,6 +638,23 @@ def get_master_and_slave_data_from_args(args):
     return (master_name, slave_data)
 
 
+def unshare_propagation_supported():
+    global unshare_mnt_propagation
+    if unshare_mnt_propagation is not None:
+        return unshare_mnt_propagation
+
+    unshare_mnt_propagation = False
+    p = subprocess.Popen(["unshare", "--help"],
+                         stderr=subprocess.PIPE,
+                         stdout=subprocess.PIPE)
+    out, err = p.communicate()
+    if p.returncode == 0:
+        if "propagation" in out:
+            unshare_mnt_propagation = True
+
+    return unshare_mnt_propagation
+
+
 def get_rsync_version(rsync_cmd):
     global rsync_version
     if rsync_version is not None:
-- 
1.8.3.1