cgroup2: implement `runc ps`

Implemented `runc ps` for cgroup v2 , using a newly added method `m.GetUnifiedPath()`.
Unlike the v1  implementation that checks `m.GetPaths()["devices"]`, the v2 implementation does not require the device controller to be available.

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
Akihiro Suda 2019-10-19 01:40:46 +09:00
parent f017e0f9e1
commit dbd771e475
6 changed files with 76 additions and 3 deletions

View File

@ -37,6 +37,13 @@ type Manager interface {
// restore the object later. // restore the object later.
GetPaths() map[string]string GetPaths() map[string]string
// GetUnifiedPath returns the unified path when running in unified mode.
// The value corresponds to the all values of GetPaths() map.
//
// GetUnifiedPath returns error when running in hybrid mode as well as
// in legacy mode.
GetUnifiedPath() (string, error)
// Sets the cgroup as configured. // Sets the cgroup as configured.
Set(container *configs.Config) error Set(container *configs.Config) error
} }

View File

@ -224,6 +224,28 @@ func (m *Manager) GetPaths() map[string]string {
return paths return paths
} }
func (m *Manager) GetUnifiedPath() (string, error) {
if !cgroups.IsCgroup2UnifiedMode() {
return "", errors.New("unified path is only supported when running in unified mode")
}
unifiedPath := ""
m.mu.Lock()
defer m.mu.Unlock()
for k, v := range m.Paths {
if unifiedPath == "" {
unifiedPath = v
} else if v != unifiedPath {
return unifiedPath,
errors.Errorf("expected %q path to be unified path %q, got %q", k, unifiedPath, v)
}
}
if unifiedPath == "" {
// FIXME: unified path could be detected even when no controller is available
return unifiedPath, errors.New("cannot detect unified path")
}
return unifiedPath, nil
}
func (m *Manager) GetStats() (*cgroups.Stats, error) { func (m *Manager) GetStats() (*cgroups.Stats, error) {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
@ -302,11 +324,25 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
} }
func (m *Manager) GetPids() ([]int, error) { func (m *Manager) GetPids() ([]int, error) {
if cgroups.IsCgroup2UnifiedMode() {
path, err := m.GetUnifiedPath()
if err != nil {
return nil, err
}
return cgroups.GetPids(path)
}
paths := m.GetPaths() paths := m.GetPaths()
return cgroups.GetPids(paths["devices"]) return cgroups.GetPids(paths["devices"])
} }
func (m *Manager) GetAllPids() ([]int, error) { func (m *Manager) GetAllPids() ([]int, error) {
if cgroups.IsCgroup2UnifiedMode() {
path, err := m.GetUnifiedPath()
if err != nil {
return nil, err
}
return cgroups.GetAllPids(path)
}
paths := m.GetPaths() paths := m.GetPaths()
return cgroups.GetAllPids(paths["devices"]) return cgroups.GetAllPids(paths["devices"])
} }

View File

@ -42,6 +42,10 @@ func (m *Manager) GetPaths() map[string]string {
return nil return nil
} }
func (m *Manager) GetUnifiedPath() (string, error) {
return "", fmt.Errorf("Systemd not supported")
}
func (m *Manager) GetStats() (*cgroups.Stats, error) { func (m *Manager) GetStats() (*cgroups.Stats, error) {
return nil, fmt.Errorf("Systemd not supported") return nil, fmt.Errorf("Systemd not supported")
} }

View File

@ -297,6 +297,10 @@ func (m *LegacyManager) GetPaths() map[string]string {
return paths return paths
} }
func (m *LegacyManager) GetUnifiedPath() (string, error) {
return "", errors.New("unified path is only supported when running in unified mode")
}
func join(c *configs.Cgroup, subsystem string, pid int) (string, error) { func join(c *configs.Cgroup, subsystem string, pid int) (string, error) {
path, err := getSubsystemPath(c, subsystem) path, err := getSubsystemPath(c, subsystem)
if err != nil { if err != nil {

View File

@ -16,6 +16,7 @@ import (
"github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/fs" "github.com/opencontainers/runc/libcontainer/cgroups/fs"
"github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -195,7 +196,24 @@ func (m *UnifiedManager) GetPaths() map[string]string {
m.mu.Unlock() m.mu.Unlock()
return paths return paths
} }
func (m *UnifiedManager) GetUnifiedPath() (string, error) {
unifiedPath := ""
m.mu.Lock()
defer m.mu.Unlock()
for k, v := range m.Paths {
if unifiedPath == "" {
unifiedPath = v
} else if v != unifiedPath {
return unifiedPath,
errors.Errorf("expected %q path to be unified path %q, got %q", k, unifiedPath, v)
}
}
if unifiedPath == "" {
// FIXME: unified path could be detected even when no controller is available
return unifiedPath, errors.New("cannot detect unified path")
}
return unifiedPath, nil
}
func createCgroupsv2Path(path string) (Err error) { func createCgroupsv2Path(path string) (Err error) {
content, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers") content, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers")
if err != nil { if err != nil {
@ -270,7 +288,7 @@ func (m *UnifiedManager) Freeze(state configs.FreezerState) error {
} }
func (m *UnifiedManager) GetPids() ([]int, error) { func (m *UnifiedManager) GetPids() ([]int, error) {
path, err := getSubsystemPath(m.Cgroups, "devices") path, err := m.GetUnifiedPath()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -278,7 +296,7 @@ func (m *UnifiedManager) GetPids() ([]int, error) {
} }
func (m *UnifiedManager) GetAllPids() ([]int, error) { func (m *UnifiedManager) GetAllPids() ([]int, error) {
path, err := getSubsystemPath(m.Cgroups, "devices") path, err := m.GetUnifiedPath()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -54,6 +54,10 @@ func (m *mockCgroupManager) GetPaths() map[string]string {
return m.paths return m.paths
} }
func (m *mockCgroupManager) GetUnifiedPath() (string, error) {
return "", fmt.Errorf("unimplemented")
}
func (m *mockCgroupManager) Freeze(state configs.FreezerState) error { func (m *mockCgroupManager) Freeze(state configs.FreezerState) error {
return nil return nil
} }