diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationParserCgroupV2.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationParserCgroupV2.cs index 061b1111548..2b5d968b494 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationParserCgroupV2.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationParserCgroupV2.cs @@ -217,6 +217,12 @@ public ulong GetAvailableMemoryInBytes() _fileSystem.ReadAll(_memoryLimitInBytes, bufferWriter.Buffer); ReadOnlySpan memoryBuffer = bufferWriter.Buffer.WrittenSpan; + + if (memoryBuffer.Equals("max\n", StringComparison.InvariantCulture)) + { + return GetHostAvailableMemory(); + } + _ = GetNextNumber(memoryBuffer, out maybeMemory); if (maybeMemory == -1) @@ -497,7 +503,13 @@ private static bool TryGetCpuUnitsFromCgroups(IFileSystem fileSystem, out float return false; } - int nextQuota = GetNextNumber(quotaBuffer, out long quota); + if (quotaBuffer.StartsWith("max", StringComparison.InvariantCulture)) + { + cpuUnits = 0; + return false; + } + + _ = GetNextNumber(quotaBuffer, out long quota); if (quota == -1) { diff --git a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxUtilizationParserCgroupV2Tests.cs b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxUtilizationParserCgroupV2Tests.cs index 0df5c1caca5..bea6ebf5c5a 100644 --- a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxUtilizationParserCgroupV2Tests.cs +++ b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxUtilizationParserCgroupV2Tests.cs @@ -118,6 +118,23 @@ public void When_Calling_GetMemoryUsageInBytes_Parser_Throws_When_UsageInBytes_D Assert.Contains("/sys/fs/cgroup/memory.current", r.Message); } + [ConditionalTheory] + [InlineData("max\n", 134_796_910_592ul)] + [InlineData("1000000\n", 1_000_000ul)] + public void When_Calling_GetAvailableMemoryInBytes_Parser_Returns_Available_Memory(string content, ulong expectedResult) + { + var f = new HardcodedValueFileSystem(new Dictionary + { + { new FileInfo("/sys/fs/cgroup/memory.max"), content }, + { new FileInfo("/proc/meminfo"), "MemTotal: 131637608 kB" } + }); + + var p = new LinuxUtilizationParserCgroupV2(f, new FakeUserHz(100)); + var result = p.GetAvailableMemoryInBytes(); + + Assert.Equal(expectedResult, result); + } + [ConditionalTheory] [InlineData("Suspicious12312312")] [InlineData("string@")] @@ -257,6 +274,21 @@ public void When_No_Cgroup_Cpu_Limits_Are_Not_Set_We_Get_Available_Cpus_From_Cpu Assert.Equal(result, cpus); } + [ConditionalFact] + public void When_Cpu_Max_Is_Set_To_Max_We_Get_Available_Cpus_From_CpuSetCpus() + { + var f = new HardcodedValueFileSystem(new Dictionary + { + { new FileInfo("/sys/fs/cgroup/cpuset.cpus.effective"), "0,1,2" }, + { new FileInfo("/sys/fs/cgroup/cpu.max"), "max 100000" }, + }); + + var p = new LinuxUtilizationParserCgroupV2(f, new FakeUserHz(100)); + var cpus = p.GetCgroupLimitedCpus(); + + Assert.Equal(3, cpus); + } + [ConditionalTheory] [InlineData("-11")] [InlineData("0-")]