33
33
import java .util .List ;
34
34
import java .util .Map ;
35
35
import java .util .Optional ;
36
+ import java .util .regex .Matcher ;
37
+ import java .util .regex .Pattern ;
36
38
import java .util .stream .Stream ;
37
39
38
40
import jdk .internal .platform .cgroupv1 .CgroupV1Subsystem ;
@@ -46,6 +48,31 @@ public class CgroupSubsystemFactory {
46
48
private static final String BLKIO_CTRL = "blkio" ;
47
49
private static final String MEMORY_CTRL = "memory" ;
48
50
51
+ /*
52
+ * From https://www.kernel.org/doc/Documentation/filesystems/proc.txt
53
+ *
54
+ * 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
55
+ * (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11)
56
+ *
57
+ * (1) mount ID: unique identifier of the mount (may be reused after umount)
58
+ * (2) parent ID: ID of parent (or of self for the top of the mount tree)
59
+ * (3) major:minor: value of st_dev for files on filesystem
60
+ * (4) root: root of the mount within the filesystem
61
+ * (5) mount point: mount point relative to the process's root
62
+ * (6) mount options: per mount options
63
+ * (7) optional fields: zero or more fields of the form "tag[:value]"
64
+ * (8) separator: marks the end of the optional fields
65
+ * (9) filesystem type: name of filesystem of the form "type[.subtype]"
66
+ * (10) mount source: filesystem specific information or "none"
67
+ * (11) super options: per super block options
68
+ */
69
+ private static final Pattern MOUNTINFO_PATTERN = Pattern .compile (
70
+ "^[^\\ s]+\\ s+[^\\ s]+\\ s+[^\\ s]+\\ s+" + // (1), (2), (3)
71
+ "[^\\ s]+\\ s+([^\\ s]+)\\ s+" + // (4), (5) - group 1: mount point
72
+ "[^-]+-\\ s+" + // (6), (7), (8)
73
+ "([^\\ s]+)\\ s+" + // (9) - group 2: filesystem type
74
+ ".*$" ); // (10), (11)
75
+
49
76
static CgroupMetrics create () {
50
77
Optional <CgroupTypeResult > optResult = null ;
51
78
try {
@@ -114,12 +141,13 @@ public static Optional<CgroupTypeResult> determineType(String mountInfo, String
114
141
anyControllersEnabled = anyControllersEnabled || info .isEnabled ();
115
142
}
116
143
117
- // If there are no mounted controllers in mountinfo, but we've only
118
- // seen 0 hierarchy IDs in /proc/cgroups, we are on a cgroups v1 system.
144
+ // If there are no mounted, relevant cgroup controllers in mountinfo and only
145
+ // 0 hierarchy IDs in /proc/cgroups have been seen , we are on a cgroups v1 system.
119
146
// However, continuing in that case does not make sense as we'd need
120
- // information from mountinfo for the mounted controller paths anyway.
147
+ // information from mountinfo for the mounted controller paths which we wouldn't
148
+ // find anyway in that case.
121
149
try (Stream <String > mntInfo = CgroupUtil .readFilePrivileged (Paths .get (mountInfo ))) {
122
- boolean anyCgroupMounted = mntInfo .anyMatch (line -> line . contains ( "cgroup" ) );
150
+ boolean anyCgroupMounted = mntInfo .anyMatch (CgroupSubsystemFactory :: isRelevantControllerMount );
123
151
if (!anyCgroupMounted && isCgroupsV2 ) {
124
152
return Optional .empty ();
125
153
}
@@ -128,6 +156,31 @@ public static Optional<CgroupTypeResult> determineType(String mountInfo, String
128
156
return Optional .of (result );
129
157
}
130
158
159
+ private static boolean isRelevantControllerMount (String line ) {
160
+ Matcher lineMatcher = MOUNTINFO_PATTERN .matcher (line .trim ());
161
+ if (lineMatcher .matches ()) {
162
+ String mountPoint = lineMatcher .group (1 );
163
+ String fsType = lineMatcher .group (2 );
164
+ if (fsType .equals ("cgroup" )) {
165
+ String filename = Paths .get (mountPoint ).getFileName ().toString ();
166
+ for (String fn : filename .split ("," )) {
167
+ switch (fn ) {
168
+ case MEMORY_CTRL : // fall through
169
+ case CPU_CTRL :
170
+ case CPUSET_CTRL :
171
+ case CPUACCT_CTRL :
172
+ case BLKIO_CTRL :
173
+ return true ;
174
+ default : break ; // ignore not recognized controllers
175
+ }
176
+ }
177
+ } else if (fsType .equals ("cgroup2" )) {
178
+ return true ;
179
+ }
180
+ }
181
+ return false ;
182
+ }
183
+
131
184
public static final class CgroupTypeResult {
132
185
private final boolean isCgroupV2 ;
133
186
private final boolean anyControllersEnabled ;
0 commit comments