This source file includes following definitions.
- find_cib_loadfile
- pcmk__procfs_process_info
- pcmk__procfs_pid_of
- pcmk__procfs_num_cores
- pcmk__procfs_pid2path
- pcmk__procfs_has_pids
- pcmk__procfs_fd_dir
- pcmk__sysrq_trigger
- pcmk__throttle_cib_load
- pcmk__throttle_load_avg
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include <dirent.h>
18 #include <ctype.h>
19
20 #if HAVE_LINUX_PROCFS
21
22
23
24
25
26
27
28
29
30
31 static char *
32 find_cib_loadfile(const char *server)
33 {
34 pid_t pid = pcmk__procfs_pid_of(server);
35
36 return pid? crm_strdup_printf("/proc/%lld/stat", (long long) pid) : NULL;
37 }
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 static int
55 pcmk__procfs_process_info(const struct dirent *entry, char *name, pid_t *pid)
56 {
57 int fd, local_pid;
58 FILE *file;
59 struct stat statbuf;
60 char procpath[128] = { 0 };
61
62
63
64
65
66
67 local_pid = atoi(entry->d_name);
68 if ((local_pid <= 0) || (strlen(entry->d_name) > 114)) {
69 return -1;
70 }
71 if (pid) {
72 *pid = (pid_t) local_pid;
73 }
74
75
76 strcpy(procpath, "/proc/");
77 strcat(procpath, entry->d_name);
78 fd = open(procpath, O_RDONLY);
79 if (fd < 0 ) {
80 return -1;
81 }
82 if (fstat(fd, &statbuf) < 0) {
83 close(fd);
84 return -1;
85 }
86 close(fd);
87
88
89 if (!S_ISDIR(statbuf.st_mode)) {
90 return -1;
91 }
92
93
94
95
96
97 if (name != NULL) {
98 strcat(procpath, "/status");
99 file = fopen(procpath, "r");
100 if (!file) {
101 return -1;
102 }
103 if (fscanf(file, "Name:\t%15[^\n]", name) != 1) {
104 fclose(file);
105 return -1;
106 }
107 name[15] = 0;
108 fclose(file);
109 }
110
111 return 0;
112 }
113 #endif
114
115
116
117
118
119
120
121
122
123
124
125
126 pid_t
127 pcmk__procfs_pid_of(const char *name)
128 {
129 #if HAVE_LINUX_PROCFS
130 DIR *dp;
131 struct dirent *entry;
132 pid_t pid = 0;
133 char entry_name[64] = { 0 };
134
135 dp = opendir("/proc");
136 if (dp == NULL) {
137 crm_notice("Can not read /proc directory to track existing components");
138 return 0;
139 }
140
141 while ((entry = readdir(dp)) != NULL) {
142 if ((pcmk__procfs_process_info(entry, entry_name, &pid) == pcmk_rc_ok)
143 && pcmk__str_eq(entry_name, name, pcmk__str_casei)
144 && (pcmk__pid_active(pid, NULL) == pcmk_rc_ok)) {
145
146 crm_info("Found %s active as process %lld", name, (long long) pid);
147 break;
148 }
149 pid = 0;
150 }
151 closedir(dp);
152 return pid;
153 #else
154 return 0;
155 #endif
156 }
157
158
159
160
161
162
163
164 unsigned int
165 pcmk__procfs_num_cores(void)
166 {
167 #if HAVE_LINUX_PROCFS
168 int cores = 0;
169 FILE *stream = NULL;
170
171
172 stream = fopen("/proc/stat", "r");
173 if (stream == NULL) {
174 crm_perror(LOG_INFO, "Could not open /proc/stat");
175 } else {
176 char buffer[2048];
177
178 while (fgets(buffer, sizeof(buffer), stream)) {
179 if (pcmk__starts_with(buffer, "cpu") && isdigit(buffer[3])) {
180 ++cores;
181 }
182 }
183 fclose(stream);
184 }
185 return cores? cores : 1;
186 #else
187 return 1;
188 #endif
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202 int
203 pcmk__procfs_pid2path(pid_t pid, char path[], size_t path_size)
204 {
205 #if HAVE_LINUX_PROCFS
206 char procfs_exe_path[PATH_MAX];
207 ssize_t link_rc;
208
209 if (snprintf(procfs_exe_path, PATH_MAX, "/proc/%lld/exe",
210 (long long) pid) >= PATH_MAX) {
211 return ENAMETOOLONG;
212 }
213
214 link_rc = readlink(procfs_exe_path, path, path_size - 1);
215 if (link_rc < 0) {
216 return errno;
217 } else if (link_rc >= (path_size - 1)) {
218 return ENAMETOOLONG;
219 }
220
221 path[link_rc] = '\0';
222 return pcmk_rc_ok;
223 #else
224 return EOPNOTSUPP;
225 #endif
226 }
227
228
229
230
231
232
233
234 bool
235 pcmk__procfs_has_pids(void)
236 {
237 #if HAVE_LINUX_PROCFS
238 static bool have_pids = false;
239 static bool checked = false;
240
241 if (!checked) {
242 char path[PATH_MAX];
243
244 have_pids = pcmk__procfs_pid2path(getpid(), path, sizeof(path)) == pcmk_rc_ok;
245 checked = true;
246 }
247 return have_pids;
248 #else
249 return false;
250 #endif
251 }
252
253
254
255
256
257
258 DIR *
259 pcmk__procfs_fd_dir(void)
260 {
261 DIR *dir = NULL;
262
263
264
265
266
267
268 #if HAVE_LINUX_PROCFS
269 dir = opendir("/proc/self/fd");
270 #endif
271
272 return dir;
273 }
274
275
276
277
278
279
280
281 void
282 pcmk__sysrq_trigger(char t)
283 {
284 #if HAVE_LINUX_PROCFS
285
286 FILE *procf = fopen("/proc/sysrq-trigger", "a");
287
288 if (procf == NULL) {
289 crm_warn("Could not open sysrq-trigger: %s", strerror(errno));
290 } else {
291 fprintf(procf, "%c\n", t);
292 fclose(procf);
293 }
294 #endif
295 }
296
297 bool
298 pcmk__throttle_cib_load(const char *server, float *load)
299 {
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343 #if HAVE_LINUX_PROCFS
344 static char *loadfile = NULL;
345 static time_t last_call = 0;
346 static long ticks_per_s = 0;
347 static unsigned long last_utime, last_stime;
348
349 char buffer[64*1024];
350 FILE *stream = NULL;
351 time_t now = time(NULL);
352
353 if (load == NULL) {
354 return false;
355 } else {
356 *load = 0.0;
357 }
358
359 if (loadfile == NULL) {
360 last_call = 0;
361 last_utime = 0;
362 last_stime = 0;
363
364 loadfile = find_cib_loadfile(server);
365 if (loadfile == NULL) {
366 crm_warn("Couldn't find CIB load file");
367 return false;
368 }
369
370 ticks_per_s = sysconf(_SC_CLK_TCK);
371 crm_trace("Found %s", loadfile);
372 }
373
374 stream = fopen(loadfile, "r");
375 if (stream == NULL) {
376 int rc = errno;
377
378 crm_warn("Couldn't read %s: %s (%d)", loadfile, pcmk_rc_str(rc), rc);
379 free(loadfile);
380 loadfile = NULL;
381 return false;
382 }
383
384 if (fgets(buffer, sizeof(buffer), stream) != NULL) {
385 char *comm = pcmk__assert_alloc(1, 256);
386 char state = 0;
387 int rc = 0, pid = 0, ppid = 0, pgrp = 0, session = 0, tty_nr = 0, tpgid = 0;
388 unsigned long flags = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0, utime = 0, stime = 0;
389
390 rc = sscanf(buffer, "%d %[^ ] %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu",
391 &pid, comm, &state, &ppid, &pgrp, &session, &tty_nr, &tpgid,
392 &flags, &minflt, &cminflt, &majflt, &cmajflt, &utime, &stime);
393 free(comm);
394
395 if (rc != 15) {
396 crm_err("Only %d of 15 fields found in %s", rc, loadfile);
397 fclose(stream);
398 return false;
399
400 } else if ((last_call > 0) && (last_call < now) && (last_utime <= utime) &&
401 (last_stime <= stime)) {
402 time_t elapsed = now - last_call;
403 unsigned long delta_utime = utime - last_utime;
404 unsigned long delta_stime = stime - last_stime;
405
406 *load = delta_utime + delta_stime;
407 *load /= ticks_per_s;
408 *load /= elapsed;
409 crm_debug("cib load: %f (%lu ticks in %lds)", *load,
410 delta_utime + delta_stime, (long) elapsed);
411
412 } else {
413 crm_debug("Init %lu + %lu ticks at %ld (%lu tps)", utime, stime,
414 (long) now, ticks_per_s);
415 }
416
417 last_call = now;
418 last_utime = utime;
419 last_stime = stime;
420
421 fclose(stream);
422 return true;
423 }
424
425 fclose(stream);
426 #endif
427 return false;
428 }
429
430 bool
431 pcmk__throttle_load_avg(float *load)
432 {
433 #if HAVE_LINUX_PROCFS
434 char buffer[256];
435 FILE *stream = NULL;
436 const char *loadfile = "/proc/loadavg";
437
438 if (load == NULL) {
439 return false;
440 }
441
442 stream = fopen(loadfile, "r");
443 if (stream == NULL) {
444 int rc = errno;
445 crm_warn("Couldn't read %s: %s (%d)", loadfile, pcmk_rc_str(rc), rc);
446 return false;
447 }
448
449 if (fgets(buffer, sizeof(buffer), stream) != NULL) {
450 char *nl = strstr(buffer, "\n");
451
452
453 *load = strtof(buffer, NULL);
454 if (nl != NULL) {
455 nl[0] = 0;
456 }
457
458 fclose(stream);
459 return true;
460 }
461
462 fclose(stream);
463 #endif
464 return false;
465 }