cgroupv2: rm legacy Paths from systemd driver
Having map of per-subsystem paths in systemd unified cgroups driver does not make sense and makes the code less readable. To get rid of it, move the systemd v1-or-v2 init code to libcontainer/factory_linux.go which already has a function to deduce unified path out of paths map. End result is much cleaner code. Besides, we no longer write pid to the same cgroup file 7 times in Apply() like we did before. While at it - add `rootless` flag which is passed on to fs2 manager - merge getv2Path() into GetUnifiedPath(), don't overwrite path if it is set during initialization (on Load). Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
parent
480bca91be
commit
9c80cd672d
|
@ -102,26 +102,6 @@ func getDbusConnection() (*systemdDbus.Conn, error) {
|
||||||
return connDbus, connErr
|
return connDbus, connErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSystemdCgroupsManager() (func(config *configs.Cgroup, paths map[string]string) cgroups.Manager, error) {
|
|
||||||
if !IsRunningSystemd() {
|
|
||||||
return nil, fmt.Errorf("systemd not running on this host, can't use systemd as a cgroups.Manager")
|
|
||||||
}
|
|
||||||
if cgroups.IsCgroup2UnifiedMode() {
|
|
||||||
return func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
|
||||||
return &UnifiedManager{
|
|
||||||
Cgroups: config,
|
|
||||||
Paths: paths,
|
|
||||||
}
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
return func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
|
||||||
return &LegacyManager{
|
|
||||||
Cgroups: config,
|
|
||||||
Paths: paths,
|
|
||||||
}
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *LegacyManager) Apply(pid int) error {
|
func (m *LegacyManager) Apply(pid int) error {
|
||||||
var (
|
var (
|
||||||
c = m.Cgroups
|
c = m.Cgroups
|
||||||
|
|
|
@ -16,14 +16,23 @@ import (
|
||||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||||
"github.com/opencontainers/runc/libcontainer/cgroups/fs2"
|
"github.com/opencontainers/runc/libcontainer/cgroups/fs2"
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UnifiedManager struct {
|
type UnifiedManager struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
Cgroups *configs.Cgroup
|
Cgroups *configs.Cgroup
|
||||||
Paths map[string]string
|
// path is like "/sys/fs/cgroup/user.slice/user-1001.slice/session-1.scope"
|
||||||
|
path string
|
||||||
|
rootless bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUnifiedManager(config *configs.Cgroup, path string, rootless bool) *UnifiedManager {
|
||||||
|
return &UnifiedManager{
|
||||||
|
Cgroups: config,
|
||||||
|
path: path,
|
||||||
|
rootless: rootless,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UnifiedManager) Apply(pid int) error {
|
func (m *UnifiedManager) Apply(pid int) error {
|
||||||
|
@ -35,12 +44,7 @@ func (m *UnifiedManager) Apply(pid int) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.Paths != nil {
|
if c.Paths != nil {
|
||||||
paths := make(map[string]string)
|
return cgroups.WriteCgroupProc(m.path, pid)
|
||||||
for name, path := range c.Paths {
|
|
||||||
paths[name] = path
|
|
||||||
}
|
|
||||||
m.Paths = paths
|
|
||||||
return cgroups.EnterPid(m.Paths, pid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Parent != "" {
|
if c.Parent != "" {
|
||||||
|
@ -144,22 +148,13 @@ func (m *UnifiedManager) Apply(pid int) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
path, err := getv2Path(m.Cgroups)
|
_, err = m.GetUnifiedPath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := createCgroupsv2Path(path); err != nil {
|
if err := createCgroupsv2Path(m.path); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.Paths = map[string]string{
|
|
||||||
"pids": path,
|
|
||||||
"memory": path,
|
|
||||||
"io": path,
|
|
||||||
"cpu": path,
|
|
||||||
"devices": path,
|
|
||||||
"cpuset": path,
|
|
||||||
"freezer": path,
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,39 +170,39 @@ func (m *UnifiedManager) Destroy() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dbusConnection.StopUnit(getUnitName(m.Cgroups), "replace", nil)
|
dbusConnection.StopUnit(getUnitName(m.Cgroups), "replace", nil)
|
||||||
if err := cgroups.RemovePaths(m.Paths); err != nil {
|
|
||||||
|
// XXX this is probably not needed, systemd should handle it
|
||||||
|
err = os.Remove(m.path)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.Paths = make(map[string]string)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this method is for v1 backward compatibility and will be removed
|
||||||
func (m *UnifiedManager) GetPaths() map[string]string {
|
func (m *UnifiedManager) GetPaths() map[string]string {
|
||||||
m.mu.Lock()
|
_, _ = m.GetUnifiedPath()
|
||||||
paths := m.Paths
|
paths := map[string]string{
|
||||||
m.mu.Unlock()
|
"pids": m.path,
|
||||||
|
"memory": m.path,
|
||||||
|
"io": m.path,
|
||||||
|
"cpu": m.path,
|
||||||
|
"devices": m.path,
|
||||||
|
"cpuset": m.path,
|
||||||
|
"freezer": m.path,
|
||||||
|
}
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UnifiedManager) GetUnifiedPath() (string, error) {
|
func (m *UnifiedManager) GetUnifiedPath() (string, error) {
|
||||||
unifiedPath := ""
|
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
for k, v := range m.Paths {
|
if m.path != "" {
|
||||||
if unifiedPath == "" {
|
return m.path, nil
|
||||||
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 getv2Path(c *configs.Cgroup) (string, error) {
|
c := m.Cgroups
|
||||||
slice := "system.slice"
|
slice := "system.slice"
|
||||||
if c.Parent != "" {
|
if c.Parent != "" {
|
||||||
slice = c.Parent
|
slice = c.Parent
|
||||||
|
@ -218,7 +213,8 @@ func getv2Path(c *configs.Cgroup) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Join(fs2.UnifiedMountpoint, slice, getUnitName(c)), nil
|
m.path = filepath.Join(fs2.UnifiedMountpoint, slice, getUnitName(c))
|
||||||
|
return m.path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createCgroupsv2Path(path string) (Err error) {
|
func createCgroupsv2Path(path string) (Err error) {
|
||||||
|
@ -263,7 +259,7 @@ func (m *UnifiedManager) fsManager() (cgroups.Manager, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return fs2.NewManager(m.Cgroups, path, false)
|
return fs2.NewManager(m.Cgroups, path, m.rootless)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UnifiedManager) Freeze(state configs.FreezerState) error {
|
func (m *UnifiedManager) Freeze(state configs.FreezerState) error {
|
||||||
|
|
|
@ -50,17 +50,6 @@ func InitArgs(args ...string) func(*LinuxFactory) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SystemdCgroups is an options func to configure a LinuxFactory to return
|
|
||||||
// containers that use systemd to create and manage cgroups.
|
|
||||||
func SystemdCgroups(l *LinuxFactory) error {
|
|
||||||
systemdCgroupsManager, err := systemd.NewSystemdCgroupsManager()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
l.NewCgroupsManager = systemdCgroupsManager
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUnifiedPath(paths map[string]string) string {
|
func getUnifiedPath(paths map[string]string) string {
|
||||||
unifiedPath := ""
|
unifiedPath := ""
|
||||||
for k, v := range paths {
|
for k, v := range paths {
|
||||||
|
@ -74,6 +63,34 @@ func getUnifiedPath(paths map[string]string) string {
|
||||||
return unifiedPath
|
return unifiedPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func systemdCgroupV2(l *LinuxFactory, rootless bool) error {
|
||||||
|
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
||||||
|
return systemd.NewUnifiedManager(config, getUnifiedPath(paths), rootless)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SystemdCgroups is an options func to configure a LinuxFactory to return
|
||||||
|
// containers that use systemd to create and manage cgroups.
|
||||||
|
func SystemdCgroups(l *LinuxFactory) error {
|
||||||
|
if !systemd.IsRunningSystemd() {
|
||||||
|
return fmt.Errorf("systemd not running on this host, can't use systemd as cgroups manager")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cgroups.IsCgroup2UnifiedMode() {
|
||||||
|
return systemdCgroupV2(l, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
||||||
|
return &systemd.LegacyManager{
|
||||||
|
Cgroups: config,
|
||||||
|
Paths: paths,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func cgroupfs2(l *LinuxFactory, rootless bool) error {
|
func cgroupfs2(l *LinuxFactory, rootless bool) error {
|
||||||
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
||||||
m, err := fs2.NewManager(config, getUnifiedPath(paths), rootless)
|
m, err := fs2.NewManager(config, getUnifiedPath(paths), rootless)
|
||||||
|
|
Loading…
Reference in New Issue