ia64/linux-2.6.18-xen.hg

view drivers/acpi/utils.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 * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <acpi/acpi_bus.h>
31 #include <acpi/acpi_drivers.h>
33 #define _COMPONENT ACPI_BUS_COMPONENT
34 ACPI_MODULE_NAME("acpi_utils")
36 /* --------------------------------------------------------------------------
37 Object Evaluation Helpers
38 -------------------------------------------------------------------------- */
39 #ifdef ACPI_DEBUG_OUTPUT
40 #define acpi_util_eval_error(h,p,s) {\
41 char prefix[80] = {'\0'};\
42 struct acpi_buffer buffer = {sizeof(prefix), prefix};\
43 acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
44 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",\
45 (char *) prefix, p, acpi_format_exception(s))); }
46 #else
47 #define acpi_util_eval_error(h,p,s)
48 #endif
49 acpi_status
50 acpi_extract_package(union acpi_object *package,
51 struct acpi_buffer *format, struct acpi_buffer *buffer)
52 {
53 u32 size_required = 0;
54 u32 tail_offset = 0;
55 char *format_string = NULL;
56 u32 format_count = 0;
57 u32 i = 0;
58 u8 *head = NULL;
59 u8 *tail = NULL;
62 if (!package || (package->type != ACPI_TYPE_PACKAGE)
63 || (package->package.count < 1)) {
64 printk(KERN_WARNING PREFIX "Invalid package argument\n");
65 return AE_BAD_PARAMETER;
66 }
68 if (!format || !format->pointer || (format->length < 1)) {
69 printk(KERN_WARNING PREFIX "Invalid format argument\n");
70 return AE_BAD_PARAMETER;
71 }
73 if (!buffer) {
74 printk(KERN_WARNING PREFIX "Invalid buffer argument\n");
75 return AE_BAD_PARAMETER;
76 }
78 format_count = (format->length / sizeof(char)) - 1;
79 if (format_count > package->package.count) {
80 printk(KERN_WARNING PREFIX "Format specifies more objects [%d]"
81 " than exist in package [%d].\n",
82 format_count, package->package.count);
83 return AE_BAD_DATA;
84 }
86 format_string = (char *)format->pointer;
88 /*
89 * Calculate size_required.
90 */
91 for (i = 0; i < format_count; i++) {
93 union acpi_object *element = &(package->package.elements[i]);
95 if (!element) {
96 return AE_BAD_DATA;
97 }
99 switch (element->type) {
101 case ACPI_TYPE_INTEGER:
102 switch (format_string[i]) {
103 case 'N':
104 size_required += sizeof(acpi_integer);
105 tail_offset += sizeof(acpi_integer);
106 break;
107 case 'S':
108 size_required +=
109 sizeof(char *) + sizeof(acpi_integer) +
110 sizeof(char);
111 tail_offset += sizeof(char *);
112 break;
113 default:
114 printk(KERN_WARNING PREFIX "Invalid package element"
115 " [%d]: got number, expecing"
116 " [%c]\n",
117 i, format_string[i]);
118 return AE_BAD_DATA;
119 break;
120 }
121 break;
123 case ACPI_TYPE_STRING:
124 case ACPI_TYPE_BUFFER:
125 switch (format_string[i]) {
126 case 'S':
127 size_required +=
128 sizeof(char *) +
129 (element->string.length * sizeof(char)) +
130 sizeof(char);
131 tail_offset += sizeof(char *);
132 break;
133 case 'B':
134 size_required +=
135 sizeof(u8 *) +
136 (element->buffer.length * sizeof(u8));
137 tail_offset += sizeof(u8 *);
138 break;
139 default:
140 printk(KERN_WARNING PREFIX "Invalid package element"
141 " [%d] got string/buffer,"
142 " expecing [%c]\n",
143 i, format_string[i]);
144 return AE_BAD_DATA;
145 break;
146 }
147 break;
149 case ACPI_TYPE_PACKAGE:
150 default:
151 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
152 "Found unsupported element at index=%d\n",
153 i));
154 /* TBD: handle nested packages... */
155 return AE_SUPPORT;
156 break;
157 }
158 }
160 /*
161 * Validate output buffer.
162 */
163 if (buffer->length < size_required) {
164 buffer->length = size_required;
165 return AE_BUFFER_OVERFLOW;
166 } else if (buffer->length != size_required || !buffer->pointer) {
167 return AE_BAD_PARAMETER;
168 }
170 head = buffer->pointer;
171 tail = buffer->pointer + tail_offset;
173 /*
174 * Extract package data.
175 */
176 for (i = 0; i < format_count; i++) {
178 u8 **pointer = NULL;
179 union acpi_object *element = &(package->package.elements[i]);
181 if (!element) {
182 return AE_BAD_DATA;
183 }
185 switch (element->type) {
187 case ACPI_TYPE_INTEGER:
188 switch (format_string[i]) {
189 case 'N':
190 *((acpi_integer *) head) =
191 element->integer.value;
192 head += sizeof(acpi_integer);
193 break;
194 case 'S':
195 pointer = (u8 **) head;
196 *pointer = tail;
197 *((acpi_integer *) tail) =
198 element->integer.value;
199 head += sizeof(acpi_integer *);
200 tail += sizeof(acpi_integer);
201 /* NULL terminate string */
202 *tail = (char)0;
203 tail += sizeof(char);
204 break;
205 default:
206 /* Should never get here */
207 break;
208 }
209 break;
211 case ACPI_TYPE_STRING:
212 case ACPI_TYPE_BUFFER:
213 switch (format_string[i]) {
214 case 'S':
215 pointer = (u8 **) head;
216 *pointer = tail;
217 memcpy(tail, element->string.pointer,
218 element->string.length);
219 head += sizeof(char *);
220 tail += element->string.length * sizeof(char);
221 /* NULL terminate string */
222 *tail = (char)0;
223 tail += sizeof(char);
224 break;
225 case 'B':
226 pointer = (u8 **) head;
227 *pointer = tail;
228 memcpy(tail, element->buffer.pointer,
229 element->buffer.length);
230 head += sizeof(u8 *);
231 tail += element->buffer.length * sizeof(u8);
232 break;
233 default:
234 /* Should never get here */
235 break;
236 }
237 break;
239 case ACPI_TYPE_PACKAGE:
240 /* TBD: handle nested packages... */
241 default:
242 /* Should never get here */
243 break;
244 }
245 }
247 return AE_OK;
248 }
250 EXPORT_SYMBOL(acpi_extract_package);
252 acpi_status
253 acpi_evaluate_integer(acpi_handle handle,
254 acpi_string pathname,
255 struct acpi_object_list *arguments, unsigned long *data)
256 {
257 acpi_status status = AE_OK;
258 union acpi_object *element;
259 struct acpi_buffer buffer = { 0, NULL };
262 if (!data)
263 return AE_BAD_PARAMETER;
265 element = kmalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
266 if (!element)
267 return AE_NO_MEMORY;
269 memset(element, 0, sizeof(union acpi_object));
270 buffer.length = sizeof(union acpi_object);
271 buffer.pointer = element;
272 status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
273 if (ACPI_FAILURE(status)) {
274 acpi_util_eval_error(handle, pathname, status);
275 kfree(element);
276 return status;
277 }
279 if (element->type != ACPI_TYPE_INTEGER) {
280 acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
281 kfree(element);
282 return AE_BAD_DATA;
283 }
285 *data = element->integer.value;
286 kfree(element);
288 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data));
290 return AE_OK;
291 }
293 EXPORT_SYMBOL(acpi_evaluate_integer);
295 #if 0
296 acpi_status
297 acpi_evaluate_string(acpi_handle handle,
298 acpi_string pathname,
299 acpi_object_list * arguments, acpi_string * data)
300 {
301 acpi_status status = AE_OK;
302 acpi_object *element = NULL;
303 acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
306 if (!data)
307 return AE_BAD_PARAMETER;
309 status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
310 if (ACPI_FAILURE(status)) {
311 acpi_util_eval_error(handle, pathname, status);
312 return status;
313 }
315 element = (acpi_object *) buffer.pointer;
317 if ((element->type != ACPI_TYPE_STRING)
318 || (element->type != ACPI_TYPE_BUFFER)
319 || !element->string.length) {
320 acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
321 return AE_BAD_DATA;
322 }
324 *data = kmalloc(element->string.length + 1, GFP_KERNEL);
325 if (!data) {
326 printk(KERN_ERR PREFIX "Memory allocation\n");
327 return -ENOMEM;
328 }
329 memset(*data, 0, element->string.length + 1);
331 memcpy(*data, element->string.pointer, element->string.length);
333 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data));
335 kfree(buffer.pointer);
337 return AE_OK;
338 }
339 #endif
341 acpi_status
342 acpi_evaluate_reference(acpi_handle handle,
343 acpi_string pathname,
344 struct acpi_object_list *arguments,
345 struct acpi_handle_list *list)
346 {
347 acpi_status status = AE_OK;
348 union acpi_object *package = NULL;
349 union acpi_object *element = NULL;
350 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
351 u32 i = 0;
354 if (!list) {
355 return AE_BAD_PARAMETER;
356 }
358 /* Evaluate object. */
360 status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
361 if (ACPI_FAILURE(status))
362 goto end;
364 package = (union acpi_object *)buffer.pointer;
366 if ((buffer.length == 0) || !package) {
367 printk(KERN_ERR PREFIX "No return object (len %X ptr %p)\n",
368 (unsigned)buffer.length, package);
369 status = AE_BAD_DATA;
370 acpi_util_eval_error(handle, pathname, status);
371 goto end;
372 }
373 if (package->type != ACPI_TYPE_PACKAGE) {
374 printk(KERN_ERR PREFIX "Expecting a [Package], found type %X\n",
375 package->type);
376 status = AE_BAD_DATA;
377 acpi_util_eval_error(handle, pathname, status);
378 goto end;
379 }
380 if (!package->package.count) {
381 printk(KERN_ERR PREFIX "[Package] has zero elements (%p)\n",
382 package);
383 status = AE_BAD_DATA;
384 acpi_util_eval_error(handle, pathname, status);
385 goto end;
386 }
388 if (package->package.count > ACPI_MAX_HANDLES) {
389 return AE_NO_MEMORY;
390 }
391 list->count = package->package.count;
393 /* Extract package data. */
395 for (i = 0; i < list->count; i++) {
397 element = &(package->package.elements[i]);
399 if (element->type != ACPI_TYPE_ANY) {
400 status = AE_BAD_DATA;
401 printk(KERN_ERR PREFIX
402 "Expecting a [Reference] package element, found type %X\n",
403 element->type);
404 acpi_util_eval_error(handle, pathname, status);
405 break;
406 }
408 /* Get the acpi_handle. */
410 list->handles[i] = element->reference.handle;
411 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n",
412 list->handles[i]));
413 }
415 end:
416 if (ACPI_FAILURE(status)) {
417 list->count = 0;
418 //kfree(list->handles);
419 }
421 kfree(buffer.pointer);
423 return status;
424 }
426 EXPORT_SYMBOL(acpi_evaluate_reference);