Import version 1.8.3
[s390-tools.git] / cpuplugd / mem.c
bloba8f2a8e3882df481ee7b69cc032f25a5b7fd6b87
1 /*
2 * Copyright IBM Corp 2007
3 * Author: Hans-Joachim Picht <hans@linux.vnet.ibm.com>
5 * Linux for System z Hotplug Daemon
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <ctype.h>
20 #include <getopt.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <sys/stat.h>
28 #include <sys/wait.h>
29 #include <sys/types.h>
30 #include <signal.h>
31 #include <syslog.h>
32 #include <pthread.h>
33 #include <linux/param.h>
34 #include <assert.h>
35 #include <fcntl.h>
36 #include <limits.h>
37 #include <termios.h>
38 #include <sys/types.h>
39 #include <sys/ioctl.h>
40 #include <sys/dir.h>
41 #include <dirent.h>
42 #include "cpuplugd.h"
45 * return page in and out as well as the page
46 * swap in and out rate based on /proc/vmstat
48 int get_vmstats(struct vm_info *v)
50 FILE *filp;
51 size_t bytes_read;
52 char buffer[2048];
53 char *match_pgpgout;
54 char *match_pswpout;
55 char *match_pgpgin;
56 char *match_pswpin;
57 int pgpgout; /* page out */
58 int pswpout; /* page swap out */
59 int pswpin; /* page swap in */
60 int pgpgin; /* page in */
61 int rc;
63 filp = fopen("/proc/vmstat", "r");
64 if (!filp) {
65 fprintf(stderr, "Can not open /proc/vmstat:");
66 fprintf(stderr, "%s\n", strerror(errno));
67 if (foreground == 0)
68 syslog(LOG_ERR, "Can not open /proc/vmstat"
69 ":%s\n", strerror(errno));
70 rc = -1;
71 goto out;
73 bytes_read = fread(buffer, 1, sizeof(buffer), filp);
75 * Bail if read failed or the buffer isn't big enough
77 if (bytes_read == 0) {
78 fprintf(stderr, "Reading /proc/vmstat failed:");
79 fprintf(stderr, "%s\n", strerror(errno));
80 if (foreground == 0)
81 syslog(LOG_ERR, "Reading /proc/vmstat failed"
82 ":%s\n", strerror(errno));
83 rc = -1;
84 goto outc;
87 * NUL-terminate the text
89 buffer[bytes_read] = '\0';
90 match_pgpgout = strstr(buffer, "pgpgout");
91 match_pswpout = strstr(buffer, "pswpout");
92 match_pgpgin = strstr(buffer, "pgpgin");
93 match_pswpin = strstr(buffer, "pswpin");
94 if (match_pgpgout == NULL || match_pswpout == NULL ||
95 match_pgpgin == NULL || match_pswpin == NULL) {
96 rc = -1;
97 goto outc;
99 sscanf(match_pgpgout, "pgpgout %d", &pgpgout);
100 sscanf(match_pswpout, "pswpout %d", &pswpout);
101 sscanf(match_pgpgin, "pgpgin %d", &pgpgin);
102 sscanf(match_pswpin, "pswpin %d", &pswpin);
103 v->pgpgout = pgpgout;
104 v->pswpout = pswpout;
105 v->pgpgin = pgpgin;
106 v->pswpin = pswpin;
107 rc = 0;
108 outc:
109 fclose(filp);
110 out:
111 return rc;
115 * The cmm_pages value defines the size of the balloon of blocked memory.
116 * Increasing the value is removing memory from Linux, which is an memunplug.
117 * Decreasing the value is adding memory back to Linux, which is memplug.
121 * increase number of pages permanently reserved
123 int memunplug(int size)
125 int old_size, new_size;
126 FILE *filp;
128 old_size = get_cmmpages_size();
130 * new value: previous value + size
132 new_size = old_size + size;
133 filp = fopen("/proc/sys/vm/cmm_pages", "w");
134 if (!filp) {
135 fprintf(stderr, "Can not open /proc/sys/vm/cmm_pages: %s\n",
136 strerror(errno));
137 if (foreground == 0)
138 syslog(LOG_ERR, "Can not open /proc/sys/vm/cmm_pages"
139 ":%s\n", strerror(errno));
140 return -1;
142 fprintf(filp, "%d\n", new_size);
143 if (debug && foreground == 1)
144 printf("changed number of pages permanently reserved "
145 "to %d \n", new_size);
146 if (debug && foreground == 0)
147 syslog(LOG_INFO, "changed number of pages permanently"
148 " reserved to %d \n", new_size);
149 fclose(filp);
150 return 1;
154 * decrease number of pages permanently reserved
156 int memplug(int size)
158 int old_size, new_size;
159 FILE *filp;
161 old_size = get_cmmpages_size();
163 * new value: previous value - size
165 new_size = old_size - size;
166 if (new_size <= 0)
167 return -1;
168 filp = fopen("/proc/sys/vm/cmm_pages", "w");
169 if (!filp) {
170 fprintf(stderr, "Can not open /proc/sys/vm/cmmpages: %s\n",
171 strerror(errno));
172 if (foreground == 0)
173 syslog(LOG_ERR, "Can not open /proc/sys/vm/cmm_pages"
174 ":%s\n", strerror(errno));
175 return -1;
177 fprintf(filp, "%d\n", new_size);
178 if (debug && foreground == 1)
179 printf("changed number of pages permanently reserved "
180 "to %d \n", new_size);
181 if (debug && foreground == 0)
182 syslog(LOG_INFO, "changed number of pages permanently"
183 "reserved to %d \n", new_size);
184 fclose(filp);
185 return 1;
189 * override the value of cmm_pages
191 int set_cmm_pages(int size)
193 FILE *filp;
195 filp = fopen("/proc/sys/vm/cmm_pages", "w");
196 if (!filp) {
197 fprintf(stderr, "Can not open /proc/sys/vm/cmmpages: %s\n",
198 strerror(errno));
199 if (foreground == 0)
200 syslog(LOG_ERR, "Can not open /proc/sys/vm/cmm_pages"
201 ":%s\n", strerror(errno));
202 return -1;
204 fprintf(filp, "%d\n", size);
205 if (debug && foreground == 1)
206 printf("changed number of pages permanently reserved "
207 "to %d \n", size);
208 if (debug && foreground == 0)
209 syslog(LOG_INFO, "changed number of pages permanently"
210 "reserved to %d \n", size);
211 fclose(filp);
212 return 1;
215 * read number of pages permanently reserved
217 int get_cmmpages_size()
219 FILE *filp;
220 int size;
221 int rc;
223 filp = fopen("/proc/sys/vm/cmm_pages", "r");
224 if (!filp) {
225 fprintf(stderr, "Can not open /proc/sys/vm/cmm_pages: %s\n",
226 strerror(errno));
227 if (foreground == 0)
228 syslog(LOG_ERR, "Can not open /proc/sys/vm/cmm_pages"
229 ":%s\n", strerror(errno));
230 return -1;
232 rc = fscanf(filp, "%d", &size);
233 if (rc != 0) {
234 fprintf(stderr, "Can not read /proc/sys/vm/cmm_pages: %s\n",
235 strerror(errno));
236 if (foreground == 0)
237 syslog(LOG_ERR, "Can not read /proc/sys/vm/cmm_pages"
238 ":%s\n", strerror(errno));
239 return -1;
241 fclose(filp);
242 return size;
248 * reset cmm pagesize to value we found prior to daemon startup
250 int cleanup_cmm()
252 FILE *filp;
254 filp = fopen("/proc/sys/vm/cmm_pages", "w");
255 if (!filp) {
256 fprintf(stderr, "Can not open /proc/sys/vm/cmm_pages: %s\n",
257 strerror(errno));
258 if (foreground == 0)
259 syslog(LOG_ERR, "Can not open /proc/sys/vm/cmm_pages"
260 ":%s\n", strerror(errno));
261 return -1;
263 fprintf(filp, "%d", cmm_pagesize_start);
264 if (debug && foreground == 1)
265 printf("changed number of pages permanently reserved"
266 " to %d \n", cmm_pagesize_start);
267 if (debug && foreground == 0)
268 syslog(LOG_INFO, "changed number of pages permanently "
269 " reserved to %d \n",
270 cmm_pagesize_start);
271 fclose(filp);
272 return 1;
279 * function to check if the cmm kernel module is loaded and the required
280 * files below /proc exit
282 int check_cmmfiles(void)
284 FILE *filp;
286 filp = fopen("/proc/sys/vm/cmm_pages", "r");
287 if (!filp)
288 return -1;
289 fclose(filp);
290 return 0;
295 * return amount of *free* memory as reported by
296 * /proc/meminfo
298 int get_free_memsize()
300 int size;
301 int rc;
302 FILE *filp;
303 size_t bytes_read;
304 char buffer[2048];
305 char *match;
307 size = 1;
308 rc = 1;
309 filp = fopen("/proc/meminfo", "r");
310 if (!filp) {
311 fprintf(stderr, "%s\n", strerror(errno));
312 if (foreground == 0)
313 syslog(LOG_ERR, "Can not open /proc/meminfo"
314 ":%s\n", strerror(errno));
315 clean_up();
317 bytes_read = fread(buffer, 1, sizeof(buffer), filp);
319 * Bail if read failed or the buffer isn't big enough
321 if (bytes_read == 0) {
322 fprintf(stderr, "Reading /proc/meminfo failed:");
323 fprintf(stderr, "%s\n", strerror(errno));
324 if (foreground == 0)
325 syslog(LOG_ERR, "Reading /proc/meminfo failed"
326 ":%s\n", strerror(errno));
327 clean_up();
329 buffer[bytes_read] = '\0';
331 * Locate the line that starts with
332 * "MemTotal".
334 match = strstr(buffer, "MemFree");
335 if (match == NULL) {
336 fprintf(stderr, "No MemFree entry found in /proc/meminfo\n");
337 clean_up();
338 } else {
340 * Parse the line to extract
341 * the amount of memory
343 rc = sscanf(match, "MemFree : %d", &size);
345 fclose(filp);
346 /* KB to MB */
347 if (rc == 1)
348 return size / 1024;
349 else
350 return -1;