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