You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2016/08/01 16:06:16 UTC

[2/2] mesos git commit: Updated NvidiaVolume to mount as 'tmpfs' if parent fs is 'noexec'.

Updated NvidiaVolume to mount as 'tmpfs' if parent fs is 'noexec'.

This patch is in response to an issue we ran into on Ubuntu 14.04,
where '/run' is being mounted as 'noexec' (MESOS-5923). Since our
NvidiaVolume is created below this mount point, we are unable to
execute any binaries we add to this volume. This causes problems, for
example, when trying to execute 'nvidia-smi' from within a container
that has this volume mounted in.

To work around this issue, we detect if any mount point above the path
where we create the volume is marked as 'noexec', and if so, we create
a new 'tmpfs' mount for the volume without 'noexec' set.

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


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

Branch: refs/heads/master
Commit: 48a492cd9d7d0a194735b9b4107a35b489c596e1
Parents: ad1f610
Author: Kevin Klues <kl...@gmail.com>
Authored: Mon Aug 1 09:06:07 2016 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Mon Aug 1 09:06:07 2016 -0700

----------------------------------------------------------------------
 .../mesos/isolators/gpu/volume.cpp              | 45 +++++++++++++++++++-
 1 file changed, 43 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/48a492cd/src/slave/containerizer/mesos/isolators/gpu/volume.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/gpu/volume.cpp b/src/slave/containerizer/mesos/isolators/gpu/volume.cpp
index 4d87c11..478e106 100644
--- a/src/slave/containerizer/mesos/isolators/gpu/volume.cpp
+++ b/src/slave/containerizer/mesos/isolators/gpu/volume.cpp
@@ -23,6 +23,7 @@
 
 #include <process/owned.hpp>
 
+#include <stout/adaptor.hpp>
 #include <stout/elf.hpp>
 #include <stout/error.hpp>
 #include <stout/foreach.hpp>
@@ -38,6 +39,7 @@
 #include <stout/os/rmdir.hpp>
 #include <stout/os/shell.hpp>
 
+#include "linux/fs.hpp"
 #include "linux/ldcache.hpp"
 
 #include "slave/containerizer/mesos/isolators/gpu/nvml.hpp"
@@ -222,6 +224,45 @@ Try<NvidiaVolume> NvidiaVolume::create()
     }
   }
 
+  // If the filesystem where we are creating this volume has the
+  // `noexec` bit set, we will not be able to execute any of the
+  // nvidia binaries we place in the volume (e.g. `nvidia-smi`). To
+  // fix this, we mount a `tmpfs` over the volume `hostPath` without
+  // the `noexec` bit set. See MESOS-5923 for more information.
+  Try<fs::MountInfoTable> table = fs::MountInfoTable::read();
+  if (table.isError()) {
+    return Error("Failed to get mount table: " + table.error());
+  }
+
+  Result<string> realpath = os::realpath(hostPath);
+  if (!realpath.isSome()) {
+    return Error("Failed to os::realpath '" + hostPath + "':"
+                 " " + (realpath.isError()
+                        ? realpath.error()
+                        : "No such file or directory"));
+  }
+
+  // Do a reverse search through the list of mounted filesystems to
+  // find the filesystem that is mounted with the longest overlapping
+  // path to our `hostPath` (which may include the `hostPath` itself).
+  // Only mount a new `tmpfs` over the `hostPath` if the filesysem we
+  // find is marked as `noexec`.
+  foreach (const fs::MountInfoTable::Entry& entry,
+           adaptor::reverse(table->entries)) {
+    if (strings::startsWith(realpath.get(), entry.target)) {
+      if (strings::contains(entry.vfsOptions, "noexec")) {
+        Try<Nothing> mnt = fs::mount(
+            "tmpfs", hostPath, "tmpfs", MS_NOSUID | MS_NODEV, "mode=755");
+
+        if (mnt.isError()) {
+          return Error("Failed to mount '" + hostPath + "': " + mnt.error());
+        }
+      }
+
+      break;
+    }
+  }
+
   // Create some directories in the volume if they don't yet exist.
   string directories[] = {"bin", "lib", "lib64" };
   foreach (const string& directory, directories) {
@@ -345,7 +386,7 @@ Try<NvidiaVolume> NvidiaVolume::create()
 
         if (!os::exists(symlinkPath)) {
           Try<Nothing> symlink =
-            fs::symlink(Path(realpath.get()).basename(), symlinkPath);
+            ::fs::symlink(Path(realpath.get()).basename(), symlinkPath);
           if (symlink.isError()) {
             return Error("Failed to fs::symlink"
                          " '" + symlinkPath + "'"
@@ -370,7 +411,7 @@ Try<NvidiaVolume> NvidiaVolume::create()
 
           if (!os::exists(symlinkPath)) {
             Try<Nothing> symlink =
-              fs::symlink(Path(realpath.get()).basename(), symlinkPath);
+              ::fs::symlink(Path(realpath.get()).basename(), symlinkPath);
             if (symlink.isError()) {
               return Error("Failed to fs::symlink"
                            " '" + symlinkPath + "'"