This is an automated email from the ASF dual-hosted git repository.

jpeach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git


The following commit(s) were added to refs/heads/master by this push:
     new baff4ec  Fixed the XFS project ID labeling to not cross mount points.
baff4ec is described below

commit baff4ec70a1124f58b354cf4003ac26b41bef6a9
Author: James Peach <jpe...@apache.org>
AuthorDate: Mon Oct 15 10:30:22 2018 -0700

    Fixed the XFS project ID labeling to not cross mount points.
    
    If we bind mount a directory on the same filesystem, the fts(3)
    directory traversal that recursively assigns XFS project IDs isn't
    able to detect when it crosses the mount point. This leads it to
    erroneously rewrite the project IDs for persistent volumes if they
    are bind mounted into the container by the `filesystem/linux`
    isolator. The fix is to test whether we crossed a mount point
    whenever we descend into a new directory so that we can avoid
    assigning project ID beneath it.
    
    Review: https://reviews.apache.org/r/68999/
---
 .../containerizer/mesos/isolators/xfs/utils.cpp    | 23 ++++++++++++++++++++++
 src/tests/containerizer/xfs_quota_tests.cpp        |  2 +-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/slave/containerizer/mesos/isolators/xfs/utils.cpp 
b/src/slave/containerizer/mesos/isolators/xfs/utils.cpp
index d5d0377..e67de07 100644
--- a/src/slave/containerizer/mesos/isolators/xfs/utils.cpp
+++ b/src/slave/containerizer/mesos/isolators/xfs/utils.cpp
@@ -356,6 +356,29 @@ static Try<Nothing> setProjectIdRecursively(
 
   for (FTSENT *node = ::fts_read(tree);
        node != nullptr; node = ::fts_read(tree)) {
+    // FTS handles crossing devices (because we use the FTS_XDEV flag), but
+    // doesn't know anything about bind mounts made on the same device. Linux
+    // doesn't have a direct API for detecting whether a vnode is a mount
+    // point, and we prefer to not take the performance cost of looking up
+    // each directory in /proc/mounts. We take advantage of the contract
+    // that the path lookup checks mount crossings before checking whether
+    // the rename is valid. This means that if we attempt an invalid rename
+    // operation (i.e. renaming the parent directory to its child), checking
+    // for EXDEV tells us whether a mount was crossed.
+    //
+    // See http://blog.schmorp.de/2016-03-03-detecting-a-mount-point.html
+    if (node->fts_info == FTS_D && node->fts_level > 0) {
+      CHECK_EQ(-1, ::rename(
+          path::join(node->fts_path, "..").c_str(), node->fts_path));
+
+      // If this is a mount point, don't descend any further. Once we skip,
+      // FTS will not show us any of the files in this directory.
+      if (errno == EXDEV) {
+        ::fts_set(tree, node, FTS_SKIP);
+        continue;
+      }
+    }
+
     if (node->fts_info == FTS_D || node->fts_info == FTS_F) {
       Try<Nothing> status = internal::setProjectId(
           node->fts_path, *node->fts_statp, projectId);
diff --git a/src/tests/containerizer/xfs_quota_tests.cpp 
b/src/tests/containerizer/xfs_quota_tests.cpp
index a615ab1..084df06 100644
--- a/src/tests/containerizer/xfs_quota_tests.cpp
+++ b/src/tests/containerizer/xfs_quota_tests.cpp
@@ -191,7 +191,7 @@ public:
     // We only need an XFS-specific directory for the work directory. We
     // don't mind that other flags refer to a different temp directory.
     flags.work_dir = mountPoint.get();
-    flags.isolation = "disk/xfs";
+    flags.isolation = "disk/xfs,filesystem/linux";
     flags.enforce_container_disk_quota = true;
     return flags;
   }

Reply via email to