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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
// SPDX-License-Identifier: GPL-3.0-or-later
#include "apps_plugin.h"
static inline void clear_pid_io(struct pid_stat *p) {
p->io_logical_bytes_read = 0;
p->io_logical_bytes_written = 0;
p->io_read_calls = 0;
p->io_write_calls = 0;
p->io_storage_bytes_read = 0;
p->io_storage_bytes_written = 0;
p->io_cancelled_write_bytes = 0;
}
#if defined(__FreeBSD__)
static inline bool read_proc_pid_io_per_os(struct pid_stat *p, void *ptr) {
struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
pid_incremental_rate(io, p->io_storage_bytes_read, proc_info->ki_rusage.ru_inblock);
pid_incremental_rate(io, p->io_storage_bytes_written, proc_info->ki_rusage.ru_oublock);
p->io_logical_bytes_read = 0;
p->io_logical_bytes_written = 0;
p->io_read_calls = 0;
p->io_write_calls = 0;
p->io_cancelled_write_bytes = 0;
return true;
}
#endif
#ifdef __APPLE__
static inline bool read_proc_pid_io_per_os(struct pid_stat *p, void *ptr) {
struct pid_info *pi = ptr;
// On MacOS, the proc_pid_rusage provides disk_io_statistics which includes io bytes read and written
// but does not provide the same level of detail as Linux, like separating logical and physical I/O bytes.
pid_incremental_rate(io, p->io_storage_bytes_read, pi->rusageinfo.ri_diskio_bytesread);
pid_incremental_rate(io, p->io_storage_bytes_written, pi->rusageinfo.ri_diskio_byteswritten);
p->io_logical_bytes_read = 0;
p->io_logical_bytes_written = 0;
p->io_read_calls = 0;
p->io_write_calls = 0;
p->io_cancelled_write_bytes = 0;
return true;
}
#endif // __APPLE__
#if !defined(__FreeBSD__) && !defined(__APPLE__)
static inline int read_proc_pid_io_per_os(struct pid_stat *p, void *ptr __maybe_unused) {
static procfile *ff = NULL;
if(unlikely(!p->io_filename)) {
char filename[FILENAME_MAX + 1];
snprintfz(filename, FILENAME_MAX, "%s/proc/%d/io", netdata_configured_host_prefix, p->pid);
p->io_filename = strdupz(filename);
}
// open the file
ff = procfile_reopen(ff, p->io_filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
if(unlikely(!ff)) goto cleanup;
ff = procfile_readall(ff);
if(unlikely(!ff)) goto cleanup;
pid_incremental_rate(io, p->io_logical_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 0, 1)));
pid_incremental_rate(io, p->io_logical_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 1, 1)));
pid_incremental_rate(io, p->io_read_calls, str2kernel_uint_t(procfile_lineword(ff, 2, 1)));
pid_incremental_rate(io, p->io_write_calls, str2kernel_uint_t(procfile_lineword(ff, 3, 1)));
pid_incremental_rate(io, p->io_storage_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 4, 1)));
pid_incremental_rate(io, p->io_storage_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 5, 1)));
pid_incremental_rate(io, p->io_cancelled_write_bytes, str2kernel_uint_t(procfile_lineword(ff, 6, 1)));
return true;
cleanup:
clear_pid_io(p);
return false;
}
#endif // !__FreeBSD__ !__APPLE__
int read_proc_pid_io(struct pid_stat *p, void *ptr) {
p->last_io_collected_usec = p->io_collected_usec;
p->io_collected_usec = now_monotonic_usec();
calls_counter++;
bool ret = read_proc_pid_io_per_os(p, ptr);
if(unlikely(global_iterations_counter == 1))
clear_pid_io(p);
return ret ? 1 : 0;
}
|