1 /* 2 * Copyright (c) 2019, Red Hat Inc. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.internal.platform; 27 28 import java.io.IOException; 29 import java.nio.file.Paths; 30 import java.util.HashMap; 31 import java.util.List; 32 import java.util.Map; 33 import java.util.stream.Collectors; 34 import java.util.stream.Stream; 35 36 import jdk.internal.platform.cgroupv1.CgroupV1Subsystem; 37 import jdk.internal.platform.cgroupv2.CgroupV2Subsystem; 38 import jdk.internal.platform.cgroupv2.CgroupV2SubsystemController; 39 40 class CgroupSubsystemFactory { 41 42 private static final String CPU_CTRL = "cpu"; 43 private static final String CPUACCT_CTRL = "cpuacct"; 44 private static final String CPUSET_CTRL = "cpuset"; 45 private static final String BLKIO_CTRL = "blkio"; 46 private static final String MEMORY_CTRL = "memory"; 47 48 static CgroupSubsystem create() { 49 Map<String, CgroupInfo> infos = new HashMap<>(); 50 try { 51 List<String> lines = CgroupUtil.readAllLinesPrivileged(Paths.get("/proc/cgroups")); 52 for (String line : lines) { 53 if (line.startsWith("#")) { 54 continue; 55 } 56 CgroupInfo info = CgroupInfo.fromCgroupsLine(line); 57 switch (info.getName()) { 58 case CPU_CTRL: infos.put(CPU_CTRL, info); break; 59 case CPUACCT_CTRL: infos.put(CPUACCT_CTRL, info); break; 60 case CPUSET_CTRL: infos.put(CPUSET_CTRL, info); break; 61 case MEMORY_CTRL: infos.put(MEMORY_CTRL, info); break; 62 case BLKIO_CTRL: infos.put(BLKIO_CTRL, info); break; 63 } 64 } 65 } catch (IOException e) { 66 return null; 67 } 68 69 // For cgroups v1 all controllers need to have non-null hierarchy id 70 boolean isCgroupsV2 = true; 71 boolean anyControllersEnabled = false; 72 for (CgroupInfo info: infos.values()) { 73 isCgroupsV2 = isCgroupsV2 && info.getHierarchyId() == 0; 74 anyControllersEnabled = anyControllersEnabled || info.isEnabled(); 75 } 76 77 // If no controller is enabled, return no metrics. 78 if (!anyControllersEnabled) { 79 return null; 80 } 81 82 if (isCgroupsV2) { 83 // read mountinfo so as to determine root mount path 84 String mountPath = null; 85 try (Stream<String> lines = 86 CgroupUtil.readFilePrivileged(Paths.get("/proc/self/mountinfo"))) { 87 88 String l = lines.filter(line -> line.contains(" - cgroup2 ")) 89 .collect(Collectors.joining()); 90 String[] tokens = l.split(" "); 91 mountPath = tokens[4]; 92 } catch (IOException e) { 93 return null; 94 } 95 String cgroupPath = null; 96 try { 97 List<String> lines = CgroupUtil.readAllLinesPrivileged(Paths.get("/proc/self/cgroup")); 98 for (String line: lines) { 99 String[] tokens = line.split(":"); 100 if (tokens.length != 3) { 101 return null; // something is not right. 102 } 103 if (!Integer.valueOf(0).toString().equals(tokens[0])) { 104 // hierarchy must be zero for cgroups v2 105 return null; 106 } 107 cgroupPath = tokens[2]; 108 break; 109 } 110 } catch (IOException e) { 111 return null; 112 } 113 CgroupSubsystemController unified = new CgroupV2SubsystemController( 114 mountPath, 115 cgroupPath); 116 return new CgroupV2Subsystem(unified); 117 } else { 118 return CgroupV1Subsystem.getInstance(); 119 } 120 } 121 }