Skip to content

Commit ea1823a

Browse files
committed
feat: linux control group version 2 API support cgroup v2
1 parent 7730b18 commit ea1823a

File tree

10 files changed

+502
-61
lines changed

10 files changed

+502
-61
lines changed

src/integrationtests/java/com/aws/greengrass/integrationtests/ipc/IPCHibernateTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.aws.greengrass.testcommons.testutilities.GGExtension;
1111
import com.aws.greengrass.testcommons.testutilities.TestUtils;
1212
import com.aws.greengrass.util.platforms.unix.linux.Cgroup;
13+
import com.aws.greengrass.util.platforms.unix.linux.CgroupSubSystem;
1314
import com.aws.greengrass.util.platforms.unix.linux.LinuxSystemResourceController;
1415
import org.junit.jupiter.api.AfterEach;
1516
import org.junit.jupiter.api.BeforeEach;
@@ -115,7 +116,7 @@ void GIVEN_LifeCycleEventStreamClient_WHEN_pause_resume_component_THEN_target_se
115116
private LinuxSystemResourceController.CgroupFreezerState getCgroupFreezerState(String serviceName)
116117
throws IOException {
117118
return LinuxSystemResourceController.CgroupFreezerState.valueOf(
118-
new String(Files.readAllBytes(Cgroup.Freezer.getCgroupFreezerStateFilePath(serviceName)),
119+
new String(Files.readAllBytes(new Cgroup(CgroupSubSystem.Freezer).getCgroupFreezerStateFilePath(serviceName)),
119120
StandardCharsets.UTF_8).trim());
120121
}
121122
}

src/integrationtests/java/com/aws/greengrass/integrationtests/lifecyclemanager/GenericExternalServiceIntegTest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.aws.greengrass.testcommons.testutilities.NoOpPathOwnershipHandler;
2222
import com.aws.greengrass.util.Pair;
2323
import com.aws.greengrass.util.platforms.unix.linux.Cgroup;
24+
import com.aws.greengrass.util.platforms.unix.linux.CgroupSubSystem;
2425
import com.aws.greengrass.util.platforms.unix.linux.LinuxSystemResourceController;
2526
import org.apache.commons.lang3.SystemUtils;
2627
import org.junit.jupiter.api.AfterEach;
@@ -713,11 +714,11 @@ void GIVEN_service_starts_up_WHEN_startup_times_out_THEN_timeout_error_code_pers
713714
}
714715

