Repository: mesos
Updated Branches:
  refs/heads/master e05922e36 -> 0ab22141f


Used shared bind mount to fix MESOS-1558.

Review: https://reviews.apache.org/r/23246


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/0ab22141
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/0ab22141
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/0ab22141

Branch: refs/heads/master
Commit: 0ab22141fc3a29ae7ed0213823db8ff52c9a8860
Parents: e05922e
Author: Jie Yu <yujie....@gmail.com>
Authored: Wed Jul 2 13:53:51 2014 -0700
Committer: Jie Yu <yujie....@gmail.com>
Committed: Wed Jul 2 17:00:03 2014 -0700

----------------------------------------------------------------------
 .../isolators/network/port_mapping.cpp          | 76 ++++++++++++++++++--
 1 file changed, 70 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/0ab22141/src/slave/containerizer/isolators/network/port_mapping.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/isolators/network/port_mapping.cpp 
b/src/slave/containerizer/isolators/network/port_mapping.cpp
index a326653..d16547a 100644
--- a/src/slave/containerizer/isolators/network/port_mapping.cpp
+++ b/src/slave/containerizer/isolators/network/port_mapping.cpp
@@ -709,7 +709,7 @@ Try<Isolator*> PortMappingIsolatorProcess::create(const 
Flags& flags)
   } else if (checkCommandTc.get() != 0) {
     return Error(
         "Check command 'tc' failed: non-zero exit code: " +
-        checkCommandTc.get());
+        stringify(checkCommandTc.get()));
   }
 
   Try<int> checkCommandIp = os::shell(NULL, "ip link show");
@@ -718,7 +718,7 @@ Try<Isolator*> PortMappingIsolatorProcess::create(const 
Flags& flags)
   } else if (checkCommandIp.get() != 0) {
     return Error(
         "Check command 'ip' failed: non-zero exit code: " +
-        checkCommandIp.get());
+        stringify(checkCommandIp.get()));
   }
 
   // Get 'ports' resource from 'resources' flag. These ports will be
@@ -1042,7 +1042,14 @@ Try<Isolator*> PortMappingIsolatorProcess::create(const 
Flags& flags)
         ": " + write.error());
   }
 
-  // Create the bind mount directory.
+  // Self bind mount BIND_MOUNT_ROOT. Since we use a new mount
+  // namespace for each container, for this mount point, we set
+  // '--make-rshared' on the host and set '--make-rslave' inside each
+  // container. This is important because when we unmount the network
+  // namespace handles on the host, those handles will be unmounted in
+  // the containers as well, but NOT vice versa.
+
+  // We first create the bind mount directory if it does not exist.
   Try<Nothing> mkdir = os::mkdir(BIND_MOUNT_ROOT);
   if(mkdir.isError()) {
     return Error(
@@ -1050,6 +1057,63 @@ Try<Isolator*> PortMappingIsolatorProcess::create(const 
Flags& flags)
         BIND_MOUNT_ROOT + ": " + mkdir.error());
   }
 
+  // Now, check '/proc/mounts' to see if BIND_MOUNT_ROOT has already
+  // been self mounted.
+  Try<fs::MountTable> mountTable = fs::MountTable::read("/proc/mounts");
+  if (mountTable.isError()) {
+    return Error(
+        "Failed to the read the mount table at '/proc/mounts': " +
+        mountTable.error());
+  }
+
+  Option<fs::MountTable::Entry> bindMountRoot;
+  foreach (const fs::MountTable::Entry& entry, mountTable.get().entries) {
+    if (entry.dir == BIND_MOUNT_ROOT) {
+      bindMountRoot = entry;
+    }
+  }
+
+  // Self bind mount BIND_MOUNT_ROOT.
+  if (bindMountRoot.isNone()) {
+    // NOTE: Instead of using fs::mount to perform the bind mount, we
+    // use the shell command here because the syscall 'mount' does not
+    // update the mount table (i.e., /etc/mtab), which could cause
+    // issues for the shell command 'mount --make-rslave' inside the
+    // container. It's OK to use the blocking os::shell here because
+    // 'create' will only be invoked during initialization.
+    Try<int> mount = os::shell(
+        NULL,
+        "mount --bind %s %s",
+        BIND_MOUNT_ROOT.c_str(),
+        BIND_MOUNT_ROOT.c_str());
+
+    if (mount.isError()) {
+      return Error(
+          "Failed to self bind mount '" + BIND_MOUNT_ROOT +
+          "': " + mount.error());
+    } else if (mount.get() != 0) {
+      return Error(
+          "Failed to self bind mount '" + BIND_MOUNT_ROOT +
+          "': non-zero exit code: " + stringify(mount.get()));
+    }
+  }
+
+  // Mark the mount point BIND_MOUNT_ROOT as recursively shared.
+  Try<int> mountShared = os::shell(
+      NULL,
+      "mount --make-rshared %s",
+      BIND_MOUNT_ROOT.c_str());
+
+  if (mountShared.isError()) {
+    return Error(
+        "Failed to mark '" + BIND_MOUNT_ROOT + "' as recursively shared: " +
+        mountShared.error());
+  } else if (mountShared.get() != 0) {
+    return Error(
+        "Failed to mark '" + BIND_MOUNT_ROOT + "' as recursively shared: " +
+        "non-zero exit code: " + stringify(mountShared.get()));
+  }
+
   return new Isolator(Owned<IsolatorProcess>(
       new PortMappingIsolatorProcess(
           flags,
@@ -1962,9 +2026,9 @@ string PortMappingIsolatorProcess::scripts(Info* info)
   script << "mount -n -o remount -t sysfs none /sys\n";
   script << "mount -n -o remount -t proc none /proc\n";
 
-  // Umount all the mount objects in BIND_MOUNT_ROOT inside child to
-  // clear reference counts to the mount namespace.
-  script << "umount " << BIND_MOUNT_ROOT << "/*\n";
+  // Mark the mount point BIND_MOUNT_ROOT as slave mount so that
+  // changes in the container will not be propagated to the host.
+  script << "mount --make-rslave " << BIND_MOUNT_ROOT << "\n";
 
   // Configure lo and eth0.
   script << "ip link set " << lo << " address " << hostMAC

Reply via email to