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.Files; 30 import java.nio.file.Paths; 31 import java.util.HashMap; 32 import java.util.List; 33 import java.util.Map; 34 import java.util.stream.Collectors; 35 import java.util.stream.Stream; 36 37 import jdk.internal.platform.cgroupv1.CgroupV1Subsystem; 38 import jdk.internal.platform.cgroupv2.CgroupV2Subsystem; 39 import jdk.internal.platform.cgroupv2.CgroupV2SubsystemController; 40 41 class CgroupSubsystemFactory { 42 43 private static final String CPU_CTRL = "cpu"; 44 private static final String CPUACCT_CTRL = "cpuacct"; 45 private static final String CPUSET_CTRL = "cpuset"; 46 private static final String BLKIO_CTRL = "blkio"; 47 private static final String MEMORY_CTRL = "memory"; 48 49 static CgroupSubsystem create() { 50 Map<String, CgroupInfo> infos = new HashMap<>(); 51 try { 52 List<String> lines = Files.readAllLines(Paths.get("/proc/cgroups")); 53 for (String line : lines) { 54 if (line.startsWith("#")) { 55 continue; 56 } 57 CgroupInfo info = CgroupInfo.fromCgroupsLine(line); 58 switch (info.getName()) { 59 case CPU_CTRL: infos.put(CPU_CTRL, info); break; 60 case CPUACCT_CTRL: infos.put(CPUACCT_CTRL, info); break; 61 case CPUSET_CTRL: infos.put(CPUSET_CTRL, info); break; 62 case MEMORY_CTRL: infos.put(MEMORY_CTRL, info); break; 63 case BLKIO_CTRL: infos.put(BLKIO_CTRL, info); break; 64 } 65 } 66 } catch (IOException e) { 67 return null; 68 } 69 70 // For cgroups v1 all controllers need to have non-null hierarchy id 71 boolean isCgroupsV2 = true; 72 boolean anyControllersEnabled = false; 73 for (CgroupInfo info: infos.values()) { 74 isCgroupsV2 = isCgroupsV2 && info.getHierarchyId() == 0; 75 anyControllersEnabled = anyControllersEnabled || info.isEnabled(); 76 } 77 78 // If no controller is enabled, return no metrics. 79 if (!anyControllersEnabled) { 80 return null; 81 } 82 83 if (isCgroupsV2) { 84 // read mountinfo so as to determine root mount path 85 String mountPath = null; 86 try (Stream<String> lines = 87 Files.lines(Paths.get("/proc/self/mountinfo"))) { 88 89 String l = lines.filter(line -> line.contains(" - cgroup2 ")) 90 .collect(Collectors.joining()); 91 String[] tokens = l.split(" "); 92 mountPath = tokens[4]; 93 } catch (IOException e) { 94 return null; 95 } 96 String cgroupPath = null; 97 try { 98 List<String> lines = Files.readAllLines(Paths.get("/proc/self/cgroup")); 99 for (String line: lines) { 100 String[] tokens = line.split(":"); 101 if (tokens.length != 3) { 102 return null; // something is not right. 103 } 104 if (!Integer.valueOf(0).toString().equals(tokens[0])) { 105 // hierarchy must be zero for cgroups v2 106 return null; 107 } 108 cgroupPath = tokens[2]; 109 break; 110 } 111 } catch (IOException e) { 112 return null; 113 } 114 CgroupSubsystemController unified = new CgroupV2SubsystemController( 115 mountPath, 116 cgroupPath); 117 return new CgroupV2Subsystem(unified); 118 } else { 119 return CgroupV1Subsystem.getInstance(); 120 } 121 } 122 }