Path: blob/master/test/hotspot/jtreg/containers/cgroup/CgroupSubsystemFactory.java
40942 views
/*1* Copyright (c) 2020, Red Hat Inc.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test CgroupSubsystemFactory25* @key cgroups26* @requires os.family == "linux"27* @library /testlibrary /test/lib28* @build sun.hotspot.WhiteBox29* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox30* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI CgroupSubsystemFactory31*/3233import java.io.IOException;34import java.nio.charset.StandardCharsets;35import java.nio.file.Files;36import java.nio.file.Path;37import java.nio.file.Paths;3839import jdk.test.lib.Asserts;40import jdk.test.lib.Utils;41import jdk.test.lib.util.FileUtils;42import sun.hotspot.WhiteBox;4344/*45* Verify hotspot's detection heuristics of CgroupSubsystemFactory::create()46*/47public class CgroupSubsystemFactory {4849// Mirrored from src/hotspot/os/linux/cgroupSubsystem_linux.hpp50private static final int CGROUPS_V1 = 1;51private static final int CGROUPS_V2 = 2;52private static final int INVALID_CGROUPS_V2 = 3;53private static final int INVALID_CGROUPS_V1 = 4;54private static final int INVALID_CGROUPS_NO_MOUNT = 5;55private Path existingDirectory;56private Path cgroupv1CgroupsJoinControllers;57private Path cgroupv1SelfCgroupsJoinControllers;58private Path cgroupv1MountInfoJoinControllers;59private Path cgroupv1CgInfoZeroHierarchy;60private Path cgroupv1MntInfoZeroHierarchy;61private Path cgroupv2CgInfoZeroHierarchy;62private Path cgroupv2MntInfoZeroHierarchy;63private Path cgroupv1CgInfoNonZeroHierarchy;64private Path cgroupv1MntInfoNonZeroHierarchyOtherOrder;65private Path cgroupv1MntInfoNonZeroHierarchy;66private Path cgroupv1MntInfoDoubleCpuset;67private Path cgroupv1MntInfoDoubleCpuset2;68private Path cgroupv1MntInfoSystemdOnly;69private String mntInfoEmpty = "";70private Path cgroupV1SelfCgroup;71private Path cgroupV2SelfCgroup;72private Path cgroupV2MntInfoMissingCgroupv2;73private Path cgroupv1MntInfoMissingMemoryController;74private String procSelfCgroupHybridContent = "11:hugetlb:/\n" +75"10:devices:/user.slice\n" +76"9:pids:/user.slice/user-15263.slice/[email protected]\n" +77"8:cpu,cpuacct:/\n" +78"7:perf_event:/\n" +79"6:freezer:/\n" +80"5:blkio:/\n" +81"4:net_cls,net_prio:/\n" +82"3:cpuset:/\n" +83"2:memory:/user.slice/user-15263.slice/[email protected]\n" +84"1:name=systemd:/user.slice/user-15263.slice/[email protected]/gnome-terminal-server.service\n" +85"0::/user.slice/user-15263.slice/[email protected]/gnome-terminal-server.service";86private String procSelfCgroupV2UnifiedContent = "0::/user.slice/user-1000.slice/session-3.scope";87private String procSelfCgroupV1JoinControllers =88"9:freezer:/\n" +89"8:rdma:/\n" +90"7:blkio:/user.slice\n" +91"6:devices:/user.slice\n" +92"5:pids:/user.slice/user-1000.slice/session-2.scope\n" +93"4:cpu,cpuacct,memory,net_cls,net_prio,hugetlb:/user.slice/user-1000.slice/session-2.scope\n" +94"3:cpuset:/\n" +95"2:perf_event:/\n" +96"1:name=systemd:/user.slice/user-1000.slice/session-2.scope\n" +97"0::/user.slice/user-1000.slice/session-2.scope\n";98private String cgroupsZeroHierarchy =99"#subsys_name hierarchy num_cgroups enabled\n" +100"cpuset 0 1 1\n" +101"cpu 0 1 1\n" +102"cpuacct 0 1 1\n" +103"memory 0 1 1\n" +104"devices 0 1 1\n" +105"freezer 0 1 1\n" +106"net_cls 0 1 1\n" +107"blkio 0 1 1\n" +108"perf_event 0 1 1 ";109private String cgroupsNonZeroJoinControllers =110"#subsys_name hierarchy num_cgroups enabled\n" +111"cpuset\t3\t1\t1\n" +112"cpu\t4\t153\t1\n" +113"cpuacct\t4\t153\t1\n" +114"blkio\t7\t87\t1\n" +115"memory\t4\t153\t1\n" +116"devices\t6\t87\t1\n" +117"freezer\t9\t1\t1\n" +118"net_cls\t4\t153\t1\n" +119"perf_event\t2\t1\t1\n" +120"net_prio\t4\t153\t1\n" +121"hugetlb\t4\t153\t1\n" +122"pids\t5\t95\t1\n" +123"rdma\t8\t1\t1\n";124private String cgroupV2LineHybrid = "31 30 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 none rw,seclabel,nsdelegate\n";125private String cgroupv1MountInfoLineMemory = "35 30 0:31 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:7 - cgroup none rw,seclabel,memory\n";126private String mntInfoHybridStub =127"30 23 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:4 - tmpfs tmpfs ro,seclabel,mode=755\n" +128"32 30 0:28 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:6 - cgroup none rw,seclabel,xattr,name=systemd\n" +129"36 30 0:32 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:8 - cgroup none rw,seclabel,pids\n" +130"37 30 0:33 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:9 - cgroup none rw,seclabel,perf_event\n" +131"38 30 0:34 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:10 - cgroup none rw,seclabel,net_cls,net_prio\n" +132"39 30 0:35 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:11 - cgroup none rw,seclabel,hugetlb\n" +133"40 30 0:36 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup none rw,seclabel,cpu,cpuacct\n" +134"41 30 0:37 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:13 - cgroup none rw,seclabel,devices\n" +135"42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup none rw,seclabel,cpuset\n" +136"43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup none rw,seclabel,blkio\n" +137"44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup none rw,seclabel,freezer\n";138private String mntInfoHybridRest = cgroupv1MountInfoLineMemory + mntInfoHybridStub;139private String mntInfoHybridMissingMemory = mntInfoHybridStub;140private String mntInfoHybrid = cgroupV2LineHybrid + mntInfoHybridRest;141private String mntInfoHybridFlippedOrder = mntInfoHybridRest + cgroupV2LineHybrid;142private String mntInfoCgroupv1JoinControllers =143"31 22 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755\n" +144"32 31 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:10 - cgroup2 cgroup2 rw,nsdelegate\n" +145"33 31 0:28 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,xattr,name=systemd\n" +146"36 31 0:31 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,perf_event\n" +147"37 31 0:32 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,cpuset\n" +148"38 31 0:33 / /sys/fs/cgroup/cpu,cpuacct,net_cls,net_prio,hugetlb,memory rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,cpu,cpuacct,memory,net_cls,net_prio,hugetlb\n" +149"39 31 0:34 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,pids\n" +150"40 31 0:35 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,devices\n" +151"41 31 0:36 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,blkio\n" +152"42 31 0:37 / /sys/fs/cgroup/rdma rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,rdma\n" +153"43 31 0:38 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,freezer\n";154private String mntInfoCgroupv1MoreCpusetLine = "121 32 0:37 / /cpusets rw,relatime shared:69 - cgroup none rw,cpuset\n";155private String mntInfoCgroupv1DoubleCpuset = mntInfoCgroupv1MoreCpusetLine + mntInfoHybrid;156private String mntInfoCgroupv1DoubleCpuset2 = mntInfoHybrid + mntInfoCgroupv1MoreCpusetLine;157private String cgroupsNonZeroHierarchy =158"#subsys_name hierarchy num_cgroups enabled\n" +159"cpuset 3 1 1\n" +160"cpu 8 1 1\n" +161"cpuacct 8 1 1\n" +162"blkio 10 1 1\n" +163"memory 2 90 1\n" +164"devices 8 74 1\n" +165"freezer 11 1 1\n" +166"net_cls 5 1 1\n" +167"perf_event 4 1 1\n" +168"net_prio 5 1 1\n" +169"hugetlb 6 1 1\n" +170"pids 3 80 1";171private String mntInfoCgroupsV2Only =172"28 21 0:25 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 none rw,seclabel,nsdelegate";173private String mntInfoCgroupsV1SystemdOnly =174"35 26 0:26 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime - cgroup systemd rw,name=systemd\n" +175"26 18 0:19 / /sys/fs/cgroup rw,relatime - tmpfs none rw,size=4k,mode=755\n";176177private void setup() {178try {179existingDirectory = Utils.createTempDirectory(CgroupSubsystemFactory.class.getSimpleName());180Path cgroupsZero = Paths.get(existingDirectory.toString(), "cgroups_zero");181Files.writeString(cgroupsZero, cgroupsZeroHierarchy, StandardCharsets.UTF_8);182cgroupv1CgInfoZeroHierarchy = cgroupsZero;183cgroupv2CgInfoZeroHierarchy = cgroupsZero;184cgroupv1MntInfoZeroHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_empty");185Files.writeString(cgroupv1MntInfoZeroHierarchy, mntInfoEmpty);186187cgroupv2MntInfoZeroHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_cgroupv2");188Files.writeString(cgroupv2MntInfoZeroHierarchy, mntInfoCgroupsV2Only);189190cgroupv1CgInfoNonZeroHierarchy = Paths.get(existingDirectory.toString(), "cgroups_non_zero");191Files.writeString(cgroupv1CgInfoNonZeroHierarchy, cgroupsNonZeroHierarchy);192193cgroupv1MntInfoNonZeroHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_non_zero");194Files.writeString(cgroupv1MntInfoNonZeroHierarchy, mntInfoHybrid);195196cgroupv1MntInfoNonZeroHierarchyOtherOrder = Paths.get(existingDirectory.toString(), "mountinfo_non_zero_cgroupv2_last");197Files.writeString(cgroupv1MntInfoNonZeroHierarchyOtherOrder, mntInfoHybridFlippedOrder);198199cgroupV1SelfCgroup = Paths.get(existingDirectory.toString(), "cgroup_self_hybrid");200Files.writeString(cgroupV1SelfCgroup, procSelfCgroupHybridContent);201202cgroupV2SelfCgroup = Paths.get(existingDirectory.toString(), "cgroup_self_v2");203Files.writeString(cgroupV2SelfCgroup, procSelfCgroupV2UnifiedContent);204205cgroupv1MntInfoMissingMemoryController = Paths.get(existingDirectory.toString(), "mnt_info_missing_memory");206Files.writeString(cgroupv1MntInfoMissingMemoryController, mntInfoHybridMissingMemory);207208cgroupV2MntInfoMissingCgroupv2 = Paths.get(existingDirectory.toString(), "mnt_info_missing_cgroup2");209Files.writeString(cgroupV2MntInfoMissingCgroupv2, mntInfoHybridStub);210211cgroupv1MntInfoDoubleCpuset = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_cpuset");212Files.writeString(cgroupv1MntInfoDoubleCpuset, mntInfoCgroupv1DoubleCpuset);213214cgroupv1MntInfoDoubleCpuset2 = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_double_cpuset2");215Files.writeString(cgroupv1MntInfoDoubleCpuset2, mntInfoCgroupv1DoubleCpuset2);216217cgroupv1MntInfoSystemdOnly = Paths.get(existingDirectory.toString(), "mnt_info_cgroupv1_systemd_only");218Files.writeString(cgroupv1MntInfoSystemdOnly, mntInfoCgroupsV1SystemdOnly);219220cgroupv1CgroupsJoinControllers = Paths.get(existingDirectory.toString(), "cgroups_cgv1_join_controllers");221Files.writeString(cgroupv1CgroupsJoinControllers, cgroupsNonZeroJoinControllers);222223cgroupv1SelfCgroupsJoinControllers = Paths.get(existingDirectory.toString(), "self_cgroup_cgv1_join_controllers");224Files.writeString(cgroupv1SelfCgroupsJoinControllers, procSelfCgroupV1JoinControllers);225226cgroupv1MountInfoJoinControllers = Paths.get(existingDirectory.toString(), "mntinfo_cgv1_join_controllers");227Files.writeString(cgroupv1MountInfoJoinControllers, mntInfoCgroupv1JoinControllers);228} catch (IOException e) {229throw new RuntimeException(e);230}231}232233private void teardown() {234try {235FileUtils.deleteFileTreeWithRetry(existingDirectory);236} catch (IOException e) {237System.err.println("Teardown failed. " + e.getMessage());238}239}240241private boolean isValidCgroup(int value) {242return value == CGROUPS_V1 || value == CGROUPS_V2;243}244245public void testCgroupv1JoinControllerCombo(WhiteBox wb) {246String procCgroups = cgroupv1CgroupsJoinControllers.toString();247String procSelfCgroup = cgroupv1SelfCgroupsJoinControllers.toString();248String procSelfMountinfo = cgroupv1MountInfoJoinControllers.toString();249int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);250Asserts.assertEQ(CGROUPS_V1, retval, "Join controllers should be properly detected");251Asserts.assertTrue(isValidCgroup(retval));252System.out.println("testCgroupv1JoinControllerMounts PASSED!");253}254255public void testCgroupv1MultipleCpusetMounts(WhiteBox wb, Path mountInfo) {256String procCgroups = cgroupv1CgInfoNonZeroHierarchy.toString();257String procSelfCgroup = cgroupV1SelfCgroup.toString();258String procSelfMountinfo = mountInfo.toString();259int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);260Asserts.assertEQ(CGROUPS_V1, retval, "Multiple cpuset controllers, but only one in /sys/fs/cgroup");261Asserts.assertTrue(isValidCgroup(retval));262System.out.println("testCgroupv1MultipleCpusetMounts PASSED!");263}264265public void testCgroupv1SystemdOnly(WhiteBox wb) {266String procCgroups = cgroupv1CgInfoZeroHierarchy.toString();267String procSelfCgroup = cgroupV1SelfCgroup.toString();268String procSelfMountinfo = cgroupv1MntInfoSystemdOnly.toString();269int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);270Asserts.assertEQ(INVALID_CGROUPS_NO_MOUNT, retval, "Only systemd mounted. Invalid");271Asserts.assertFalse(isValidCgroup(retval));272System.out.println("testCgroupv1SystemdOnly PASSED!");273}274275public void testCgroupv1NoMounts(WhiteBox wb) {276String procCgroups = cgroupv1CgInfoZeroHierarchy.toString();277String procSelfCgroup = cgroupV1SelfCgroup.toString();278String procSelfMountinfo = cgroupv1MntInfoZeroHierarchy.toString();279int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);280Asserts.assertEQ(INVALID_CGROUPS_NO_MOUNT, retval, "No cgroups mounted in /proc/self/mountinfo. Invalid.");281Asserts.assertFalse(isValidCgroup(retval));282System.out.println("testCgroupv1NoMounts PASSED!");283}284285public void testCgroupv2NoCgroup2Fs(WhiteBox wb) {286String procCgroups = cgroupv2CgInfoZeroHierarchy.toString();287String procSelfCgroup = cgroupV2SelfCgroup.toString();288String procSelfMountinfo = cgroupV2MntInfoMissingCgroupv2.toString();289int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);290Asserts.assertEQ(INVALID_CGROUPS_V2, retval, "No cgroup2 filesystem in /proc/self/mountinfo. Invalid.");291Asserts.assertFalse(isValidCgroup(retval));292System.out.println("testCgroupv2NoCgroup2Fs PASSED!");293}294295public void testCgroupv1MissingMemoryController(WhiteBox wb) {296String procCgroups = cgroupv1CgInfoNonZeroHierarchy.toString();297String procSelfCgroup = cgroupV1SelfCgroup.toString();298String procSelfMountinfo = cgroupv1MntInfoMissingMemoryController.toString();299int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);300Asserts.assertEQ(INVALID_CGROUPS_V1, retval, "Required memory controller path missing in mountinfo. Invalid.");301Asserts.assertFalse(isValidCgroup(retval));302System.out.println("testCgroupv1MissingMemoryController PASSED!");303}304305public void testCgroupv2(WhiteBox wb) {306String procCgroups = cgroupv2CgInfoZeroHierarchy.toString();307String procSelfCgroup = cgroupV2SelfCgroup.toString();308String procSelfMountinfo = cgroupv2MntInfoZeroHierarchy.toString();309int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);310Asserts.assertEQ(CGROUPS_V2, retval, "Expected");311Asserts.assertTrue(isValidCgroup(retval));312System.out.println("testCgroupv2 PASSED!");313}314315public void testCgroupV1Hybrid(WhiteBox wb) {316String procCgroups = cgroupv1CgInfoNonZeroHierarchy.toString();317String procSelfCgroup = cgroupV1SelfCgroup.toString();318String procSelfMountinfo = cgroupv1MntInfoNonZeroHierarchy.toString();319int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);320Asserts.assertEQ(CGROUPS_V1, retval, "Hybrid cgroups expected as cgroups v1");321Asserts.assertTrue(isValidCgroup(retval));322System.out.println("testCgroupv1Hybrid PASSED!");323}324325public void testCgroupV1HybridMntInfoOrder(WhiteBox wb) {326String procCgroups = cgroupv1CgInfoNonZeroHierarchy.toString();327String procSelfCgroup = cgroupV1SelfCgroup.toString();328String procSelfMountinfo = cgroupv1MntInfoNonZeroHierarchyOtherOrder.toString();329int retval = wb.validateCgroup(procCgroups, procSelfCgroup, procSelfMountinfo);330Asserts.assertEQ(CGROUPS_V1, retval, "Hybrid cgroups expected as cgroups v1");331Asserts.assertTrue(isValidCgroup(retval));332System.out.println("testCgroupv1HybridMntInfoOrder PASSED!");333}334335336public static void main(String[] args) throws Exception {337WhiteBox wb = WhiteBox.getWhiteBox();338CgroupSubsystemFactory test = new CgroupSubsystemFactory();339test.setup();340try {341test.testCgroupv1SystemdOnly(wb);342test.testCgroupv1NoMounts(wb);343test.testCgroupv2(wb);344test.testCgroupV1Hybrid(wb);345test.testCgroupV1HybridMntInfoOrder(wb);346test.testCgroupv1MissingMemoryController(wb);347test.testCgroupv2NoCgroup2Fs(wb);348test.testCgroupv1MultipleCpusetMounts(wb, test.cgroupv1MntInfoDoubleCpuset);349test.testCgroupv1MultipleCpusetMounts(wb, test.cgroupv1MntInfoDoubleCpuset2);350test.testCgroupv1JoinControllerCombo(wb);351} finally {352test.teardown();353}354}355}356357358