Skip to content

Commit

Permalink
stats: get mem limit from the cgroup
Browse files Browse the repository at this point in the history
b25b330 introduced this behaviour.

It was fine at the time because we didn't support "container update",
so the limit could not be changed at runtime.  Since it is not
possible to change the memory limit at runtime, read the limit as
reported from the cgroup.

containers/crun#1217 is required for crun.

Closes: containers#18621

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed May 19, 2023
1 parent a58ea23 commit 7c53a46
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 10 deletions.
12 changes: 2 additions & 10 deletions libpod/stats_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package libpod

import (
"fmt"
"math"
"strings"
"syscall"
"time"
Expand Down Expand Up @@ -59,7 +58,7 @@ func (c *Container) getPlatformContainerStats(stats *define.ContainerStats, prev
// calc the average cpu usage for the time the container is running
stats.AvgCPU = calculateCPUPercent(cgroupStats, 0, now, uint64(c.state.StartedTime.UnixNano()))
stats.MemUsage = cgroupStats.MemoryStats.Usage.Usage
stats.MemLimit = c.getMemLimit()
stats.MemLimit = c.getMemLimit(cgroupStats.MemoryStats.Usage.Limit)
stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100
stats.PIDs = 0
if conState == define.ContainerStateRunning || conState == define.ContainerStatePaused {
Expand All @@ -83,14 +82,7 @@ func (c *Container) getPlatformContainerStats(stats *define.ContainerStats, prev
}

// getMemory limit returns the memory limit for a container
func (c *Container) getMemLimit() uint64 {
memLimit := uint64(math.MaxUint64)

resources := c.LinuxResources()
if resources != nil && resources.Memory != nil && resources.Memory.Limit != nil {
memLimit = uint64(*resources.Memory.Limit)
}

func (c *Container) getMemLimit(memLimit uint64) uint64 {
si := &syscall.Sysinfo_t{}
err := syscall.Sysinfo(si)
if err != nil {
Expand Down
35 changes: 35 additions & 0 deletions test/e2e/stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package integration
import (
"fmt"
"strconv"
"strings"
"time"

. "github.com/containers/podman/v4/test/utils"
Expand Down Expand Up @@ -181,6 +182,9 @@ var _ = Describe("Podman stats", func() {

// Regression test for #8265
It("podman stats with custom memory limits", func() {
if strings.Contains(podmanTest.OCIRuntime, "crun") {
Skip("Test requires crun > 1.8.4")
}
// Run three containers. One with a memory limit. Make sure
// that the limits are different and the limited one has a
// lower limit.
Expand Down Expand Up @@ -229,4 +233,35 @@ var _ = Describe("Podman stats", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
})

It("podman stats show cgroup memory limit", func() {
if strings.Contains(podmanTest.OCIRuntime, "crun") {
Skip("Test requires crun > 1.8.4")
}
ctrWithLimit := "with-limit"

session := podmanTest.Podman([]string{"run", "-d", "--name", ctrWithLimit, "--memory", "50m", ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

session = podmanTest.Podman([]string{"stats", "--no-stream", "--format", "{{.MemLimit}}", ctrWithLimit})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

limit, err := strconv.Atoi(session.OutputToString())
Expect(err).ToNot(HaveOccurred())
Expect(limit).To(BeNumerically("==", 50*1024*1024))

session = podmanTest.Podman([]string{"container", "update", ctrWithLimit, "--memory", "100m"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

session = podmanTest.Podman([]string{"stats", "--no-stream", "--format", "{{.MemLimit}}", ctrWithLimit})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

limit, err = strconv.Atoi(session.OutputToString())
Expect(err).ToNot(HaveOccurred())
Expect(limit).To(BeNumerically("==", 100*1024*1024))
})
})

0 comments on commit 7c53a46

Please sign in to comment.