Skip to content

Commit 14e4502

Browse files
committed
8293472: Incorrect container resource limit detection if manual cgroup fs mounts present
Backport-of: 8f3bbe950fb5a3d9f6cae122209df01df0f342f0
1 parent ac7d936 commit 14e4502

File tree

6 files changed

+135
-54
lines changed

6 files changed

+135
-54
lines changed

src/hotspot/os/linux/cgroupSubsystem_linux.cpp

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,32 @@ CgroupSubsystem* CgroupSubsystemFactory::create() {
122122
return new CgroupV1Subsystem(cpuset, cpu, cpuacct, pids, memory);
123123
}
124124

125+
void CgroupSubsystemFactory::set_controller_paths(CgroupInfo* cg_infos,
126+
int controller,
127+
const char* name,
128+
char* mount_path,
129+
char* root_path) {
130+
if (cg_infos[controller]._mount_path != NULL) {
131+
// On some systems duplicate controllers get mounted in addition to
132+
// the main cgroup controllers most likely under /sys/fs/cgroup. In that
133+
// case pick the one under /sys/fs/cgroup and discard others.
134+
if (strstr(cg_infos[controller]._mount_path, "/sys/fs/cgroup") != cg_infos[controller]._mount_path) {
135+
log_debug(os, container)("Duplicate %s controllers detected. Picking %s, skipping %s.",
136+
name, mount_path, cg_infos[controller]._mount_path);
137+
os::free(cg_infos[controller]._mount_path);
138+
os::free(cg_infos[controller]._root_mount_path);
139+
cg_infos[controller]._mount_path = os::strdup(mount_path);
140+
cg_infos[controller]._root_mount_path = os::strdup(root_path);
141+
} else {
142+
log_debug(os, container)("Duplicate %s controllers detected. Picking %s, skipping %s.",
143+
name, cg_infos[controller]._mount_path, mount_path);
144+
}
145+
} else {
146+
cg_infos[controller]._mount_path = os::strdup(mount_path);
147+
cg_infos[controller]._root_mount_path = os::strdup(root_path);
148+
}
149+
}
150+
125151
bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos,
126152
const char* proc_cgroups,
127153
const char* proc_self_cgroup,
@@ -287,7 +313,6 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos,
287313
bool cgroupv2_mount_point_found = false;
288314
bool any_cgroup_mounts_found = false;
289315
while ((p = fgets(buf, MAXPATHLEN, mntinfo)) != NULL) {
290-
char tmp_mount_point[MAXPATHLEN+1];
291316
char tmp_fs_type[MAXPATHLEN+1];
292317
char tmproot[MAXPATHLEN+1];
293318
char tmpmount[MAXPATHLEN+1];
@@ -298,15 +323,13 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos,
298323
// Cgroup v2 relevant info. We only look for the _mount_path iff is_cgroupsV2 so
299324
// as to avoid memory stomping of the _mount_path pointer later on in the cgroup v1
300325
// block in the hybrid case.
301-
//
302-
if (is_cgroupsV2 && sscanf(p, "%*d %*d %*d:%*d %*s %s %*[^-]- %s %*s %*s", tmp_mount_point, tmp_fs_type) == 2) {
326+
if (is_cgroupsV2 && sscanf(p, "%*d %*d %*d:%*d %s %s %*[^-]- %s %*s %*s", tmproot, tmpmount, tmp_fs_type) == 3) {
303327
// we likely have an early match return (e.g. cgroup fs match), be sure we have cgroup2 as fstype
304-
if (!cgroupv2_mount_point_found && strcmp("cgroup2", tmp_fs_type) == 0) {
328+
if (strcmp("cgroup2", tmp_fs_type) == 0) {
305329
cgroupv2_mount_point_found = true;
306330
any_cgroup_mounts_found = true;
307331
for (int i = 0; i < CG_INFO_LENGTH; i++) {
308-
assert(cg_infos[i]._mount_path == NULL, "_mount_path memory stomping");
309-
cg_infos[i]._mount_path = os::strdup(tmp_mount_point);
332+
set_controller_paths(cg_infos, i, "(cg2, unified)", tmpmount, tmproot);
310333
}
311334
}
312335
}
@@ -331,47 +354,23 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos,
331354
while ((token = strsep(&cptr, ",")) != NULL) {
332355
if (strcmp(token, "memory") == 0) {
333356
any_cgroup_mounts_found = true;
334-
assert(cg_infos[MEMORY_IDX]._mount_path == NULL, "stomping of _mount_path");
335-
cg_infos[MEMORY_IDX]._mount_path = os::strdup(tmpmount);
336-
cg_infos[MEMORY_IDX]._root_mount_path = os::strdup(tmproot);
357+
set_controller_paths(cg_infos, MEMORY_IDX, token, tmpmount, tmproot);
337358
cg_infos[MEMORY_IDX]._data_complete = true;
338359
} else if (strcmp(token, "cpuset") == 0) {
339360
any_cgroup_mounts_found = true;
340-
if (cg_infos[CPUSET_IDX]._mount_path != NULL) {
341-
// On some systems duplicate cpuset controllers get mounted in addition to
342-
// the main cgroup controllers most likely under /sys/fs/cgroup. In that
343-
// case pick the one under /sys/fs/cgroup and discard others.
344-
if (strstr(cg_infos[CPUSET_IDX]._mount_path, "/sys/fs/cgroup") != cg_infos[CPUSET_IDX]._mount_path) {
345-
log_warning(os, container)("Duplicate cpuset controllers detected. Picking %s, skipping %s.",
346-
tmpmount, cg_infos[CPUSET_IDX]._mount_path);
347-
os::free(cg_infos[CPUSET_IDX]._mount_path);
348-
cg_infos[CPUSET_IDX]._mount_path = os::strdup(tmpmount);
349-
} else {
350-
log_warning(os, container)("Duplicate cpuset controllers detected. Picking %s, skipping %s.",
351-
cg_infos[CPUSET_IDX]._mount_path, tmpmount);
352-
}
353-
} else {
354-
cg_infos[CPUSET_IDX]._mount_path = os::strdup(tmpmount);
355-
}
356-
cg_infos[CPUSET_IDX]._root_mount_path = os::strdup(tmproot);
361+
set_controller_paths(cg_infos, CPUSET_IDX, token, tmpmount, tmproot);
357362
cg_infos[CPUSET_IDX]._data_complete = true;
358363
} else if (strcmp(token, "cpu") == 0) {
359364
any_cgroup_mounts_found = true;
360-
assert(cg_infos[CPU_IDX]._mount_path == NULL, "stomping of _mount_path");
361-
cg_infos[CPU_IDX]._mount_path = os::strdup(tmpmount);
362-
cg_infos[CPU_IDX]._root_mount_path = os::strdup(tmproot);
365+
set_controller_paths(cg_infos, CPU_IDX, token, tmpmount, tmproot);
363366
cg_infos[CPU_IDX]._data_complete = true;
364367
} else if (strcmp(token, "cpuacct") == 0) {
365368
any_cgroup_mounts_found = true;
366-
assert(cg_infos[CPUACCT_IDX]._mount_path == NULL, "stomping of _mount_path");
367-
cg_infos[CPUACCT_IDX]._mount_path = os::strdup(tmpmount);
368-
cg_infos[CPUACCT_IDX]._root_mount_path = os::strdup(tmproot);
369+
set_controller_paths(cg_infos, CPUACCT_IDX, token, tmpmount, tmproot);
369370
cg_infos[CPUACCT_IDX]._data_complete = true;
370371
} else if (strcmp(token, "pids") == 0) {
371372
any_cgroup_mounts_found = true;
372-
assert(cg_infos[PIDS_IDX]._mount_path == NULL, "stomping of _mount_path");
373-
cg_infos[PIDS_IDX]._mount_path = os::strdup(tmpmount);
374-
cg_infos[PIDS_IDX]._root_mount_path = os::strdup(tmproot);
373+
set_controller_paths(cg_infos, PIDS_IDX, token, tmpmount, tmproot);
375374
cg_infos[PIDS_IDX]._data_complete = true;
376375
}
377376
}

src/hotspot/os/linux/cgroupSubsystem_linux.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,11 @@ class CgroupSubsystemFactory: AllStatic {
308308
}
309309
#endif
310310

311+
static void set_controller_paths(CgroupInfo* cg_infos,
312+
int controller,
313+
const char* name,
314+
char* mount_path,
315+
char* root_path);
311316
// Determine the cgroup type (version 1 or version 2), given
312317
// relevant paths to files. Sets 'flags' accordingly.
313318
static bool determine_type(CgroupInfo* cg_infos,

test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,19 @@ public class CgroupSubsystemFactory {
6262
private Path cgroupv1MntInfoZeroHierarchy;
6363
private Path cgroupv2CgInfoZeroHierarchy;
6464
private Path cgroupv2MntInfoZeroHierarchy;
65+
private Path cgroupv2MntInfoDouble;
66+
private Path cgroupv2MntInfoDouble2;
6567
private Path cgroupv1CgInfoNonZeroHierarchy;
6668
private Path cgroupv1MntInfoNonZeroHierarchyOtherOrder;
6769
private Path cgroupv1MntInfoNonZeroHierarchy;
6870
private Path cgroupv1MntInfoDoubleCpuset;
6971
private Path cgroupv1MntInfoDoubleCpuset2;
72+
private Path cgroupv1MntInfoDoubleMemory;
73+
private Path cgroupv1MntInfoDoubleMemory2;
74+
private Path cgroupv1MntInfoDoubleCpu;
75+
private Path cgroupv1MntInfoDoubleCpu2;
76+
private Path cgroupv1MntInfoDoublePids;
77+
private Path cgroupv1MntInfoDoublePids2;
7078
private Path cgroupv1MntInfoSystemdOnly;
7179
private String mntInfoEmpty = "";
7280
private Path cgroupV1SelfCgroup;
@@ -160,6 +168,15 @@ public class CgroupSubsystemFactory {
160168
private String mntInfoCgroupv1MoreCpusetLine = "121 32 0:37 / /cpusets rw,relatime shared:69 - cgroup none rw,cpuset\n";
161169
private String mntInfoCgroupv1DoubleCpuset = mntInfoCgroupv1MoreCpusetLine + mntInfoHybrid;
162170
private String mntInfoCgroupv1DoubleCpuset2 = mntInfoHybrid + mntInfoCgroupv1MoreCpusetLine;
171+
private String mntInfoCgroupv1MoreMemoryLine = "1100 1098 0:28 / /memory rw,nosuid,nodev,noexec,relatime master:6 - cgroup cgroup rw,memory\n";
172+
private String mntInfoCgroupv1DoubleMemory = mntInfoCgroupv1MoreMemoryLine + mntInfoHybrid;
173+
private String mntInfoCgroupv1DoubleMemory2 = mntInfoHybrid + mntInfoCgroupv1MoreMemoryLine;
174+
private String mntInfoCgroupv1DoubleCpuLine = "1101 1098 0:29 / /cpu,cpuacct rw,nosuid,nodev,noexec,relatime master:7 - cgroup cgroup rw,cpu,cpuacct\n";
175+
private String mntInfoCgroupv1DoubleCpu = mntInfoCgroupv1DoubleCpuLine + mntInfoHybrid;
176+
private String mntInfoCgroupv1DoubleCpu2 = mntInfoHybrid + mntInfoCgroupv1DoubleCpuLine;
177+
private String mntInfoCgroupv1DoublePidsLine = "1107 1098 0:35 / /pids rw,nosuid,nodev,noexec,relatime master:13 - cgroup cgroup rw,pids\n";
178+
private String mntInfoCgroupv1DoublePids = mntInfoCgroupv1DoublePidsLine + mntInfoHybrid;
179+
private String mntInfoCgroupv1DoublePids2 = mntInfoHybrid + mntInfoCgroupv1DoublePidsLine;
163180
private String cgroupsNonZeroHierarchy =
164181
"#subsys_name hierarchy num_cgroups enabled\n" +
165182
"cpuset 3 1 1\n" +
@@ -175,7 +192,11 @@ public class CgroupSubsystemFactory {
175192
"hugetlb 6 1 1\n" +
176193
"pids 9 80 1"; // hierarchy has to match procSelfCgroupHybridContent
177194
private String mntInfoCgroupsV2Only =
178-
"28 21 0:25 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 none rw,seclabel,nsdelegate";
195+
"28 21 0:25 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 none rw,seclabel,nsdelegate\n";
196+
private String mntInfoCgroupsV2MoreLine =
197+
"240 232 0:24 /../.. /cgroup-in ro,relatime - cgroup2 cgroup2 rw,nsdelegate\n";
198+
private String mntInfoCgroupsV2Double = mntInfoCgroupsV2MoreLine + mntInfoCgroupsV2Only;
199+
private String mntInfoCgroupsV2Double2 = mntInfoCgroupsV2Only + mntInfoCgroupsV2MoreLine;
179200
private String mntInfoCgroupsV1SystemdOnly =
180201
"35 26 0:26 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime - cgroup systemd rw,name=systemd\n" +
181202
"26 18 0:19 / /sys/fs/cgroup rw,relatime - tmpfs none rw,size=4k,mode=755\n";
@@ -217,6 +238,12 @@ private void setup() {
217238
cgroupv2MntInfoZeroHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_cgroupv2");
218239
Files.writeString(cgroupv2MntInfoZeroHierarchy, mntInfoCgroupsV2Only);
219240

241+
cgroupv2MntInfoDouble = Paths.get(existingDirectory.toString(), "mountinfo_cgroupv2_double");
242+
Files.writeString(cgroupv2MntInfoDouble, mntInfoCgroupsV2Double);
243+
244+
cgroupv2MntInfoDouble2 = Paths.get(existingDirectory.toString(), "mountinfo_cgroupv2_double2");
245+
Files.writeString(cgroupv2MntInfoDouble2, mntInfoCgroupsV2Double2);
246+
220247
cgroupv1CgInfoNonZeroHierarchy = Paths.get(existingDirectory.toString(), "cgroups_non_zero");
221248
Files.writeString(cgroupv1CgInfoNonZeroHierarchy, cgroupsNonZeroHierarchy);
222249

@@ -244,6 +271,24 @@ private void setup() {
244271
cgroupv1MntInfoDoubleCpuset2 = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_cpuset2");
245272
Files.writeString(cgroupv1MntInfoDoubleCpuset2, mntInfoCgroupv1DoubleCpuset2);
246273

274+
cgroupv1MntInfoDoubleMemory = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_memory");
275+
Files.writeString(cgroupv1MntInfoDoubleMemory, mntInfoCgroupv1DoubleMemory);
276+
277+
cgroupv1MntInfoDoubleMemory2 = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_memory2");
278+
Files.writeString(cgroupv1MntInfoDoubleMemory2, mntInfoCgroupv1DoubleMemory2);
279+
280+
cgroupv1MntInfoDoubleCpu = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_cpu");
281+
Files.writeString(cgroupv1MntInfoDoubleCpu, mntInfoCgroupv1DoubleCpu);
282+
283+
cgroupv1MntInfoDoubleCpu2 = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_cpu2");
284+
Files.writeString(cgroupv1MntInfoDoubleCpu2, mntInfoCgroupv1DoubleCpu2);
285+
286+
cgroupv1MntInfoDoublePids = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_pids");
287+
Files.writeString(cgroupv1MntInfoDoublePids, mntInfoCgroupv1DoublePids);
288+
289+
cgroupv1MntInfoDoublePids2 = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_pids2");
290+
Files.writeString(cgroupv1MntInfoDoublePids2, mntInfoCgroupv1DoublePids2);
291+
247292
cgroupv1MntInfoSystemdOnly = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_systemd_only");
248293
Files.writeString(cgroupv1MntInfoSystemdOnly, mntInfoCgroupsV1SystemdOnly);
249294

@@ -291,14 +336,14 @@ public void testCgroupv1JoinControllerCombo(WhiteBox wb) {
291336
System.out.println("testCgroupv1JoinControllerMounts PASSED!");
292337
}
293338

294-
public void testCgroupv1MultipleCpusetMounts(WhiteBox wb, Path mountInfo) {
339+
public void testCgroupv1MultipleControllerMounts(WhiteBox wb, Path mountInfo) {
295340
String procCgroups = cgroupv1CgInfoNonZeroHierarchy.toString();
296341
String procSelfCgroup = cgroupV1SelfCgroup.toString();
297342
String procSelfMountinfo = mountInfo.toString();
298343
int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);
299-
Asserts.assertEQ(CGROUPS_V1, retval, "Multiple cpuset controllers, but only one in /sys/fs/cgroup");
344+
Asserts.assertEQ(CGROUPS_V1, retval, "Multiple controllers, but only one in /sys/fs/cgroup");
300345
Asserts.assertTrue(isValidCgroup(retval));
301-
System.out.println("testCgroupv1MultipleCpusetMounts PASSED!");
346+
System.out.println("testCgroupv1MultipleControllerMounts PASSED!");
302347
}
303348

304349
public void testCgroupv1SystemdOnly(WhiteBox wb) {
@@ -341,10 +386,10 @@ public void testCgroupv1MissingMemoryController(WhiteBox wb) {
341386
System.out.println("testCgroupv1MissingMemoryController PASSED!");
342387
}
343388

344-
public void testCgroupv2(WhiteBox wb) {
389+
public void testCgroupv2(WhiteBox wb, Path mountInfo) {
345390
String procCgroups = cgroupv2CgInfoZeroHierarchy.toString();
346391
String procSelfCgroup = cgroupV2SelfCgroup.toString();
347-
String procSelfMountinfo = cgroupv2MntInfoZeroHierarchy.toString();
392+
String procSelfMountinfo = mountInfo.toString();
348393
int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);
349394
Asserts.assertEQ(CGROUPS_V2, retval, "Expected");
350395
Asserts.assertTrue(isValidCgroup(retval));
@@ -388,13 +433,21 @@ public static void main(String[] args) throws Exception {
388433
try {
389434
test.testCgroupv1SystemdOnly(wb);
390435
test.testCgroupv1NoMounts(wb);
391-
test.testCgroupv2(wb);
436+
test.testCgroupv2(wb, test.cgroupv2MntInfoZeroHierarchy);
437+
test.testCgroupv2(wb, test.cgroupv2MntInfoDouble);
438+
test.testCgroupv2(wb, test.cgroupv2MntInfoDouble2);
392439
test.testCgroupV1Hybrid(wb);
393440
test.testCgroupV1HybridMntInfoOrder(wb);
394441
test.testCgroupv1MissingMemoryController(wb);
395442
test.testCgroupv2NoCgroup2Fs(wb);
396-
test.testCgroupv1MultipleCpusetMounts(wb, test.cgroupv1MntInfoDoubleCpuset);
397-
test.testCgroupv1MultipleCpusetMounts(wb, test.cgroupv1MntInfoDoubleCpuset2);
443+
test.testCgroupv1MultipleControllerMounts(wb, test.cgroupv1MntInfoDoubleCpuset);
444+
test.testCgroupv1MultipleControllerMounts(wb, test.cgroupv1MntInfoDoubleCpuset2);
445+
test.testCgroupv1MultipleControllerMounts(wb, test.cgroupv1MntInfoDoubleMemory);
446+
test.testCgroupv1MultipleControllerMounts(wb, test.cgroupv1MntInfoDoubleMemory2);
447+
test.testCgroupv1MultipleControllerMounts(wb, test.cgroupv1MntInfoDoubleCpu);
448+
test.testCgroupv1MultipleControllerMounts(wb, test.cgroupv1MntInfoDoubleCpu2);
449+
test.testCgroupv1MultipleControllerMounts(wb, test.cgroupv1MntInfoDoublePids);
450+
test.testCgroupv1MultipleControllerMounts(wb, test.cgroupv1MntInfoDoublePids2);
398451
test.testCgroupv1JoinControllerCombo(wb);
399452
test.testNonZeroHierarchyOnlyFreezer(wb);
400453
} finally {

test/hotspot/jtreg/containers/docker/DockerBasicTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public static void main(String[] args) throws Exception {
5353
try {
5454
testJavaVersion();
5555
testHelloDocker();
56+
testJavaVersionWithCgMounts();
5657
} finally {
5758
if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) {
5859
DockerTestUtils.removeDockerImage(imageNameAndTag);
@@ -81,4 +82,17 @@ private static void testHelloDocker() throws Exception {
8182
.shouldHaveExitValue(0)
8283
.shouldContain("Hello Docker");
8384
}
85+
86+
87+
private static void testJavaVersionWithCgMounts() throws Exception {
88+
DockerRunOptions opts =
89+
new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", "-version")
90+
.addDockerOpts("-v", "/sys/fs/cgroup:/cgroups-in:ro");
91+
92+
// Duplicated cgroup mounts should be handled by the container detection
93+
// code and should not cause any error/warning output.
94+
DockerTestUtils.dockerRunJava(opts)
95+
.shouldHaveExitValue(0)
96+
.shouldNotMatch("\\[os,container *\\]");
97+
}
8498
}

test/hotspot/jtreg/containers/docker/TestCPUAwareness.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,11 @@ public static void main(String[] args) throws Exception {
7575
testActiveProcessorCount(2, 2);
7676

7777
// cpu quota and period
78-
testCpuQuotaAndPeriod(50*1000, 100*1000);
79-
testCpuQuotaAndPeriod(100*1000, 100*1000);
80-
testCpuQuotaAndPeriod(150*1000, 100*1000);
81-
testCpuQuotaAndPeriod(400*1000, 100*1000);
78+
testCpuQuotaAndPeriod(50*1000, 100*1000, false);
79+
testCpuQuotaAndPeriod(100*1000, 100*1000, false);
80+
testCpuQuotaAndPeriod(150*1000, 100*1000, false);
81+
testCpuQuotaAndPeriod(400*1000, 100*1000, false);
82+
testCpuQuotaAndPeriod(50*1000, 100*1000, true /* additional cgroup mount */);
8283

8384
testOperatingSystemMXBeanAwareness("0.5", "1");
8485
testOperatingSystemMXBeanAwareness("1.0", "1");
@@ -174,7 +175,7 @@ private static int adjustExpectedAPCForAvailableCPUs(int expectedAPC) {
174175
}
175176

176177

177-
private static void testCpuQuotaAndPeriod(int quota, int period)
178+
private static void testCpuQuotaAndPeriod(int quota, int period, boolean addCgmounts)
178179
throws Exception {
179180
Common.logNewTestCase("test cpu quota and period: ");
180181
System.out.println("quota = " + quota);
@@ -188,6 +189,10 @@ private static void testCpuQuotaAndPeriod(int quota, int period)
188189
.addDockerOpts("--cpu-period=" + period)
189190
.addDockerOpts("--cpu-quota=" + quota);
190191

192+
if (addCgmounts) {
193+
opts = opts.addDockerOpts("--volume", "/sys/fs/cgroup:/cgroups-in:ro");
194+
}
195+
191196
Common.run(opts)
192197
.shouldMatch("CPU Period is.*" + period)
193198
.shouldMatch("CPU Quota is.*" + quota)

0 commit comments

Comments
 (0)