This source file includes following definitions.
- linux_module_init
- linux_module_fini
- next_field
- convert_value
- query
- local_getline
- local_stripper
- local_getfields
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include "opal_config.h"
26 #include "opal/constants.h"
27
28
29
30 #include <stdio.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <ctype.h>
37 #include <time.h>
38 #ifdef HAVE_SYS_TIME_H
39 #include <sys/time.h>
40 #endif
41
42 #include <sys/param.h>
43
44 #include "opal/dss/dss_types.h"
45 #include "opal/util/argv.h"
46 #include "opal/util/printf.h"
47
48 #include "pstat_linux.h"
49
50
51
52
53 static int linux_module_init(void);
54 static int query(pid_t pid,
55 opal_pstats_t *stats,
56 opal_node_stats_t *nstats);
57 static int linux_module_fini(void);
58
59
60
61
62 const opal_pstat_base_module_t opal_pstat_linux_module = {
63
64 linux_module_init,
65 query,
66 linux_module_fini
67 };
68
69 #define OPAL_STAT_MAX_LENGTH 1024
70
71
72 static char *local_getline(FILE *fp);
73 static char *local_stripper(char *data);
74 static void local_getfields(char *data, char ***fields);
75
76
77 static char input[OPAL_STAT_MAX_LENGTH];
78
79 static int linux_module_init(void)
80 {
81 return OPAL_SUCCESS;
82 }
83
84 static int linux_module_fini(void)
85 {
86 return OPAL_SUCCESS;
87 }
88
89 static char *next_field(char *ptr, int barrier)
90 {
91 int i=0;
92
93
94
95
96 while (!isspace(*ptr) && i < barrier) {
97 ptr++;
98 i++;
99 }
100
101
102 while (isspace(*ptr) && i < barrier) {
103 ptr++;
104 i++;
105 }
106
107 return ptr;
108 }
109
110 static float convert_value(char *value)
111 {
112 char *ptr;
113 float fval;
114
115
116 fval = (float)strtoul(value, &ptr, 10);
117
118 if (NULL != ptr && NULL != strstr(ptr, "kB")) {
119 fval /= 1024.0;
120 }
121 return fval;
122 }
123
124 static int query(pid_t pid,
125 opal_pstats_t *stats,
126 opal_node_stats_t *nstats)
127 {
128 char data[4096];
129 int fd;
130 size_t numchars;
131 char *ptr, *eptr;
132 int i;
133 int len, itime;
134 double dtime;
135 FILE *fp;
136 char *dptr, *value;
137 char **fields;
138 opal_diskstats_t *ds;
139 opal_netstats_t *ns;
140
141 if (NULL != stats) {
142
143 gettimeofday(&stats->sample_time, NULL);
144
145
146
147 if (NULL != nstats) {
148 nstats->sample_time.tv_sec = stats->sample_time.tv_sec;
149 nstats->sample_time.tv_usec = stats->sample_time.tv_usec;
150 }
151 } else if (NULL != nstats) {
152
153 gettimeofday(&nstats->sample_time, NULL);
154 }
155
156 if (NULL != stats) {
157
158 numchars = snprintf(data, sizeof(data), "/proc/%d/stat", pid);
159 if (numchars >= sizeof(data)) {
160 return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
161 }
162
163 if (0 > (fd = open(data, O_RDONLY))) {
164
165
166
167
168 return OPAL_ERR_FILE_OPEN_FAILURE;
169 }
170
171
172
173
174 memset(data, 0, sizeof(data));
175 len = read(fd, data, sizeof(data)-1);
176 if (len < 0) {
177
178 close(fd);
179 return OPAL_ERR_FILE_OPEN_FAILURE;
180 }
181 close(fd);
182
183
184 data[len] = '\0';
185
186
187
188
189
190
191 stats->pid = pid;
192
193
194 if (NULL == (ptr = strchr(data, '('))) {
195
196 return OPAL_ERR_BAD_PARAM;
197 }
198
199 ptr++;
200
201
202 if (NULL == (eptr = strchr(ptr, ')'))) {
203
204 return OPAL_ERR_BAD_PARAM;
205 }
206
207
208 i = 0;
209 while (ptr < eptr && i < OPAL_PSTAT_MAX_STRING_LEN) {
210 stats->cmd[i++] = *ptr++;
211 }
212
213
214 ptr = next_field(eptr, len);
215
216
217 stats->state[0] = *ptr;
218
219 ptr = next_field(ptr, len);
220
221
222 ptr = next_field(ptr, len);
223 ptr = next_field(ptr, len);
224 ptr = next_field(ptr, len);
225 ptr = next_field(ptr, len);
226 ptr = next_field(ptr, len);
227 ptr = next_field(ptr, len);
228 ptr = next_field(ptr, len);
229 ptr = next_field(ptr, len);
230 ptr = next_field(ptr, len);
231 ptr = next_field(ptr, len);
232
233
234 itime = strtoul(ptr, &ptr, 10);
235 itime += strtoul(ptr, &ptr, 10);
236
237 dtime = (double)itime / (double)HZ;
238 stats->time.tv_sec = (int)dtime;
239 stats->time.tv_usec = (int)(1000000.0 * (dtime - stats->time.tv_sec));
240
241 ptr = next_field(ptr, len);
242
243
244 ptr = next_field(ptr, len);
245 ptr = next_field(ptr, len);
246
247
248 stats->priority = strtol(ptr, &ptr, 10);
249
250 ptr = next_field(ptr, len);
251
252
253 ptr = next_field(ptr, len);
254
255
256 stats->num_threads = strtoul(ptr, &ptr, 10);
257
258 ptr = next_field(ptr, len);
259
260
261 ptr = next_field(ptr, len);
262 ptr = next_field(ptr, len);
263 ptr = next_field(ptr, len);
264 ptr = next_field(ptr, len);
265 ptr = next_field(ptr, len);
266 ptr = next_field(ptr, len);
267 ptr = next_field(ptr, len);
268 ptr = next_field(ptr, len);
269 ptr = next_field(ptr, len);
270 ptr = next_field(ptr, len);
271 ptr = next_field(ptr, len);
272 ptr = next_field(ptr, len);
273 ptr = next_field(ptr, len);
274 ptr = next_field(ptr, len);
275 ptr = next_field(ptr, len);
276 ptr = next_field(ptr, len);
277 ptr = next_field(ptr, len);
278 ptr = next_field(ptr, len);
279
280
281 stats->processor = strtol(ptr, NULL, 10);
282
283
284
285
286 memset(data, 0, sizeof(data));
287 numchars = snprintf(data, sizeof(data), "/proc/%d/status", pid);
288 if (numchars >= sizeof(data)) {
289 return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
290 }
291
292 if (NULL == (fp = fopen(data, "r"))) {
293
294 return OPAL_SUCCESS;
295 }
296
297
298 while (NULL != (dptr = local_getline(fp))) {
299 if (NULL == (value = local_stripper(dptr))) {
300
301 continue;
302 }
303
304 if (0 == strncmp(dptr, "VmPeak", strlen("VmPeak"))) {
305 stats->peak_vsize = convert_value(value);
306 } else if (0 == strncmp(dptr, "VmSize", strlen("VmSize"))) {
307 stats->vsize = convert_value(value);
308 } else if (0 == strncmp(dptr, "VmRSS", strlen("VmRSS"))) {
309 stats->rss = convert_value(value);
310 }
311 }
312 fclose(fp);
313
314
315 memset(data, 0, sizeof(data));
316 numchars = snprintf(data, sizeof(data), "/proc/%d/smaps", pid);
317 if (numchars >= sizeof(data)) {
318 return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
319 }
320
321 if (NULL == (fp = fopen(data, "r"))) {
322
323 return OPAL_SUCCESS;
324 }
325
326
327 while (NULL != (dptr = local_getline(fp))) {
328 if (NULL == (value = local_stripper(dptr))) {
329
330 continue;
331 }
332
333 if (0 == strncmp(dptr, "Pss", strlen("Pss"))) {
334 stats->pss += convert_value(value);
335 }
336 }
337 fclose(fp);
338 }
339
340 if (NULL != nstats) {
341
342 if (0 > (fd = open("/proc/loadavg", O_RDONLY))) {
343
344
345
346 goto diskstats;
347 }
348
349
350
351
352 memset(data, 0, sizeof(data));
353 len = read(fd, data, sizeof(data)-1);
354 close(fd);
355 if (len < 0) {
356 goto diskstats;
357 }
358
359
360 data[len] = '\0';
361
362
363 nstats->la = strtof(data, &ptr);
364 nstats->la5 = strtof(ptr, &eptr);
365 nstats->la15 = strtof(eptr, NULL);
366
367
368 if (NULL == (fp = fopen("/proc/meminfo", "r"))) {
369
370 goto diskstats;
371 }
372
373
374 while (NULL != (dptr = local_getline(fp))) {
375 if (NULL == (value = local_stripper(dptr))) {
376
377 continue;
378 }
379 if (0 == strcmp(dptr, "MemTotal")) {
380 nstats->total_mem = convert_value(value);
381 } else if (0 == strcmp(dptr, "MemFree")) {
382 nstats->free_mem = convert_value(value);
383 } else if (0 == strcmp(dptr, "Buffers")) {
384 nstats->buffers = convert_value(value);
385 } else if (0 == strcmp(dptr, "Cached")) {
386 nstats->cached = convert_value(value);
387 } else if (0 == strcmp(dptr, "SwapCached")) {
388 nstats->swap_cached = convert_value(value);
389 } else if (0 == strcmp(dptr, "SwapTotal")) {
390 nstats->swap_total = convert_value(value);
391 } else if (0 == strcmp(dptr, "SwapFree")) {
392 nstats->swap_free = convert_value(value);
393 } else if (0 == strcmp(dptr, "Mapped")) {
394 nstats->mapped = convert_value(value);
395 }
396 }
397 fclose(fp);
398
399 diskstats:
400
401 if (NULL == (fp = fopen("/proc/diskstats", "r"))) {
402
403
404
405 goto netstats;
406 }
407
408 while (NULL != (dptr = local_getline(fp))) {
409
410 if (NULL == strstr(dptr, "sd")) {
411 continue;
412 }
413
414 fields = NULL;
415 local_getfields(dptr, &fields);
416 if (NULL == fields) {
417 continue;
418 }
419 if (14 < opal_argv_count(fields)) {
420 opal_argv_free(fields);
421 continue;
422 }
423
424 ds = OBJ_NEW(opal_diskstats_t);
425 ds->disk = strdup(fields[2]);
426 ds->num_reads_completed = strtoul(fields[3], NULL, 10);
427 ds->num_reads_merged = strtoul(fields[4], NULL, 10);
428 ds->num_sectors_read = strtoul(fields[5], NULL, 10);
429 ds->milliseconds_reading = strtoul(fields[6], NULL, 10);
430 ds->num_writes_completed = strtoul(fields[7], NULL, 10);
431 ds->num_writes_merged = strtoul(fields[8], NULL, 10);
432 ds->num_sectors_written = strtoul(fields[9], NULL, 10);
433 ds->milliseconds_writing = strtoul(fields[10], NULL, 10);
434 ds->num_ios_in_progress = strtoul(fields[11], NULL, 10);
435 ds->milliseconds_io = strtoul(fields[12], NULL, 10);
436 ds->weighted_milliseconds_io = strtoul(fields[13], NULL, 10);
437 opal_list_append(&nstats->diskstats, &ds->super);
438 opal_argv_free(fields);
439 }
440 fclose(fp);
441
442 netstats:
443
444 if (NULL == (fp = fopen("/proc/net/dev", "r"))) {
445
446
447
448 goto complete;
449 }
450
451 local_getline(fp);
452 local_getline(fp);
453
454 while (NULL != (dptr = local_getline(fp))) {
455
456 if (NULL == (ptr = strchr(dptr, ':'))) {
457 continue;
458 }
459 *ptr = '\0';
460 ptr++;
461
462 fields = NULL;
463 local_getfields(ptr, &fields);
464 if (NULL == fields) {
465 continue;
466 }
467
468 ns = OBJ_NEW(opal_netstats_t);
469 ns->net_interface = strdup(dptr);
470 ns->num_bytes_recvd = strtoul(fields[0], NULL, 10);
471 ns->num_packets_recvd = strtoul(fields[1], NULL, 10);
472 ns->num_recv_errs = strtoul(fields[2], NULL, 10);
473 ns->num_bytes_sent = strtoul(fields[8], NULL, 10);
474 ns->num_packets_sent = strtoul(fields[9], NULL, 10);
475 ns->num_send_errs = strtoul(fields[10], NULL, 10);
476 opal_list_append(&nstats->netstats, &ns->super);
477 opal_argv_free(fields);
478 }
479 fclose(fp);
480 }
481
482 complete:
483 return OPAL_SUCCESS;
484 }
485
486 static char *local_getline(FILE *fp)
487 {
488 char *ret, *ptr;
489
490 ret = fgets(input, OPAL_STAT_MAX_LENGTH, fp);
491 if (NULL != ret) {
492 input[strlen(input)-1] = '\0';
493
494 ptr = input;
495 while (!isalnum(*ptr)) {
496 ptr++;
497 }
498 return ptr;
499 }
500
501 return NULL;
502 }
503
504 static char *local_stripper(char *data)
505 {
506 char *ptr, *end, *enddata;
507 int len = strlen(data);
508
509
510 if (NULL == (end = strchr(data, ':'))) {
511 return NULL;
512 }
513 ptr = end;
514 --end;
515
516 while (end != data && !isalnum(*end)) {
517 --end;
518 }
519 ++end;
520 *end = '\0';
521
522 ptr++;
523 enddata = &(data[len-1]);
524 while (ptr != enddata && !isalnum(*ptr)) {
525 ++ptr;
526 }
527 return ptr;
528 }
529
530 static void local_getfields(char *dptr, char ***fields)
531 {
532 char *ptr, *end;
533
534
535 *fields = NULL;
536
537
538 ptr = dptr;
539 while ('\0' != *ptr && !isalnum(*ptr)) {
540 ptr++;
541 }
542 if ('\0' == *ptr) {
543 return;
544 }
545
546
547
548
549
550
551 end = ptr;
552 end++;
553 while ('\0' != *end) {
554
555 while ('\0' != *end && isalnum(*end)) {
556 end++;
557 }
558
559 *end = '\0';
560
561 opal_argv_append_nosize(fields, ptr);
562
563 end++;
564 while ('\0' != *end && !isalnum(*end)) {
565 end++;
566 }
567 if ('\0' == *end) {
568 ptr = NULL;
569 break;
570 }
571 ptr = end;
572 end++;
573 }
574 if (NULL != ptr) {
575
576 opal_argv_append_nosize(fields, ptr);
577 }
578 }