1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "sysinfo.h"
22 #include "log.h"
23
get_diskstat(const char * devname,zbx_uint64_t * dstat)24 int get_diskstat(const char *devname, zbx_uint64_t *dstat)
25 {
26 return FAIL;
27 }
28
get_disk_stats(const char * devname,zbx_uint64_t * rbytes,zbx_uint64_t * wbytes,zbx_uint64_t * roper,zbx_uint64_t * woper,char ** error)29 static int get_disk_stats(const char *devname, zbx_uint64_t *rbytes, zbx_uint64_t *wbytes, zbx_uint64_t *roper,
30 zbx_uint64_t *woper, char **error)
31 {
32 int ret = SYSINFO_RET_FAIL, mib[2], i, drive_count;
33 size_t len;
34 struct diskstats *stats;
35
36 mib[0] = CTL_HW;
37 mib[1] = HW_DISKCOUNT;
38
39 len = sizeof(drive_count);
40
41 if (0 != sysctl(mib, 2, &drive_count, &len, NULL, 0))
42 {
43 *error = zbx_dsprintf(NULL, "Cannot obtain number of disks: %s", zbx_strerror(errno));
44 return SYSINFO_RET_FAIL;
45 }
46
47 len = drive_count * sizeof(struct diskstats);
48
49 stats = zbx_calloc(NULL, drive_count, len);
50
51 mib[0] = CTL_HW;
52 mib[1] = HW_DISKSTATS;
53
54 if (NULL != rbytes)
55 *rbytes = 0;
56 if (NULL != wbytes)
57 *wbytes = 0;
58 if (NULL != roper)
59 *roper = 0;
60 if (NULL != woper)
61 *woper = 0;
62
63 if (0 != sysctl(mib, 2, stats, &len, NULL, 0))
64 {
65 zbx_free(stats);
66 *error = zbx_dsprintf(NULL, "Cannot obtain disk information: %s", zbx_strerror(errno));
67 return SYSINFO_RET_FAIL;
68 }
69
70 for (i = 0; i < drive_count; i++)
71 {
72 if (NULL == devname || '\0' == *devname || 0 == strcmp(devname, "all") ||
73 0 == strcmp(devname, stats[i].ds_name))
74 {
75 if (NULL != rbytes)
76 *rbytes += stats[i].ds_rbytes;
77 if (NULL != wbytes)
78 *wbytes += stats[i].ds_wbytes;
79 if (NULL != roper)
80 *roper += stats[i].ds_rxfer;
81 if (NULL != woper)
82 *woper += stats[i].ds_wxfer;
83
84 ret = SYSINFO_RET_OK;
85 }
86 }
87
88 zbx_free(stats);
89
90 if (SYSINFO_RET_FAIL == ret)
91 {
92 *error = zbx_strdup(NULL, "Cannot find information for this disk device.");
93 return SYSINFO_RET_FAIL;
94 }
95
96 return ret;
97 }
98
VFS_DEV_READ_BYTES(const char * devname,AGENT_RESULT * result)99 static int VFS_DEV_READ_BYTES(const char *devname, AGENT_RESULT *result)
100 {
101 zbx_uint64_t value;
102 char *error;
103
104 if (SYSINFO_RET_OK != get_disk_stats(devname, &value, NULL, NULL, NULL, &error))
105 {
106 SET_MSG_RESULT(result, error);
107 return SYSINFO_RET_FAIL;
108 }
109
110 SET_UI64_RESULT(result, value);
111
112 return SYSINFO_RET_OK;
113 }
114
VFS_DEV_READ_OPERATIONS(const char * devname,AGENT_RESULT * result)115 static int VFS_DEV_READ_OPERATIONS(const char *devname, AGENT_RESULT *result)
116 {
117 zbx_uint64_t value;
118 char *error;
119
120 if (SYSINFO_RET_OK != get_disk_stats(devname, NULL, NULL, &value, NULL, &error))
121 {
122 SET_MSG_RESULT(result, error);
123 return SYSINFO_RET_FAIL;
124 }
125
126 SET_UI64_RESULT(result, value);
127
128 return SYSINFO_RET_OK;
129 }
130
VFS_DEV_WRITE_BYTES(const char * devname,AGENT_RESULT * result)131 static int VFS_DEV_WRITE_BYTES(const char *devname, AGENT_RESULT *result)
132 {
133 zbx_uint64_t value;
134 char *error;
135
136 if (SYSINFO_RET_OK != get_disk_stats(devname, NULL, &value, NULL, NULL, &error))
137 {
138 SET_MSG_RESULT(result, error);
139 return SYSINFO_RET_FAIL;
140 }
141
142 SET_UI64_RESULT(result, value);
143
144 return SYSINFO_RET_OK;
145 }
146
VFS_DEV_WRITE_OPERATIONS(const char * devname,AGENT_RESULT * result)147 static int VFS_DEV_WRITE_OPERATIONS(const char *devname, AGENT_RESULT *result)
148 {
149 zbx_uint64_t value;
150 char *error;
151
152 if (SYSINFO_RET_OK != get_disk_stats(devname, NULL, NULL, NULL, &value, &error))
153 {
154 SET_MSG_RESULT(result, error);
155 return SYSINFO_RET_FAIL;
156 }
157
158 SET_UI64_RESULT(result, value);
159
160 return SYSINFO_RET_OK;
161 }
162
VFS_DEV_READ(AGENT_REQUEST * request,AGENT_RESULT * result)163 int VFS_DEV_READ(AGENT_REQUEST *request, AGENT_RESULT *result)
164 {
165 char *devname, *mode;
166 int ret;
167
168 if (2 < request->nparam)
169 {
170 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
171 return SYSINFO_RET_FAIL;
172 }
173
174 devname = get_rparam(request, 0);
175 mode = get_rparam(request, 1);
176
177 if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "operations"))
178 ret = VFS_DEV_READ_OPERATIONS(devname, result);
179 else if (0 == strcmp(mode, "bytes"))
180 ret = VFS_DEV_READ_BYTES(devname, result);
181 else
182 {
183 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
184 return SYSINFO_RET_FAIL;
185 }
186
187 return ret;
188 }
189
VFS_DEV_WRITE(AGENT_REQUEST * request,AGENT_RESULT * result)190 int VFS_DEV_WRITE(AGENT_REQUEST *request, AGENT_RESULT *result)
191 {
192 char *devname, *mode;
193 int ret;
194
195 if (2 < request->nparam)
196 {
197 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
198 return SYSINFO_RET_FAIL;
199 }
200
201 devname = get_rparam(request, 0);
202 mode = get_rparam(request, 1);
203
204 if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "operations"))
205 ret = VFS_DEV_WRITE_OPERATIONS(devname, result);
206 else if (0 == strcmp(mode, "bytes"))
207 ret = VFS_DEV_WRITE_BYTES(devname, result);
208 else
209 {
210 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
211 return SYSINFO_RET_FAIL;
212 }
213
214 return ret;
215 }
216