715716
private void assertResourceLimits(String componentName, long memory, double cpus) throws Exception {
716-
byte[] buf1 = Files.readAllBytes(Cgroup.Memory.getComponentMemoryLimitPath(componentName));
717+
byte[] buf1 = Files.readAllBytes(new Cgroup(CgroupSubSystem.Memory).getComponentMemoryLimitPath(componentName));
717718
assertThat(memory, equalTo(Long.parseLong(new String(buf1, StandardCharsets.UTF_8).trim())));
718719

719-
byte[] buf2 = Files.readAllBytes(Cgroup.CPU.getComponentCpuQuotaPath(componentName));
720-
byte[] buf3 = Files.readAllBytes(Cgroup.CPU.getComponentCpuPeriodPath(componentName));
720+
byte[] buf2 = Files.readAllBytes(new Cgroup(CgroupSubSystem.CPU).getComponentCpuQuotaPath(componentName));
721+
byte[] buf3 = Files.readAllBytes(new Cgroup(CgroupSubSystem.CPU).getComponentCpuPeriodPath(componentName));
721722

722723
int quota = Integer.parseInt(new String(buf2, StandardCharsets.UTF_8).trim());
723724
int period = Integer.parseInt(new String(buf3, StandardCharsets.UTF_8).trim());
@@ -761,7 +762,7 @@ void GIVEN_running_service_WHEN_pause_resume_requested_THEN_pause_resume_Service
761762
private LinuxSystemResourceController.CgroupFreezerState getCgroupFreezerState(String serviceName)
762763
throws IOException {
763764
return LinuxSystemResourceController.CgroupFreezerState
764-
.valueOf(new String(Files.readAllBytes(Cgroup.Freezer.getCgroupFreezerStateFilePath(serviceName))
765+
.valueOf(new String(Files.readAllBytes(new Cgroup(CgroupSubSystem.Freezer).getCgroupFreezerStateFilePath(serviceName))
765766
, StandardCharsets.UTF_8).trim());
766767
}
767768
}

src/main/java/com/aws/greengrass/util/platforms/unix/linux/Cgroup.java

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,62 @@
66
package com.aws.greengrass.util.platforms.unix.linux;
77

88
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
9+
import org.apache.commons.lang3.StringUtils;
910

1011
import java.nio.file.Path;
1112
import java.nio.file.Paths;
1213

1314
/**
14-
* Represents Linux cgroup v1 subsystems.
15+
* Represents Linux cgroup subsystems.
1516
*/
1617
@SuppressFBWarnings(value = "DMI_HARDCODED_ABSOLUTE_FILENAME", justification = "Cgroup virtual filesystem path "
1718
+ "cannot be relative")
18-
public enum Cgroup {
19-
Memory("memory"), CPU("cpu,cpuacct"), Freezer("freezer", "freezer");
20-
19+
public class Cgroup {
2120
private static final String CGROUP_ROOT = "/sys/fs/cgroup";
2221
private static final String GG_NAMESPACE = "greengrass";
2322
private static final String CGROUP_MEMORY_LIMITS = "memory.limit_in_bytes";
2423
private static final String CPU_CFS_PERIOD_US = "cpu.cfs_period_us";
2524
private static final String CPU_CFS_QUOTA_US = "cpu.cfs_quota_us";
2625
private static final String CGROUP_PROCS = "cgroup.procs";
2726
private static final String FREEZER_STATE_FILE = "freezer.state";
27+
private static final String CPU_MAX = "cpu.max";
28+
private static final String MEMORY_MAX = "memory.max";
29+
private static final String CGROUP_SUBTREE_CONTROL = "cgroup.subtree_control";
30+
private static final String CGROUP_FREEZE = "cgroup.freeze";
2831

2932
private final String osString;
3033
private final String mountSrc;
3134

32-
Cgroup(String str) {
33-
osString = str;
34-
mountSrc = "cgroup";
35+
/**
36+
* Cgroup constructor.
37+
*
38+
* @param subSystem subController
39+
*/
40+
public Cgroup(CgroupSubSystem subSystem) {
41+
this.osString = subSystem.getOsString();
42+
this.mountSrc = subSystem.getMountSrc();
3543
}
3644

37-
Cgroup(String str, String mountSrc) {
38-
this.osString = str;
39-
this.mountSrc = mountSrc;
45+
Cgroup(CgroupSubSystemV2 subSystemV2) {
46+
this.osString = subSystemV2.getOsString();
47+
this.mountSrc = subSystemV2.getMountSrc();
4048
}
4149

4250
public static Path getRootPath() {
4351
return Paths.get(CGROUP_ROOT);
4452
}
4553

46-
public static String rootMountCmd() {
47-
return String.format("mount -t tmpfs cgroup %s", CGROUP_ROOT);
54+
/**
55+
* root mount cmd.
56+
*
57+
* @return mount command string
58+
*/
59+
public String rootMountCmd() {
60+
if (StringUtils.isEmpty(osString)) {
61+
return String.format("mount -t cgroup2 none %s", CGROUP_ROOT);
62+
} else {
63+
return String.format("mount -t tmpfs cgroup %s", CGROUP_ROOT);
64+
}
4865
}
4966

5067
public String subsystemMountCmd() {
@@ -63,8 +80,18 @@ public Path getSubsystemComponentPath(String componentName) {
6380
return getSubsystemGGPath().resolve(componentName);
6481
}
6582

83+
/**
84+
* get component memory limit path.
85+
*
86+
* @param componentName componentName
87+
* @return memory limit Path
88+
*/
6689
public Path getComponentMemoryLimitPath(String componentName) {
67-
return getSubsystemComponentPath(componentName).resolve(CGROUP_MEMORY_LIMITS);
90+
if (StringUtils.isEmpty(osString)) {
91+
return getSubsystemComponentPath(componentName).resolve(MEMORY_MAX);
92+
} else {
93+
return getSubsystemComponentPath(componentName).resolve(CGROUP_MEMORY_LIMITS);
94+
}
6895
}
6996

7097
public Path getComponentCpuPeriodPath(String componentName) {
@@ -79,7 +106,34 @@ public Path getCgroupProcsPath(String componentName) {
79106
return getSubsystemComponentPath(componentName).resolve(CGROUP_PROCS);
80107
}
81108

109+
/**
110+
* get cgroup freezer path.
111+
*
112+
* @param componentName componentName
113+
* @return cgroup freezer path
114+
*/
82115
public Path getCgroupFreezerStateFilePath(String componentName) {
83-
return getSubsystemComponentPath(componentName).resolve(FREEZER_STATE_FILE);
116+
if (StringUtils.isEmpty(osString)) {
117+
return getSubsystemComponentPath(componentName).resolve(CGROUP_FREEZE);
118+
} else {
119+
return getSubsystemComponentPath(componentName).resolve(FREEZER_STATE_FILE);
120+
}
121+
}
122+
123+
public Path getRootSubTreeControlPath() {
124+
return getSubsystemRootPath().resolve(CGROUP_SUBTREE_CONTROL);
125+
}
126+
127+
public Path getGGSubTreeControlPath() {
128+
return getSubsystemGGPath().resolve(CGROUP_SUBTREE_CONTROL);
84129
}
130+
131+
public Path getComponentCpuMaxPath(String componentName) {
132+
return getSubsystemComponentPath(componentName).resolve(CPU_MAX);
133+
}
134+
135+
public Path getCgroupFreezePath(String componentName) {
136+
return getSubsystemComponentPath(componentName).resolve(CGROUP_FREEZE);
137+
}
138+
85139
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package com.aws.greengrass.util.platforms.unix.linux;
7+
8+
public enum CgroupSubSystem {
9+
Memory("memory", ""), CPU("cpu,cpuacct", ""), Freezer("freezer", "freezer");
10+
11+
private String osString;
12+
private String mountSrc;
13+
14+
CgroupSubSystem(String osString, String mountSrc) {
15+
this.osString = osString;
16+
this.mountSrc = mountSrc;
17+
}
18+
19+
/**
20+
* Get the osString associated with this CgroupSubController.
21+
*
22+
* @return the osString associated with this CgroupSubController.
23+
*/
24+
public String getOsString() {
25+
return osString;
26+
}
27+
28+
/**
29+
* Get the mountSrc associated with this CgroupSubController.
30+
*
31+
* @return the mountSrc associated with this CgroupSubController.
32+
*/
33+
public String getMountSrc() {
34+
return mountSrc;
35+
}
36+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package com.aws.greengrass.util.platforms.unix.linux;
7+
8+
public enum CgroupSubSystemV2 {
9+
Memory("", ""), CPU("", ""), Freezer("", ""),
10+
Unified("","");
11+
12+
private String osString;
13+
private String mountSrc;
14+
15+
CgroupSubSystemV2(String osString, String mountSrc) {
16+
this.osString = osString;
17+
this.mountSrc = mountSrc;
18+
}
19+
20+
/**
21+
* Get the osString associated with this CgroupSubController.
22+
*
23+
* @return the osString associated with this CgroupSubController.
24+
*/
25+
public String getOsString() {
26+
return osString;
27+
}
28+
29+
/**
30+
* Get the mountSrc associated with this CgroupSubController.
31+
*
32+
* @return the mountSrc associated with this CgroupSubController.
33+
*/
34+
public String getMountSrc() {
35+
return mountSrc;
36+
}
37+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package com.aws.greengrass.util.platforms.unix.linux;
7+
8+
public enum CgroupV2FreezerState {
9+
THAWED(0),
10+
FROZEN(1);
11+
12+
private int index;
13+
14+
CgroupV2FreezerState(int index) {
15+
this.index = index;
16+
}
17+
18+
/**
19+
* Get the index value associated with this CgroupV2FreezerState.
20+
*
21+
* @return the integer index value associated with this CgroupV2FreezerState.
22+
*/
23+
public int getIndex() {
24+
return index;
25+
}
26+
}

src/main/java/com/aws/greengrass/util/platforms/unix/linux/LinuxPlatform.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,33 @@
77

88
import com.aws.greengrass.util.platforms.SystemResourceController;
99
import com.aws.greengrass.util.platforms.unix.UnixPlatform;
10+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
1011

12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
14+
import java.nio.file.Paths;
15+
16+
@SuppressFBWarnings(value = "DMI_HARDCODED_ABSOLUTE_FILENAME",
17+
justification = "Cgroup Controller virtual filesystem path cannot be relative")
1118
public class LinuxPlatform extends UnixPlatform {
12-
SystemResourceController systemResourceController = new LinuxSystemResourceController(this);
19+
private static final String CGROUP_ROOT = "/sys/fs/cgroup";
20+
private static final String CGROUP_CONTROLLERS = "cgroup.controllers";
21+
22+
SystemResourceController systemResourceController;
1323

1424
@Override
1525
public SystemResourceController getSystemResourceController() {
26+
//if the path exists, identify it as cgroupv1, otherwise identify it as cgroupv2
27+
if (Files.exists(getControllersRootPath())) {
28+
systemResourceController = new LinuxSystemResourceControllerV2(this);
29+
} else {
30+
systemResourceController = new LinuxSystemResourceController(this);
31+
}
32+
1633
return systemResourceController;
1734
}
35+
36+
private Path getControllersRootPath() {
37+
return Paths.get(CGROUP_ROOT).resolve(CGROUP_CONTROLLERS);
38+
}
1839
}

0 commit comments

Comments
 (0)