Skip to content

Commit 2bee645

Browse files
author
Jonathan Dowland
committed
8253435: Cgroup: 'stomping of _mount_path' crash if manually mounted cpusets exist
Reviewed-by: sgehwolf Backport-of: 0054c15f60cce6470be05d29bfacbdb74cfb7bc9
1 parent d9db01c commit 2bee645

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

hotspot/src/os/linux/vm/cgroupSubsystem_linux.cpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,26 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos,
310310
cg_infos[MEMORY_IDX]._root_mount_path = os::strdup(tmproot);
311311
cg_infos[MEMORY_IDX]._data_complete = true;
312312
} else if (strcmp(token, "cpuset") == 0) {
313-
assert(cg_infos[CPUSET_IDX]._mount_path == NULL, "stomping of _mount_path");
314-
cg_infos[CPUSET_IDX]._mount_path = os::strdup(tmpmount);
313+
if (cg_infos[CPUSET_IDX]._mount_path != NULL) {
314+
// On some systems duplicate cpuset controllers get mounted in addition to
315+
// the main cgroup controllers most likely under /sys/fs/cgroup. In that
316+
// case pick the one under /sys/fs/cgroup and discard others.
317+
if (strstr(cg_infos[CPUSET_IDX]._mount_path, "/sys/fs/cgroup") != cg_infos[CPUSET_IDX]._mount_path) {
318+
if (PrintContainerInfo) {
319+
tty->print_cr("Duplicate cpuset controllers detected. Picking %s, skipping %s.",
320+
tmpmount, cg_infos[CPUSET_IDX]._mount_path);
321+
}
322+
os::free(cg_infos[CPUSET_IDX]._mount_path);
323+
cg_infos[CPUSET_IDX]._mount_path = os::strdup(tmpmount);
324+
} else {
325+
if (PrintContainerInfo) {
326+
tty->print_cr("Duplicate cpuset controllers detected. Picking %s, skipping %s.",
327+
cg_infos[CPUSET_IDX]._mount_path, tmpmount);
328+
}
329+
}
330+
} else {
331+
cg_infos[CPUSET_IDX]._mount_path = os::strdup(tmpmount);
332+
}
315333
cg_infos[CPUSET_IDX]._root_mount_path = os::strdup(tmproot);
316334
cg_infos[CPUSET_IDX]._data_complete = true;
317335
} else if (strcmp(token, "cpu") == 0) {

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

+24-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public class CgroupSubsystemFactory {
6363
private Path cgroupv1CgInfoNonZeroHierarchy;
6464
private Path cgroupv1MntInfoNonZeroHierarchyOtherOrder;
6565
private Path cgroupv1MntInfoNonZeroHierarchy;
66+
private Path cgroupv1MntInfoDoubleCpuset;
67+
private Path cgroupv1MntInfoDoubleCpuset2;
6668
private String mntInfoEmpty = "";
6769
private Path cgroupV1SelfCgroup;
6870
private Path cgroupV2SelfCgroup;
@@ -105,11 +107,14 @@ public class CgroupSubsystemFactory {
105107
"41 30 0:37 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:13 - cgroup none rw,seclabel,devices\n" +
106108
"42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup none rw,seclabel,cpuset\n" +
107109
"43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup none rw,seclabel,blkio\n" +
108-
"44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup none rw,seclabel,freezer";
110+
"44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup none rw,seclabel,freezer\n";
109111
private String mntInfoHybridRest = cgroupv1MountInfoLineMemory + mntInfoHybridStub;
110112
private String mntInfoHybridMissingMemory = mntInfoHybridStub;
111113
private String mntInfoHybrid = cgroupV2LineHybrid + mntInfoHybridRest;
112114
private String mntInfoHybridFlippedOrder = mntInfoHybridRest + cgroupV2LineHybrid;
115+
private String mntInfoCgroupv1MoreCpusetLine = "121 32 0:37 / /cpusets rw,relatime shared:69 - cgroup none rw,cpuset\n";
116+
private String mntInfoCgroupv1DoubleCpuset = mntInfoCgroupv1MoreCpusetLine + mntInfoHybrid;
117+
private String mntInfoCgroupv1DoubleCpuset2 = mntInfoHybrid + mntInfoCgroupv1MoreCpusetLine;
113118
private String cgroupsNonZeroHierarchy =
114119
"#subsys_name hierarchy num_cgroups enabled\n" +
115120
"cpuset 3 1 1\n" +
@@ -160,6 +165,12 @@ private void setup() {
160165

161166
cgroupV2MntInfoMissingCgroupv2 = Paths.get(existingDirectory.toString(), "mnt_info_missing_cgroup2");
162167
Files.write(cgroupV2MntInfoMissingCgroupv2, mntInfoHybridStub.getBytes());
168+
169+
cgroupv1MntInfoDoubleCpuset = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_cpuset");
170+
Files.write(cgroupv1MntInfoDoubleCpuset, mntInfoCgroupv1DoubleCpuset.getBytes());
171+
172+
cgroupv1MntInfoDoubleCpuset2 = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_cpuset2");
173+
Files.write(cgroupv1MntInfoDoubleCpuset2, mntInfoCgroupv1DoubleCpuset2.getBytes());
163174
} catch (IOException e) {
164175
throw new RuntimeException(e);
165176
}
@@ -196,6 +207,16 @@ private boolean isValidCgroup(int value) {
196207
return value == CGROUPS_V1 || value == CGROUPS_V2;
197208
}
198209

210+
public void testCgroupv1MultipleCpusetMounts(WhiteBox wb, Path mountInfo) {
211+
String procCgroups = cgroupv1CgInfoNonZeroHierarchy.toString();
212+
String procSelfCgroup = cgroupV1SelfCgroup.toString();
213+
String procSelfMountinfo = mountInfo.toString();
214+
int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);
215+
Asserts.assertEQ(CGROUPS_V1, retval, "Multiple cpuset controllers, but only one in /sys/fs/cgroup");
216+
Asserts.assertTrue(isValidCgroup(retval));
217+
System.out.println("testCgroupv1MultipleCpusetMounts PASSED!");
218+
}
219+
199220
public void testCgroupv1NoMounts(WhiteBox wb) {
200221
String procCgroups = cgroupv1CgInfoZeroHierarchy.toString();
201222
String procSelfCgroup = cgroupV1SelfCgroup.toString();
@@ -268,6 +289,8 @@ public static void main(String[] args) throws Exception {
268289
test.testCgroupV1HybridMntInfoOrder(wb);
269290
test.testCgroupv1MissingMemoryController(wb);
270291
test.testCgroupv2NoCgroup2Fs(wb);
292+
test.testCgroupv1MultipleCpusetMounts(wb, test.cgroupv1MntInfoDoubleCpuset);
293+
test.testCgroupv1MultipleCpusetMounts(wb, test.cgroupv1MntInfoDoubleCpuset2);
271294
} finally {
272295
test.teardown();
273296
}

0 commit comments

Comments
 (0)