@cryptotaxi247 / netdata-1 / commits / 2a764ebe4

autodetects cgroupsv2 on systems with systemd (#9249)

Timotej S committed Jun 25, 2020 at 09:46 UTC 2a764ebe4f649fb08b129566a3b28c86c932aeba
1 file changed +128 -1
collectors/cgroups.plugin/sys_fs_cgroup.c
+128 -1
@@ -73,6 +73,129 @@ static uint32_t Write_hash = 0;
73 static uint32_t user_hash = 0;
74 static uint32_t system_hash = 0;
75
76 +enum cgroups_type { CGROUPS_AUTODETECT_FAIL, CGROUPS_V1, CGROUPS_V2 };
77 +
78 +enum cgroups_systemd_setting {
79 + SYSTEMD_CGROUP_ERR,
80 + SYSTEMD_CGROUP_LEGACY,
81 + SYSTEMD_CGROUP_HYBRID,
82 + SYSTEMD_CGROUP_UNIFIED
83 +};
84 +
85 +struct cgroups_systemd_config_setting {
86 + char *name;
87 + enum cgroups_systemd_setting setting;
88 +};
89 +
90 +static struct cgroups_systemd_config_setting cgroups_systemd_options[] = {
91 + { .name = "legacy", .setting = SYSTEMD_CGROUP_LEGACY },
92 + { .name = "hybrid", .setting = SYSTEMD_CGROUP_HYBRID },
93 + { .name = "unified", .setting = SYSTEMD_CGROUP_UNIFIED },
94 + { .name = NULL, .setting = SYSTEMD_CGROUP_ERR },
95 +};
96 +
97 +/* on Fed systemd is not in PATH for some reason */
98 +#define SYSTEMD_CMD_RHEL "/usr/lib/systemd/systemd --version"
99 +#define SYSTEMD_HIERARCHY_STRING "default-hierarchy="
100 +
101 +#define MAXSIZE_PROC_CMDLINE 4096
102 +static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec)
103 +{
104 + pid_t command_pid;
105 + enum cgroups_systemd_setting retval = SYSTEMD_CGROUP_ERR;
106 + char buf[MAXSIZE_PROC_CMDLINE];
107 + char *begin, *end;
108 +
109 + FILE *f = mypopen(exec, &command_pid);
110 +
111 + if (!f)
112 + return retval;
113 +
114 + while (fgets(buf, MAXSIZE_PROC_CMDLINE, f) != NULL) {
115 + if ((begin = strstr(buf, SYSTEMD_HIERARCHY_STRING))) {
116 + end = begin = begin + strlen(SYSTEMD_HIERARCHY_STRING);
117 + if (!*begin)
118 + break;
119 + while (isalpha(*end))
120 + end++;
121 + *end = 0;
122 + for (int i = 0; cgroups_systemd_options[i].name; i++) {
123 + if (!strcmp(begin, cgroups_systemd_options[i].name)) {
124 + retval = cgroups_systemd_options[i].setting;
125 + break;
126 + }
127 + }
128 + break;
129 + }
130 + }
131 +
132 + if (mypclose(f, command_pid))
133 + return SYSTEMD_CGROUP_ERR;
134 +
135 + return retval;
136 +}
137 +
138 +static enum cgroups_type cgroups_try_detect_version()
139 +{
140 + pid_t command_pid;
141 + char buf[MAXSIZE_PROC_CMDLINE];
142 + enum cgroups_systemd_setting systemd_setting;
143 + int cgroups2_available = 0;
144 +
145 + // 1. check if cgroups2 availible on system at all
146 + FILE *f = mypopen("grep cgroup /proc/filesystems", &command_pid);
147 + if (!f) {
148 + error("popen failed");
149 + return CGROUPS_AUTODETECT_FAIL;
150 + }
151 + while (fgets(buf, MAXSIZE_PROC_CMDLINE, f) != NULL) {
152 + if (strstr(buf, "cgroup2")) {
153 + cgroups2_available = 1;
154 + break;
155 + }
156 + }
157 + if(mypclose(f, command_pid))
158 + return CGROUPS_AUTODETECT_FAIL;
159 +
160 + if(!cgroups2_available)
161 + return CGROUPS_V1;
162 +
163 + // 2. check systemd compiletime setting
164 + if ((systemd_setting = cgroups_detect_systemd("systemd --version")) == SYSTEMD_CGROUP_ERR)
165 + systemd_setting = cgroups_detect_systemd(SYSTEMD_CMD_RHEL);
166 +
167 + if(systemd_setting == SYSTEMD_CGROUP_ERR)
168 + return CGROUPS_AUTODETECT_FAIL;
169 +
170 + if(systemd_setting == SYSTEMD_CGROUP_LEGACY || systemd_setting == SYSTEMD_CGROUP_HYBRID) {
171 + // curently we prefer V1 if HYBRID is set as it seems to be more feature complete
172 + // in the future we might want to continue here if SYSTEMD_CGROUP_HYBRID
173 + // and go ahead with V2
174 + return CGROUPS_V1;
175 + }
176 +
177 + // 3. if we are unified as on Fedora (default cgroups2 only mode)
178 + // check kernel command line flag that can override that setting
179 + f = fopen("/proc/cmdline", "r");
180 + if (!f) {
181 + error("Error reading kernel boot commandline parameters");
182 + return CGROUPS_AUTODETECT_FAIL;
183 + }
184 +
185 + if (!fgets(buf, MAXSIZE_PROC_CMDLINE, f)) {
186 + error("couldn't read all cmdline params into buffer");
187 + return CGROUPS_AUTODETECT_FAIL;
188 + }
189 +
190 + fclose(f);
191 +
192 + if (strstr(buf, "systemd.unified_cgroup_hierarchy=0")) {
193 + info("cgroups v2 (unified cgroups) is available but are disabled on this system.");
194 + return CGROUPS_V1;
195 + }
196 + return CGROUPS_V2;
197 +}
198 +
199 void read_cgroup_plugin_configuration() {
200 system_page_size = sysconf(_SC_PAGESIZE);
201
@@ -89,7 +212,11 @@ void read_cgroup_plugin_configuration() {
212 if(cgroup_check_for_new_every < cgroup_update_every)
213 cgroup_check_for_new_every = cgroup_update_every;
214
92 - cgroup_use_unified_cgroups = config_get_boolean_ondemand("plugin:cgroups", "use unified cgroups", cgroup_use_unified_cgroups);
215 + cgroup_use_unified_cgroups = config_get_boolean_ondemand("plugin:cgroups", "use unified cgroups", CONFIG_BOOLEAN_AUTO);
216 + if(cgroup_use_unified_cgroups == CONFIG_BOOLEAN_AUTO)
217 + cgroup_use_unified_cgroups = (cgroups_try_detect_version() == CGROUPS_V2);
218 +
219 + info("use unified cgroups %s", cgroup_use_unified_cgroups ? "true" : "false");
220
221 cgroup_containers_chart_priority = (int)config_get_number("plugin:cgroups", "containers priority", cgroup_containers_chart_priority);
222 if(cgroup_containers_chart_priority < 1)