You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jp...@apache.org on 2018/09/05 23:45:35 UTC

[mesos] 03/03: Exposed an XFS helper to find the block device for a given path.

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

commit 6a933e780a2bd835b31c6420ad23d86de94f77ac
Author: James Peach <jp...@apache.org>
AuthorDate: Wed Sep 5 15:11:34 2018 -0700

    Exposed an XFS helper to find the block device for a given path.
    
    To manage persistent volumes in the `disk/xfs` isolator we need
    to keep track of the block device that hosts a given filesystem
    path. Expose the `getDeviceForPath` helper API to directly return
    this information.
    
    Review: https://reviews.apache.org/r/68400/
---
 .../containerizer/mesos/isolators/xfs/utils.cpp    |  8 ++++---
 .../containerizer/mesos/isolators/xfs/utils.hpp    |  6 +++++
 src/tests/containerizer/xfs_quota_tests.cpp        | 27 ++++++++++++++++++----
 3 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/src/slave/containerizer/mesos/isolators/xfs/utils.cpp b/src/slave/containerizer/mesos/isolators/xfs/utils.cpp
index b691c76..d5d0377 100644
--- a/src/slave/containerizer/mesos/isolators/xfs/utils.cpp
+++ b/src/slave/containerizer/mesos/isolators/xfs/utils.cpp
@@ -107,9 +107,7 @@ static Try<struct fsxattr> getAttributes(int fd)
 }
 
 
-// Return the path of the device backing the filesystem containing
-// the given path.
-static Try<string> getDeviceForPath(const string& path)
+Try<string> getDeviceForPath(const string& path)
 {
   struct stat statbuf;
 
@@ -117,6 +115,10 @@ static Try<string> getDeviceForPath(const string& path)
     return ErrnoError("Unable to access '" + path + "'");
   }
 
+  if (S_ISBLK(statbuf.st_mode)) {
+    return path;
+  }
+
   char* name = blkid_devno_to_devname(statbuf.st_dev);
   if (name == nullptr) {
     return ErrnoError("Unable to get device for '" + path + "'");
diff --git a/src/slave/containerizer/mesos/isolators/xfs/utils.hpp b/src/slave/containerizer/mesos/isolators/xfs/utils.hpp
index e269eb5..db1829a 100644
--- a/src/slave/containerizer/mesos/isolators/xfs/utils.hpp
+++ b/src/slave/containerizer/mesos/isolators/xfs/utils.hpp
@@ -98,6 +98,12 @@ bool isPathXfs(const std::string& path);
 Try<bool> isQuotaEnabled(const std::string& path);
 
 
+// Return the path of the block device backing the given path. If the path
+// is a filesystem path, then the corresponding block device is resolved. If
+// the path is already a block device path, then the same path is returned.
+Try<std::string> getDeviceForPath(const std::string& path);
+
+
 Result<QuotaInfo> getProjectQuota(
     const std::string& path,
     prid_t projectId);
diff --git a/src/tests/containerizer/xfs_quota_tests.cpp b/src/tests/containerizer/xfs_quota_tests.cpp
index 59ec182..2b3a2e2 100644
--- a/src/tests/containerizer/xfs_quota_tests.cpp
+++ b/src/tests/containerizer/xfs_quota_tests.cpp
@@ -289,14 +289,18 @@ TEST_F(ROOT_XFS_QuotaTest, QuotaGetSet)
   ASSERT_SOME(os::mkdir(root));
 
   EXPECT_SOME(setProjectQuota(root, projectId, limit));
+  EXPECT_SOME_EQ(
+      makeQuotaInfo(limit, 0 /* used */),
+      getProjectQuota(root, projectId));
 
-  Result<QuotaInfo> info = getProjectQuota(root, projectId);
-  ASSERT_SOME(info);
+  EXPECT_SOME(clearProjectQuota(root, projectId));
 
-  EXPECT_EQ(limit, info->hardLimit);
-  EXPECT_EQ(Bytes(0), info->used);
+  // After we clear the quota, the quota record is removed and we will get
+  // ENOENT trying to read it back.
+  EXPECT_ERROR(getProjectQuota(root, projectId));
 
-  EXPECT_SOME(clearProjectQuota(root, projectId));
+  EXPECT_SOME_EQ(loopDevice, getDeviceForPath(root));
+  EXPECT_SOME_EQ(loopDevice, getDeviceForPath(loopDevice.get()));
 }
 
 
@@ -328,6 +332,19 @@ TEST_F(ROOT_XFS_QuotaTest, QuotaLimit)
   EXPECT_ERROR(mkfile(path::join(root, "file2"), Megabytes(2)));
 
   EXPECT_SOME(clearProjectQuota(root, projectId));
+
+  // Since this project ID still consumes space, there should still
+  // be a quota record. However, the limits should be cleared.
+  Result<QuotaInfo> info = getProjectQuota(root, projectId);
+  ASSERT_SOME(info);
+
+  EXPECT_EQ(Bytes(0), info->softLimit);
+  EXPECT_EQ(Bytes(0), info->hardLimit);
+
+  // We use LE here because we know that the 10MB write succeeded but
+  // the 2MB write did not. We could end up using 10MB if the second
+  // write atomically failed, or 11MB if it partially succeeded.
+  EXPECT_LE(used, info->used);
 }