ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/srm_env.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /*
2 * srm_env.c - Access to SRM environment
3 * variables through linux' procfs
4 *
5 * Copyright (C) 2001-2002 Jan-Benedict Glaw <jbglaw@lug-owl.de>
6 *
7 * This driver is at all a modified version of Erik Mouw's
8 * Documentation/DocBook/procfs_example.c, so: thank
9 * you, Erik! He can be reached via email at
10 * <J.A.K.Mouw@its.tudelft.nl>. It is based on an idea
11 * provided by DEC^WCompaq^WIntel's "Jumpstart" CD. They
12 * included a patch like this as well. Thanks for idea!
13 *
14 * This program is free software; you can redistribute
15 * it and/or modify it under the terms of the GNU General
16 * Public License version 2 as published by the Free Software
17 * Foundation.
18 *
19 * This program is distributed in the hope that it will be
20 * useful, but WITHOUT ANY WARRANTY; without even the implied
21 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
22 * PURPOSE. See the GNU General Public License for more
23 * details.
24 *
25 * You should have received a copy of the GNU General Public
26 * License along with this program; if not, write to the
27 * Free Software Foundation, Inc., 59 Temple Place,
28 * Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
32 /*
33 * Changelog
34 * ~~~~~~~~~
35 *
36 * Thu, 22 Aug 2002 15:10:43 +0200
37 * - Update Config.help entry. I got a number of emails asking
38 * me to tell their senders if they could make use of this
39 * piece of code... So: "SRM is something like BIOS for your
40 * Alpha"
41 * - Update code formatting a bit to better conform CodingStyle
42 * rules.
43 * - So this is v0.0.5, with no changes (except formatting)
44 *
45 * Wed, 22 May 2002 00:11:21 +0200
46 * - Fix typo on comment (SRC -> SRM)
47 * - Call this "Version 0.0.4"
48 *
49 * Tue, 9 Apr 2002 18:44:40 +0200
50 * - Implement access by variable name and additionally
51 * by number. This is done by creating two subdirectories
52 * where one holds all names (like the old directory
53 * did) and the other holding 256 files named like "0",
54 * "1" and so on.
55 * - Call this "Version 0.0.3"
56 *
57 */
59 #include <linux/kernel.h>
60 #include <linux/module.h>
61 #include <linux/init.h>
62 #include <linux/proc_fs.h>
63 #include <asm/console.h>
64 #include <asm/uaccess.h>
65 #include <asm/machvec.h>
67 #define BASE_DIR "srm_environment" /* Subdir in /proc/ */
68 #define NAMED_DIR "named_variables" /* Subdir for known variables */
69 #define NUMBERED_DIR "numbered_variables" /* Subdir for all variables */
70 #define VERSION "0.0.5" /* Module version */
71 #define NAME "srm_env" /* Module name */
73 MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
74 MODULE_DESCRIPTION("Accessing Alpha SRM environment through procfs interface");
75 MODULE_LICENSE("GPL");
77 typedef struct _srm_env {
78 char *name;
79 unsigned long id;
80 struct proc_dir_entry *proc_entry;
81 } srm_env_t;
83 static struct proc_dir_entry *base_dir;
84 static struct proc_dir_entry *named_dir;
85 static struct proc_dir_entry *numbered_dir;
86 static char number[256][4];
88 static srm_env_t srm_named_entries[] = {
89 { "auto_action", ENV_AUTO_ACTION },
90 { "boot_dev", ENV_BOOT_DEV },
91 { "bootdef_dev", ENV_BOOTDEF_DEV },
92 { "booted_dev", ENV_BOOTED_DEV },
93 { "boot_file", ENV_BOOT_FILE },
94 { "booted_file", ENV_BOOTED_FILE },
95 { "boot_osflags", ENV_BOOT_OSFLAGS },
96 { "booted_osflags", ENV_BOOTED_OSFLAGS },
97 { "boot_reset", ENV_BOOT_RESET },
98 { "dump_dev", ENV_DUMP_DEV },
99 { "enable_audit", ENV_ENABLE_AUDIT },
100 { "license", ENV_LICENSE },
101 { "char_set", ENV_CHAR_SET },
102 { "language", ENV_LANGUAGE },
103 { "tty_dev", ENV_TTY_DEV },
104 { NULL, 0 },
105 };
106 static srm_env_t srm_numbered_entries[256];
110 static int
111 srm_env_read(char *page, char **start, off_t off, int count, int *eof,
112 void *data)
113 {
114 int nbytes;
115 unsigned long ret;
116 srm_env_t *entry;
118 if(off != 0)
119 return -EFAULT;
121 entry = (srm_env_t *) data;
122 ret = callback_getenv(entry->id, page, count);
124 if((ret >> 61) == 0)
125 nbytes = (int) ret;
126 else
127 nbytes = -EFAULT;
129 return nbytes;
130 }
133 static int
134 srm_env_write(struct file *file, const char __user *buffer, unsigned long count,
135 void *data)
136 {
137 int res;
138 srm_env_t *entry;
139 char *buf = (char *) __get_free_page(GFP_USER);
140 unsigned long ret1, ret2;
142 entry = (srm_env_t *) data;
144 if (!buf)
145 return -ENOMEM;
147 res = -EINVAL;
148 if (count >= PAGE_SIZE)
149 goto out;
151 res = -EFAULT;
152 if (copy_from_user(buf, buffer, count))
153 goto out;
154 buf[count] = '\0';
156 ret1 = callback_setenv(entry->id, buf, count);
157 if ((ret1 >> 61) == 0) {
158 do
159 ret2 = callback_save_env();
160 while((ret2 >> 61) == 1);
161 res = (int) ret1;
162 }
164 out:
165 free_page((unsigned long)buf);
166 return res;
167 }
169 static void
170 srm_env_cleanup(void)
171 {
172 srm_env_t *entry;
173 unsigned long var_num;
175 if(base_dir) {
176 /*
177 * Remove named entries
178 */
179 if(named_dir) {
180 entry = srm_named_entries;
181 while(entry->name != NULL && entry->id != 0) {
182 if(entry->proc_entry) {
183 remove_proc_entry(entry->name,
184 named_dir);
185 entry->proc_entry = NULL;
186 }
187 entry++;
188 }
189 remove_proc_entry(NAMED_DIR, base_dir);
190 }
192 /*
193 * Remove numbered entries
194 */
195 if(numbered_dir) {
196 for(var_num = 0; var_num <= 255; var_num++) {
197 entry = &srm_numbered_entries[var_num];
199 if(entry->proc_entry) {
200 remove_proc_entry(entry->name,
201 numbered_dir);
202 entry->proc_entry = NULL;
203 entry->name = NULL;
204 }
205 }
206 remove_proc_entry(NUMBERED_DIR, base_dir);
207 }
209 remove_proc_entry(BASE_DIR, NULL);
210 }
212 return;
213 }
216 static int __init
217 srm_env_init(void)
218 {
219 srm_env_t *entry;
220 unsigned long var_num;
222 /*
223 * Check system
224 */
225 if(!alpha_using_srm) {
226 printk(KERN_INFO "%s: This Alpha system doesn't "
227 "know about SRM (or you've booted "
228 "SRM->MILO->Linux, which gets "
229 "misdetected)...\n", __FUNCTION__);
230 return -ENODEV;
231 }
233 /*
234 * Init numbers
235 */
236 for(var_num = 0; var_num <= 255; var_num++)
237 sprintf(number[var_num], "%ld", var_num);
239 /*
240 * Create base directory
241 */
242 base_dir = proc_mkdir(BASE_DIR, NULL);
243 if(base_dir == NULL) {
244 printk(KERN_ERR "Couldn't create base dir /proc/%s\n",
245 BASE_DIR);
246 goto cleanup;
247 }
248 base_dir->owner = THIS_MODULE;
250 /*
251 * Create per-name subdirectory
252 */
253 named_dir = proc_mkdir(NAMED_DIR, base_dir);
254 if(named_dir == NULL) {
255 printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
256 BASE_DIR, NAMED_DIR);
257 goto cleanup;
258 }
259 named_dir->owner = THIS_MODULE;
261 /*
262 * Create per-number subdirectory
263 */
264 numbered_dir = proc_mkdir(NUMBERED_DIR, base_dir);
265 if(numbered_dir == NULL) {
266 printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
267 BASE_DIR, NUMBERED_DIR);
268 goto cleanup;
270 }
271 numbered_dir->owner = THIS_MODULE;
273 /*
274 * Create all named nodes
275 */
276 entry = srm_named_entries;
277 while(entry->name != NULL && entry->id != 0) {
278 entry->proc_entry = create_proc_entry(entry->name,
279 0644, named_dir);
280 if(entry->proc_entry == NULL)
281 goto cleanup;
283 entry->proc_entry->data = (void *) entry;
284 entry->proc_entry->owner = THIS_MODULE;
285 entry->proc_entry->read_proc = srm_env_read;
286 entry->proc_entry->write_proc = srm_env_write;
288 entry++;
289 }
291 /*
292 * Create all numbered nodes
293 */
294 for(var_num = 0; var_num <= 255; var_num++) {
295 entry = &srm_numbered_entries[var_num];
296 entry->name = number[var_num];
298 entry->proc_entry = create_proc_entry(entry->name,
299 0644, numbered_dir);
300 if(entry->proc_entry == NULL)
301 goto cleanup;
303 entry->id = var_num;
304 entry->proc_entry->data = (void *) entry;
305 entry->proc_entry->owner = THIS_MODULE;
306 entry->proc_entry->read_proc = srm_env_read;
307 entry->proc_entry->write_proc = srm_env_write;
308 }
310 printk(KERN_INFO "%s: version %s loaded successfully\n", NAME,
311 VERSION);
313 return 0;
315 cleanup:
316 srm_env_cleanup();
318 return -ENOMEM;
319 }
322 static void __exit
323 srm_env_exit(void)
324 {
325 srm_env_cleanup();
326 printk(KERN_INFO "%s: unloaded successfully\n", NAME);
328 return;
329 }
332 module_init(srm_env_init);
333 module_exit(srm_env_exit);