ia64/linux-2.6.18-xen.hg

view scripts/kconfig/menu.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 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
6 #include <stdlib.h>
7 #include <string.h>
9 #define LKC_DIRECT_LINK
10 #include "lkc.h"
12 struct menu rootmenu;
13 static struct menu **last_entry_ptr;
15 struct file *file_list;
16 struct file *current_file;
18 static void menu_warn(struct menu *menu, const char *fmt, ...)
19 {
20 va_list ap;
21 va_start(ap, fmt);
22 fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
23 vfprintf(stderr, fmt, ap);
24 fprintf(stderr, "\n");
25 va_end(ap);
26 }
28 static void prop_warn(struct property *prop, const char *fmt, ...)
29 {
30 va_list ap;
31 va_start(ap, fmt);
32 fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
33 vfprintf(stderr, fmt, ap);
34 fprintf(stderr, "\n");
35 va_end(ap);
36 }
38 void menu_init(void)
39 {
40 current_entry = current_menu = &rootmenu;
41 last_entry_ptr = &rootmenu.list;
42 }
44 void menu_add_entry(struct symbol *sym)
45 {
46 struct menu *menu;
48 menu = malloc(sizeof(*menu));
49 memset(menu, 0, sizeof(*menu));
50 menu->sym = sym;
51 menu->parent = current_menu;
52 menu->file = current_file;
53 menu->lineno = zconf_lineno();
55 *last_entry_ptr = menu;
56 last_entry_ptr = &menu->next;
57 current_entry = menu;
58 }
60 void menu_end_entry(void)
61 {
62 }
64 struct menu *menu_add_menu(void)
65 {
66 menu_end_entry();
67 last_entry_ptr = &current_entry->list;
68 return current_menu = current_entry;
69 }
71 void menu_end_menu(void)
72 {
73 last_entry_ptr = &current_menu->next;
74 current_menu = current_menu->parent;
75 }
77 struct expr *menu_check_dep(struct expr *e)
78 {
79 if (!e)
80 return e;
82 switch (e->type) {
83 case E_NOT:
84 e->left.expr = menu_check_dep(e->left.expr);
85 break;
86 case E_OR:
87 case E_AND:
88 e->left.expr = menu_check_dep(e->left.expr);
89 e->right.expr = menu_check_dep(e->right.expr);
90 break;
91 case E_SYMBOL:
92 /* change 'm' into 'm' && MODULES */
93 if (e->left.sym == &symbol_mod)
94 return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
95 break;
96 default:
97 break;
98 }
99 return e;
100 }
102 void menu_add_dep(struct expr *dep)
103 {
104 current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
105 }
107 void menu_set_type(int type)
108 {
109 struct symbol *sym = current_entry->sym;
111 if (sym->type == type)
112 return;
113 if (sym->type == S_UNKNOWN) {
114 sym->type = type;
115 return;
116 }
117 menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
118 sym->name ? sym->name : "<choice>",
119 sym_type_name(sym->type), sym_type_name(type));
120 }
122 struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
123 {
124 struct property *prop = prop_alloc(type, current_entry->sym);
126 prop->menu = current_entry;
127 prop->expr = expr;
128 prop->visible.expr = menu_check_dep(dep);
130 if (prompt) {
131 if (isspace(*prompt)) {
132 prop_warn(prop, "leading whitespace ignored");
133 while (isspace(*prompt))
134 prompt++;
135 }
136 if (current_entry->prompt)
137 prop_warn(prop, "prompt redefined");
138 current_entry->prompt = prop;
139 }
140 prop->text = prompt;
142 return prop;
143 }
145 struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
146 {
147 return menu_add_prop(type, prompt, NULL, dep);
148 }
150 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
151 {
152 menu_add_prop(type, NULL, expr, dep);
153 }
155 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
156 {
157 menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
158 }
160 void menu_add_option(int token, char *arg)
161 {
162 struct property *prop;
164 switch (token) {
165 case T_OPT_MODULES:
166 prop = prop_alloc(P_DEFAULT, modules_sym);
167 prop->expr = expr_alloc_symbol(current_entry->sym);
168 break;
169 case T_OPT_DEFCONFIG_LIST:
170 if (!sym_defconfig_list)
171 sym_defconfig_list = current_entry->sym;
172 else if (sym_defconfig_list != current_entry->sym)
173 zconf_error("trying to redefine defconfig symbol");
174 break;
175 }
176 }
178 static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
179 {
180 return sym2->type == S_INT || sym2->type == S_HEX ||
181 (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
182 }
184 void sym_check_prop(struct symbol *sym)
185 {
186 struct property *prop;
187 struct symbol *sym2;
188 for (prop = sym->prop; prop; prop = prop->next) {
189 switch (prop->type) {
190 case P_DEFAULT:
191 if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
192 prop->expr->type != E_SYMBOL)
193 prop_warn(prop,
194 "default for config symbol '%'"
195 " must be a single symbol", sym->name);
196 break;
197 case P_SELECT:
198 sym2 = prop_get_symbol(prop);
199 if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
200 prop_warn(prop,
201 "config symbol '%s' uses select, but is "
202 "not boolean or tristate", sym->name);
203 else if (sym2->type == S_UNKNOWN)
204 prop_warn(prop,
205 "'select' used by config symbol '%s' "
206 "refer to undefined symbol '%s'",
207 sym->name, sym2->name);
208 else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
209 prop_warn(prop,
210 "'%s' has wrong type. 'select' only "
211 "accept arguments of boolean and "
212 "tristate type", sym2->name);
213 break;
214 case P_RANGE:
215 if (sym->type != S_INT && sym->type != S_HEX)
216 prop_warn(prop, "range is only allowed "
217 "for int or hex symbols");
218 if (!menu_range_valid_sym(sym, prop->expr->left.sym) ||
219 !menu_range_valid_sym(sym, prop->expr->right.sym))
220 prop_warn(prop, "range is invalid");
221 break;
222 default:
223 ;
224 }
225 }
226 }
228 void menu_finalize(struct menu *parent)
229 {
230 struct menu *menu, *last_menu;
231 struct symbol *sym;
232 struct property *prop;
233 struct expr *parentdep, *basedep, *dep, *dep2, **ep;
235 sym = parent->sym;
236 if (parent->list) {
237 if (sym && sym_is_choice(sym)) {
238 /* find the first choice value and find out choice type */
239 for (menu = parent->list; menu; menu = menu->next) {
240 if (menu->sym) {
241 current_entry = parent;
242 menu_set_type(menu->sym->type);
243 current_entry = menu;
244 menu_set_type(sym->type);
245 break;
246 }
247 }
248 parentdep = expr_alloc_symbol(sym);
249 } else if (parent->prompt)
250 parentdep = parent->prompt->visible.expr;
251 else
252 parentdep = parent->dep;
254 for (menu = parent->list; menu; menu = menu->next) {
255 basedep = expr_transform(menu->dep);
256 basedep = expr_alloc_and(expr_copy(parentdep), basedep);
257 basedep = expr_eliminate_dups(basedep);
258 menu->dep = basedep;
259 if (menu->sym)
260 prop = menu->sym->prop;
261 else
262 prop = menu->prompt;
263 for (; prop; prop = prop->next) {
264 if (prop->menu != menu)
265 continue;
266 dep = expr_transform(prop->visible.expr);
267 dep = expr_alloc_and(expr_copy(basedep), dep);
268 dep = expr_eliminate_dups(dep);
269 if (menu->sym && menu->sym->type != S_TRISTATE)
270 dep = expr_trans_bool(dep);
271 prop->visible.expr = dep;
272 if (prop->type == P_SELECT) {
273 struct symbol *es = prop_get_symbol(prop);
274 es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
275 expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
276 }
277 }
278 }
279 for (menu = parent->list; menu; menu = menu->next)
280 menu_finalize(menu);
281 } else if (sym) {
282 basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
283 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
284 basedep = expr_eliminate_dups(expr_transform(basedep));
285 last_menu = NULL;
286 for (menu = parent->next; menu; menu = menu->next) {
287 dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
288 if (!expr_contains_symbol(dep, sym))
289 break;
290 if (expr_depends_symbol(dep, sym))
291 goto next;
292 dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
293 dep = expr_eliminate_dups(expr_transform(dep));
294 dep2 = expr_copy(basedep);
295 expr_eliminate_eq(&dep, &dep2);
296 expr_free(dep);
297 if (!expr_is_yes(dep2)) {
298 expr_free(dep2);
299 break;
300 }
301 expr_free(dep2);
302 next:
303 menu_finalize(menu);
304 menu->parent = parent;
305 last_menu = menu;
306 }
307 if (last_menu) {
308 parent->list = parent->next;
309 parent->next = last_menu->next;
310 last_menu->next = NULL;
311 }
312 }
313 for (menu = parent->list; menu; menu = menu->next) {
314 if (sym && sym_is_choice(sym) && menu->sym) {
315 menu->sym->flags |= SYMBOL_CHOICEVAL;
316 if (!menu->prompt)
317 menu_warn(menu, "choice value must have a prompt");
318 for (prop = menu->sym->prop; prop; prop = prop->next) {
319 if (prop->type == P_PROMPT && prop->menu != menu) {
320 prop_warn(prop, "choice values "
321 "currently only support a "
322 "single prompt");
323 }
324 if (prop->type == P_DEFAULT)
325 prop_warn(prop, "defaults for choice "
326 "values not supported");
327 }
328 current_entry = menu;
329 menu_set_type(sym->type);
330 menu_add_symbol(P_CHOICE, sym, NULL);
331 prop = sym_get_choice_prop(sym);
332 for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
333 ;
334 *ep = expr_alloc_one(E_CHOICE, NULL);
335 (*ep)->right.sym = menu->sym;
336 }
337 if (menu->list && (!menu->prompt || !menu->prompt->text)) {
338 for (last_menu = menu->list; ; last_menu = last_menu->next) {
339 last_menu->parent = parent;
340 if (!last_menu->next)
341 break;
342 }
343 last_menu->next = menu->next;
344 menu->next = menu->list;
345 menu->list = NULL;
346 }
347 }
349 if (sym && !(sym->flags & SYMBOL_WARNED)) {
350 if (sym->type == S_UNKNOWN)
351 menu_warn(parent, "config symbol defined without type");
353 if (sym_is_choice(sym) && !parent->prompt)
354 menu_warn(parent, "choice must have a prompt");
356 /* Check properties connected to this symbol */
357 sym_check_prop(sym);
358 sym->flags |= SYMBOL_WARNED;
359 }
361 if (sym && !sym_is_optional(sym) && parent->prompt) {
362 sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
363 expr_alloc_and(parent->prompt->visible.expr,
364 expr_alloc_symbol(&symbol_mod)));
365 }
366 }
368 bool menu_is_visible(struct menu *menu)
369 {
370 struct menu *child;
371 struct symbol *sym;
372 tristate visible;
374 if (!menu->prompt)
375 return false;
376 sym = menu->sym;
377 if (sym) {
378 sym_calc_value(sym);
379 visible = menu->prompt->visible.tri;
380 } else
381 visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
383 if (visible != no)
384 return true;
385 if (!sym || sym_get_tristate_value(menu->sym) == no)
386 return false;
388 for (child = menu->list; child; child = child->next)
389 if (menu_is_visible(child))
390 return true;
391 return false;
392 }
394 const char *menu_get_prompt(struct menu *menu)
395 {
396 if (menu->prompt)
397 return _(menu->prompt->text);
398 else if (menu->sym)
399 return _(menu->sym->name);
400 return NULL;
401 }
403 struct menu *menu_get_root_menu(struct menu *menu)
404 {
405 return &rootmenu;
406 }
408 struct menu *menu_get_parent_menu(struct menu *menu)
409 {
410 enum prop_type type;
412 for (; menu != &rootmenu; menu = menu->parent) {
413 type = menu->prompt ? menu->prompt->type : 0;
414 if (type == P_MENU)
415 break;
416 }
417 return menu;
418 }