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

bmahler 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 dc0bf98fd [cgroups2] Introduce API to set soft memory protection.
dc0bf98fd is described below

commit dc0bf98fdd1dfebd5435847c3fc1b9fa11fce724
Author: Devin Leamy <[email protected]>
AuthorDate: Tue Apr 16 15:47:02 2024 -0400

    [cgroups2] Introduce API to set soft memory protection.
    
    The 'memory.low' control is for soft memory protection. This only
    applies when the system is trying to reclaim memory. Soft memory
    protection means that the kernel will do its best to not reclaim
    memory from the cgroup if its usage is below the value in 'memory.low'.
    Before it reclaims any memory below the value in 'memory.low' it will
    first reclaim unprotected memory from other cgroups.
    
    We introduce `cgroups2::memory::low` and `cgroups2::memory::set_low`
    to set and get this soft memory protection limit.
---
 src/linux/cgroups2.cpp                     | 18 ++++++++++++++++++
 src/linux/cgroups2.hpp                     | 21 +++++++++++++++++++++
 src/tests/containerizer/cgroups2_tests.cpp | 18 ++++++++++++++++++
 3 files changed, 57 insertions(+)

diff --git a/src/linux/cgroups2.cpp b/src/linux/cgroups2.cpp
index f9912564b..2ae459853 100644
--- a/src/linux/cgroups2.cpp
+++ b/src/linux/cgroups2.cpp
@@ -795,6 +795,7 @@ Result<Bytes> parse_bytelimit(const string& value)
 namespace control {
 
 const string CURRENT = "memory.current";
+const string LOW = "memory.low";
 const string MAX = "memory.max";
 const string MIN = "memory.min";
 
@@ -812,6 +813,23 @@ Try<Bytes> usage(const string& cgroup)
 }
 
 
+Try<Nothing> set_low(const string& cgroup, const Bytes& bytes)
+{
+  return cgroups2::write(cgroup, control::LOW, bytes.bytes());
+}
+
+
+Try<Bytes> low(const string& cgroup)
+{
+  Try<uint64_t> contents = cgroups2::read<uint64_t>(cgroup, control::LOW);
+  if (contents.isError()) {
+    return Error("Failed to read 'memory.low': " + contents.error());
+  }
+
+  return Bytes(*contents);
+}
+
+
 Try<Nothing> set_min(const string& cgroup, const Bytes& bytes)
 {
   return cgroups2::write(cgroup, control::MIN, bytes.bytes());
diff --git a/src/linux/cgroups2.hpp b/src/linux/cgroups2.hpp
index e87ea0113..86959aae7 100644
--- a/src/linux/cgroups2.hpp
+++ b/src/linux/cgroups2.hpp
@@ -245,6 +245,27 @@ namespace memory {
 Try<Bytes> usage(const std::string& cgroup);
 
 
+// Set the best-effort memory protection for a cgroup and its descendants. If
+// there is memory contention and this cgroup is within the 'low' threshold,
+// then memory will be reclaimed from other cgroups (without memory protection)
+// before reclaiming from this cgroup.
+//
+// Note: See the top-level `cgroups2::memory` comment about byte alignment and
+//       hierarchical restrictions.
+//
+// Cannot be used for the root cgroup.
+Try<Nothing> set_low(const std::string& cgroup, const Bytes& bytes);
+
+
+// Get the best-effort memory protection for a cgroup and its descendants. If
+// there is memory contention and this cgroup is within the 'low' threshold,
+// then memory will be reclaimed from other cgroups (without memory protection)
+// before reclaiming from this cgroup.
+//
+// Cannot be used for the root cgroup.
+Try<Bytes> low(const std::string& cgroup);
+
+
 // Set the minimum memory that is guaranteed to not be reclaimed under any
 // conditions.
 //
diff --git a/src/tests/containerizer/cgroups2_tests.cpp 
b/src/tests/containerizer/cgroups2_tests.cpp
index 221f612a8..6c8156a63 100644
--- a/src/tests/containerizer/cgroups2_tests.cpp
+++ b/src/tests/containerizer/cgroups2_tests.cpp
@@ -326,6 +326,24 @@ TEST_F(Cgroups2Test, ROOT_CGROUPS2_MemoryUsage)
 }
 
 
+TEST_F(Cgroups2Test, ROOT_CGROUPS2_MemoryLow)
+{
+  ASSERT_SOME(enable_controllers({"memory"}));
+
+  ASSERT_SOME(cgroups2::create(TEST_CGROUP));
+  ASSERT_SOME(cgroups2::controllers::enable(TEST_CGROUP, {"memory"}));
+
+  const Bytes bytes = Bytes(os::pagesize()) * 5;
+
+  // Does not exist for the root cgroup.
+  EXPECT_ERROR(cgroups2::memory::low(cgroups2::ROOT_CGROUP));
+  EXPECT_ERROR(cgroups2::memory::set_low(cgroups2::ROOT_CGROUP, bytes));
+
+  EXPECT_SOME(cgroups2::memory::set_low(TEST_CGROUP, bytes));
+  EXPECT_SOME_EQ(bytes, cgroups2::memory::low(TEST_CGROUP));
+}
+
+
 TEST_F(Cgroups2Test, ROOT_CGROUPS2_MemoryMinimum)
 {
   ASSERT_SOME(enable_controllers({"memory"}));

Reply via email to