From a285b4bd1a115e8227f4d520651256eda9949a3f Mon Sep 17 00:00:00 2001 From: "changxin.dong" Date: Fri, 21 Oct 2022 11:41:50 +0800 Subject: [PATCH] feat: linux control group version 2 API support cgroup v2 --- .../unix/linux/CGroupSubSystemPath.java | 73 +++++++++++++++ .../util/platforms/unix/linux/Cgroup.java | 84 ++++------------- .../platforms/unix/linux/CgroupSubSystem.java | 59 +++++++++++- .../unix/linux/CgroupSubSystemV2.java | 91 +++++++++++++------ .../linux/LinuxSystemResourceController.java | 2 +- .../LinuxSystemResourceControllerV2.java | 2 +- 6 files changed, 215 insertions(+), 96 deletions(-) create mode 100644 src/main/java/com/aws/greengrass/util/platforms/unix/linux/CGroupSubSystemPath.java diff --git a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CGroupSubSystemPath.java b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CGroupSubSystemPath.java new file mode 100644 index 0000000000..500fdfd03e --- /dev/null +++ b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CGroupSubSystemPath.java @@ -0,0 +1,73 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.aws.greengrass.util.platforms.unix.linux; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import java.nio.file.Path; +import java.nio.file.Paths; + +@SuppressFBWarnings(value = "DMI_HARDCODED_ABSOLUTE_FILENAME", + justification = "CGroupSubSystemPath virtual filesystem path cannot be relative") +public interface CGroupSubSystemPath { + String CGROUP_ROOT = "/sys/fs/cgroup"; + String GG_NAMESPACE = "greengrass"; + String CGROUP_MEMORY_LIMITS = "memory.limit_in_bytes"; + String CPU_CFS_PERIOD_US = "cpu.cfs_period_us"; + String CPU_CFS_QUOTA_US = "cpu.cfs_quota_us"; + String CGROUP_PROCS = "cgroup.procs"; + String FREEZER_STATE_FILE = "freezer.state"; + String CPU_MAX = "cpu.max"; + String MEMORY_MAX = "memory.max"; + String CGROUP_SUBTREE_CONTROL = "cgroup.subtree_control"; + String CGROUP_FREEZE = "cgroup.freeze"; + + default Path getRootPath() { + return Paths.get(CGROUP_ROOT); + } + + String rootMountCmd(); + + default String subsystemMountCmd() { + return null; + } + + Path getSubsystemRootPath(); + + Path getSubsystemGGPath(); + + Path getSubsystemComponentPath(String componentName); + + Path getComponentMemoryLimitPath(String componentName); + + default Path getComponentCpuPeriodPath(String componentName) { + return null; + } + + default Path getComponentCpuQuotaPath(String componentName) { + return null; + } + + Path getCgroupProcsPath(String componentName); + + Path getCgroupFreezerStateFilePath(String componentName); + + default Path getRootSubTreeControlPath() { + return null; + } + + default Path getGGSubTreeControlPath() { + return null; + } + + default Path getComponentCpuMaxPath(String componentName) { + return null; + } + + default Path getCgroupFreezePath(String componentName) { + return null; + } +} diff --git a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/Cgroup.java b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/Cgroup.java index 0c38eee419..43b877f506 100644 --- a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/Cgroup.java +++ b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/Cgroup.java @@ -5,54 +5,20 @@ package com.aws.greengrass.util.platforms.unix.linux; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import org.apache.commons.lang3.StringUtils; - import java.nio.file.Path; -import java.nio.file.Paths; /** * Represents Linux cgroup subsystems. */ -@SuppressFBWarnings(value = "DMI_HARDCODED_ABSOLUTE_FILENAME", justification = "Cgroup virtual filesystem path " - + "cannot be relative") public class Cgroup { - private static final String CGROUP_ROOT = "/sys/fs/cgroup"; - private static final String GG_NAMESPACE = "greengrass"; - private static final String CGROUP_MEMORY_LIMITS = "memory.limit_in_bytes"; - private static final String CPU_CFS_PERIOD_US = "cpu.cfs_period_us"; - private static final String CPU_CFS_QUOTA_US = "cpu.cfs_quota_us"; - private static final String CGROUP_PROCS = "cgroup.procs"; - private static final String FREEZER_STATE_FILE = "freezer.state"; - private static final String CPU_MAX = "cpu.max"; - private static final String MEMORY_MAX = "memory.max"; - private static final String CGROUP_SUBTREE_CONTROL = "cgroup.subtree_control"; - private static final String CGROUP_FREEZE = "cgroup.freeze"; - - private final String osString; - private final String mountSrc; - - /** - * Cgroup constructor. - * - * @param subSystem subController - */ - public Cgroup(CgroupSubSystem subSystem) { - this.osString = subSystem.getOsString(); - this.mountSrc = subSystem.getMountSrc(); - } + private final CGroupSubSystemPath subSystem; - /** - * Cgroup constructor. - * @param subSystemV2 subsystem version2 - */ - public Cgroup(CgroupSubSystemV2 subSystemV2) { - this.osString = subSystemV2.getOsString(); - this.mountSrc = subSystemV2.getMountSrc(); + public Cgroup(CGroupSubSystemPath subSystem) { + this.subSystem = subSystem; } - public static Path getRootPath() { - return Paths.get(CGROUP_ROOT); + public Path getRootPath() { + return subSystem.getRootPath(); } /** @@ -61,27 +27,23 @@ public static Path getRootPath() { * @return mount command string */ public String rootMountCmd() { - if (StringUtils.isEmpty(osString)) { - return String.format("mount -t cgroup2 none %s", CGROUP_ROOT); - } else { - return String.format("mount -t tmpfs cgroup %s", CGROUP_ROOT); - } + return subSystem.rootMountCmd(); } public String subsystemMountCmd() { - return String.format("mount -t cgroup -o %s %s %s", osString, mountSrc, getSubsystemRootPath()); + return subSystem.subsystemMountCmd(); } public Path getSubsystemRootPath() { - return Paths.get(CGROUP_ROOT).resolve(osString); + return subSystem.getSubsystemRootPath(); } public Path getSubsystemGGPath() { - return getSubsystemRootPath().resolve(GG_NAMESPACE); + return subSystem.getSubsystemGGPath(); } public Path getSubsystemComponentPath(String componentName) { - return getSubsystemGGPath().resolve(componentName); + return subSystem.getSubsystemComponentPath(componentName); } /** @@ -91,23 +53,19 @@ public Path getSubsystemComponentPath(String componentName) { * @return memory limit Path */ public Path getComponentMemoryLimitPath(String componentName) { - if (StringUtils.isEmpty(osString)) { - return getSubsystemComponentPath(componentName).resolve(MEMORY_MAX); - } else { - return getSubsystemComponentPath(componentName).resolve(CGROUP_MEMORY_LIMITS); - } + return subSystem.getComponentMemoryLimitPath(componentName); } public Path getComponentCpuPeriodPath(String componentName) { - return getSubsystemComponentPath(componentName).resolve(CPU_CFS_PERIOD_US); + return subSystem.getComponentCpuPeriodPath(componentName); } public Path getComponentCpuQuotaPath(String componentName) { - return getSubsystemComponentPath(componentName).resolve(CPU_CFS_QUOTA_US); + return subSystem.getComponentCpuQuotaPath(componentName); } public Path getCgroupProcsPath(String componentName) { - return getSubsystemComponentPath(componentName).resolve(CGROUP_PROCS); + return subSystem.getCgroupProcsPath(componentName); } /** @@ -117,27 +75,23 @@ public Path getCgroupProcsPath(String componentName) { * @return cgroup freezer path */ public Path getCgroupFreezerStateFilePath(String componentName) { - if (StringUtils.isEmpty(osString)) { - return getSubsystemComponentPath(componentName).resolve(CGROUP_FREEZE); - } else { - return getSubsystemComponentPath(componentName).resolve(FREEZER_STATE_FILE); - } + return subSystem.getCgroupFreezerStateFilePath(componentName); } public Path getRootSubTreeControlPath() { - return getSubsystemRootPath().resolve(CGROUP_SUBTREE_CONTROL); + return subSystem.getRootSubTreeControlPath(); } public Path getGGSubTreeControlPath() { - return getSubsystemGGPath().resolve(CGROUP_SUBTREE_CONTROL); + return subSystem.getGGSubTreeControlPath(); } public Path getComponentCpuMaxPath(String componentName) { - return getSubsystemComponentPath(componentName).resolve(CPU_MAX); + return subSystem.getComponentCpuMaxPath(componentName); } public Path getCgroupFreezePath(String componentName) { - return getSubsystemComponentPath(componentName).resolve(CGROUP_FREEZE); + return subSystem.getCgroupFreezePath(componentName); } } diff --git a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CgroupSubSystem.java b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CgroupSubSystem.java index c40874030e..6b36dd7c3a 100644 --- a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CgroupSubSystem.java +++ b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CgroupSubSystem.java @@ -5,7 +5,14 @@ package com.aws.greengrass.util.platforms.unix.linux; -public enum CgroupSubSystem { +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import java.nio.file.Path; +import java.nio.file.Paths; + +@SuppressFBWarnings(value = "DMI_HARDCODED_ABSOLUTE_FILENAME", + justification = "CgroupSubSystem virtual filesystem path cannot be relative") +public enum CgroupSubSystem implements CGroupSubSystemPath { Memory("memory", ""), CPU("cpu,cpuacct", ""), Freezer("freezer", "freezer"); private String osString; @@ -33,4 +40,54 @@ public String getOsString() { public String getMountSrc() { return mountSrc; } + + @Override + public String rootMountCmd() { + return String.format("mount -t tmpfs cgroup %s", CGROUP_ROOT); + } + + @Override + public String subsystemMountCmd() { + return String.format("mount -t cgroup -o %s %s %s", osString, mountSrc, getSubsystemRootPath()); + } + + @Override + public Path getSubsystemRootPath() { + return Paths.get(CGROUP_ROOT).resolve(osString); + } + + @Override + public Path getSubsystemGGPath() { + return getSubsystemRootPath().resolve(GG_NAMESPACE); + } + + @Override + public Path getSubsystemComponentPath(String componentName) { + return getSubsystemGGPath().resolve(componentName); + } + + @Override + public Path getComponentMemoryLimitPath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(CGROUP_MEMORY_LIMITS); + } + + @Override + public Path getComponentCpuPeriodPath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(CPU_CFS_PERIOD_US); + } + + @Override + public Path getComponentCpuQuotaPath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(CPU_CFS_QUOTA_US); + } + + @Override + public Path getCgroupProcsPath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(CGROUP_PROCS); + } + + @Override + public Path getCgroupFreezerStateFilePath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(FREEZER_STATE_FILE); + } } diff --git a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CgroupSubSystemV2.java b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CgroupSubSystemV2.java index 1978d052a6..7a3cf1b31e 100644 --- a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CgroupSubSystemV2.java +++ b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/CgroupSubSystemV2.java @@ -5,33 +5,68 @@ package com.aws.greengrass.util.platforms.unix.linux; -public enum CgroupSubSystemV2 { - Memory("", ""), CPU("", ""), Freezer("", ""), - Unified("",""); - - private String osString; - private String mountSrc; - - CgroupSubSystemV2(String osString, String mountSrc) { - this.osString = osString; - this.mountSrc = mountSrc; - } - - /** - * Get the osString associated with this CgroupSubController. - * - * @return the osString associated with this CgroupSubController. - */ - public String getOsString() { - return osString; - } - - /** - * Get the mountSrc associated with this CgroupSubController. - * - * @return the mountSrc associated with this CgroupSubController. - */ - public String getMountSrc() { - return mountSrc; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import java.nio.file.Path; +import java.nio.file.Paths; + +@SuppressFBWarnings(value = "DMI_HARDCODED_ABSOLUTE_FILENAME", + justification = "CgroupSubSystemV2 virtual filesystem path cannot be relative") +public enum CgroupSubSystemV2 implements CGroupSubSystemPath { + Memory, CPU, Freezer, Unified; + + @Override + public String rootMountCmd() { + return String.format("mount -t cgroup2 none %s", CGROUP_ROOT); + } + + @Override + public Path getSubsystemRootPath() { + return Paths.get(CGROUP_ROOT); + } + + @Override + public Path getSubsystemGGPath() { + return getSubsystemRootPath().resolve(GG_NAMESPACE); + } + + @Override + public Path getSubsystemComponentPath(String componentName) { + return getSubsystemGGPath().resolve(componentName); + } + + @Override + public Path getComponentMemoryLimitPath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(MEMORY_MAX); + } + + @Override + public Path getCgroupProcsPath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(CGROUP_PROCS); + } + + @Override + public Path getCgroupFreezerStateFilePath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(CGROUP_FREEZE); + } + + @Override + public Path getRootSubTreeControlPath() { + return getSubsystemRootPath().resolve(CGROUP_SUBTREE_CONTROL); + } + + @Override + public Path getGGSubTreeControlPath() { + return getSubsystemGGPath().resolve(CGROUP_SUBTREE_CONTROL); + } + + @Override + public Path getComponentCpuMaxPath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(CPU_MAX); + } + + @Override + public Path getCgroupFreezePath(String componentName) { + return getSubsystemComponentPath(componentName).resolve(CGROUP_FREEZE); } } diff --git a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/LinuxSystemResourceController.java b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/LinuxSystemResourceController.java index 9447961228..f926b80d84 100644 --- a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/LinuxSystemResourceController.java +++ b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/LinuxSystemResourceController.java @@ -268,7 +268,7 @@ public Set getMountedPaths() throws IOException { protected void initializeCgroup(GreengrassService component, Cgroup cgroup) throws IOException { Set mounts = getMountedPaths(); - if (!mounts.contains(Cgroup.getRootPath().toString())) { + if (!mounts.contains(cgroup.getRootPath().toString())) { platform.runCmd(cgroup.rootMountCmd(), o -> { }, "Failed to mount cgroup root"); Files.createDirectory(cgroup.getSubsystemRootPath()); diff --git a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/LinuxSystemResourceControllerV2.java b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/LinuxSystemResourceControllerV2.java index 564cb5be4b..57a7f52c96 100644 --- a/src/main/java/com/aws/greengrass/util/platforms/unix/linux/LinuxSystemResourceControllerV2.java +++ b/src/main/java/com/aws/greengrass/util/platforms/unix/linux/LinuxSystemResourceControllerV2.java @@ -83,7 +83,7 @@ public void resumeComponentProcesses(GreengrassService component) throws IOExcep protected void initializeCgroup(GreengrassService component, Cgroup cgroup) throws IOException { Set mounts = getMountedPaths(); - if (!mounts.contains(Cgroup.getRootPath().toString())) { + if (!mounts.contains(cgroup.getRootPath().toString())) { platform.runCmd(cgroup.rootMountCmd(), o -> { }, "Failed to mount cgroup root"); Files.createDirectory(cgroup.getSubsystemRootPath());