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 
24 #include <uvm/uvm_extern.h>
25 
26 static int			mib[] = {CTL_VM, VM_UVMEXP2};
27 static size_t			len;
28 static struct uvmexp_sysctl	uvm;
29 
30 #define ZBX_SYSCTL(value)										\
31 													\
32 	len = sizeof(value);										\
33 	if (0 != sysctl(mib, 2, &value, &len, NULL, 0))							\
34 	{												\
35 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s",	\
36 				zbx_strerror(errno)));							\
37 		return SYSINFO_RET_FAIL;								\
38 	}
39 
VM_MEMORY_TOTAL(AGENT_RESULT * result)40 static int	VM_MEMORY_TOTAL(AGENT_RESULT *result)
41 {
42 	ZBX_SYSCTL(uvm);
43 
44 	SET_UI64_RESULT(result, uvm.npages << uvm.pageshift);
45 
46 	return SYSINFO_RET_OK;
47 }
48 
VM_MEMORY_ACTIVE(AGENT_RESULT * result)49 static int	VM_MEMORY_ACTIVE(AGENT_RESULT *result)
50 {
51 	ZBX_SYSCTL(uvm);
52 
53 	SET_UI64_RESULT(result, uvm.active << uvm.pageshift);
54 
55 	return SYSINFO_RET_OK;
56 }
57 
VM_MEMORY_INACTIVE(AGENT_RESULT * result)58 static int	VM_MEMORY_INACTIVE(AGENT_RESULT *result)
59 {
60 	ZBX_SYSCTL(uvm);
61 
62 	SET_UI64_RESULT(result, uvm.inactive << uvm.pageshift);
63 
64 	return SYSINFO_RET_OK;
65 }
66 
VM_MEMORY_WIRED(AGENT_RESULT * result)67 static int	VM_MEMORY_WIRED(AGENT_RESULT *result)
68 {
69 	ZBX_SYSCTL(uvm);
70 
71 	SET_UI64_RESULT(result, uvm.wired << uvm.pageshift);
72 
73 	return SYSINFO_RET_OK;
74 }
75 
VM_MEMORY_ANON(AGENT_RESULT * result)76 static int	VM_MEMORY_ANON(AGENT_RESULT *result)
77 {
78 	ZBX_SYSCTL(uvm);
79 
80 	SET_UI64_RESULT(result, uvm.anonpages << uvm.pageshift);
81 
82 	return SYSINFO_RET_OK;
83 }
84 
VM_MEMORY_EXEC(AGENT_RESULT * result)85 static int	VM_MEMORY_EXEC(AGENT_RESULT *result)
86 {
87 	ZBX_SYSCTL(uvm);
88 
89 	SET_UI64_RESULT(result, uvm.execpages << uvm.pageshift);
90 
91 	return SYSINFO_RET_OK;
92 }
93 
VM_MEMORY_FILE(AGENT_RESULT * result)94 static int	VM_MEMORY_FILE(AGENT_RESULT *result)
95 {
96 	ZBX_SYSCTL(uvm);
97 
98 	SET_UI64_RESULT(result, uvm.filepages << uvm.pageshift);
99 
100 	return SYSINFO_RET_OK;
101 }
102 
VM_MEMORY_FREE(AGENT_RESULT * result)103 static int	VM_MEMORY_FREE(AGENT_RESULT *result)
104 {
105 	ZBX_SYSCTL(uvm);
106 
107 	SET_UI64_RESULT(result, uvm.free << uvm.pageshift);
108 
109 	return SYSINFO_RET_OK;
110 }
111 
VM_MEMORY_USED(AGENT_RESULT * result)112 static int	VM_MEMORY_USED(AGENT_RESULT *result)
113 {
114 	ZBX_SYSCTL(uvm);
115 
116 	SET_UI64_RESULT(result, (uvm.npages - uvm.free) << uvm.pageshift);
117 
118 	return SYSINFO_RET_OK;
119 }
120 
VM_MEMORY_PUSED(AGENT_RESULT * result)121 static int	VM_MEMORY_PUSED(AGENT_RESULT *result)
122 {
123 	ZBX_SYSCTL(uvm);
124 
125 	if (0 == uvm.npages)
126 	{
127 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero."));
128 		return SYSINFO_RET_FAIL;
129 	}
130 
131 	SET_DBL_RESULT(result, (uvm.npages - uvm.free) / (double)uvm.npages * 100);
132 
133 	return SYSINFO_RET_OK;
134 }
135 
VM_MEMORY_AVAILABLE(AGENT_RESULT * result)136 static int	VM_MEMORY_AVAILABLE(AGENT_RESULT *result)
137 {
138 	zbx_uint64_t	available;
139 
140 	ZBX_SYSCTL(uvm);
141 
142 	available = uvm.inactive + uvm.execpages + uvm.filepages + uvm.free;
143 
144 	SET_UI64_RESULT(result, available << uvm.pageshift);
145 
146 	return SYSINFO_RET_OK;
147 }
148 
VM_MEMORY_PAVAILABLE(AGENT_RESULT * result)149 static int	VM_MEMORY_PAVAILABLE(AGENT_RESULT *result)
150 {
151 	zbx_uint64_t	available;
152 
153 	ZBX_SYSCTL(uvm);
154 
155 	if (0 == uvm.npages)
156 	{
157 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero."));
158 		return SYSINFO_RET_FAIL;
159 	}
160 
161 	available = uvm.inactive + uvm.execpages + uvm.filepages + uvm.free;
162 
163 	SET_DBL_RESULT(result, available / (double)uvm.npages * 100);
164 
165 	return SYSINFO_RET_OK;
166 }
167 
VM_MEMORY_BUFFERS(AGENT_RESULT * result)168 static int	VM_MEMORY_BUFFERS(AGENT_RESULT *result)
169 {
170 	int	mib[] = {CTL_VM, VM_NKMEMPAGES}, pages;
171 
172 	ZBX_SYSCTL(pages);
173 
174 	SET_UI64_RESULT(result, (zbx_uint64_t)pages * sysconf(_SC_PAGESIZE));
175 
176 	return SYSINFO_RET_OK;
177 }
178 
VM_MEMORY_CACHED(AGENT_RESULT * result)179 static int	VM_MEMORY_CACHED(AGENT_RESULT *result)
180 {
181 	ZBX_SYSCTL(uvm);
182 
183 	SET_UI64_RESULT(result, (uvm.execpages + uvm.filepages) << uvm.pageshift);
184 
185 	return SYSINFO_RET_OK;
186 }
187 
VM_MEMORY_SHARED(AGENT_RESULT * result)188 static int	VM_MEMORY_SHARED(AGENT_RESULT *result)
189 {
190 	int		mib[] = {CTL_VM, VM_METER};
191 	struct vmtotal	vm;
192 
193 	ZBX_SYSCTL(vm);
194 
195 	SET_UI64_RESULT(result, (zbx_uint64_t)(vm.t_vmshr + vm.t_rmshr) * sysconf(_SC_PAGESIZE));
196 
197 	return SYSINFO_RET_OK;
198 }
199 
VM_MEMORY_SIZE(AGENT_REQUEST * request,AGENT_RESULT * result)200 int     VM_MEMORY_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
201 {
202 	char	*mode;
203 	int	ret = SYSINFO_RET_FAIL;
204 
205 	if (1 < request->nparam)
206 	{
207 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
208 		return SYSINFO_RET_FAIL;
209 	}
210 
211 	mode = get_rparam(request, 0);
212 
213 	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))
214 		ret = VM_MEMORY_TOTAL(result);
215 	else if (0 == strcmp(mode, "active"))
216 		ret = VM_MEMORY_ACTIVE(result);
217 	else if (0 == strcmp(mode, "inactive"))
218 		ret = VM_MEMORY_INACTIVE(result);
219 	else if (0 == strcmp(mode, "wired"))
220 		ret = VM_MEMORY_WIRED(result);
221 	else if (0 == strcmp(mode, "anon"))
222 		ret = VM_MEMORY_ANON(result);
223 	else if (0 == strcmp(mode, "exec"))
224 		ret = VM_MEMORY_EXEC(result);
225 	else if (0 == strcmp(mode, "file"))
226 		ret = VM_MEMORY_FILE(result);
227 	else if (0 == strcmp(mode, "free"))
228 		ret = VM_MEMORY_FREE(result);
229 	else if (0 == strcmp(mode, "used"))
230 		ret = VM_MEMORY_USED(result);
231 	else if (0 == strcmp(mode, "pused"))
232 		ret = VM_MEMORY_PUSED(result);
233 	else if (0 == strcmp(mode, "available"))
234 		ret = VM_MEMORY_AVAILABLE(result);
235 	else if (0 == strcmp(mode, "pavailable"))
236 		ret = VM_MEMORY_PAVAILABLE(result);
237 	else if (0 == strcmp(mode, "buffers"))
238 		ret = VM_MEMORY_BUFFERS(result);
239 	else if (0 == strcmp(mode, "cached"))
240 		ret = VM_MEMORY_CACHED(result);
241 	else if (0 == strcmp(mode, "shared"))
242 		ret = VM_MEMORY_SHARED(result);
243 	else
244 	{
245 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
246 		ret = SYSINFO_RET_FAIL;
247 	}
248 
249 	return ret;
250 }
251