ia64/linux-2.6.18-xen.hg

annotate drivers/acpi/namespace/nsobject.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
rev   line source
ian@0 1 /*******************************************************************************
ian@0 2 *
ian@0 3 * Module Name: nsobject - Utilities for objects attached to namespace
ian@0 4 * table entries
ian@0 5 *
ian@0 6 ******************************************************************************/
ian@0 7
ian@0 8 /*
ian@0 9 * Copyright (C) 2000 - 2006, R. Byron Moore
ian@0 10 * All rights reserved.
ian@0 11 *
ian@0 12 * Redistribution and use in source and binary forms, with or without
ian@0 13 * modification, are permitted provided that the following conditions
ian@0 14 * are met:
ian@0 15 * 1. Redistributions of source code must retain the above copyright
ian@0 16 * notice, this list of conditions, and the following disclaimer,
ian@0 17 * without modification.
ian@0 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
ian@0 19 * substantially similar to the "NO WARRANTY" disclaimer below
ian@0 20 * ("Disclaimer") and any redistribution must be conditioned upon
ian@0 21 * including a substantially similar Disclaimer requirement for further
ian@0 22 * binary redistribution.
ian@0 23 * 3. Neither the names of the above-listed copyright holders nor the names
ian@0 24 * of any contributors may be used to endorse or promote products derived
ian@0 25 * from this software without specific prior written permission.
ian@0 26 *
ian@0 27 * Alternatively, this software may be distributed under the terms of the
ian@0 28 * GNU General Public License ("GPL") version 2 as published by the Free
ian@0 29 * Software Foundation.
ian@0 30 *
ian@0 31 * NO WARRANTY
ian@0 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
ian@0 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
ian@0 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
ian@0 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
ian@0 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ian@0 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
ian@0 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ian@0 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
ian@0 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
ian@0 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
ian@0 42 * POSSIBILITY OF SUCH DAMAGES.
ian@0 43 */
ian@0 44
ian@0 45 #include <acpi/acpi.h>
ian@0 46 #include <acpi/acnamesp.h>
ian@0 47
ian@0 48 #define _COMPONENT ACPI_NAMESPACE
ian@0 49 ACPI_MODULE_NAME("nsobject")
ian@0 50
ian@0 51 /*******************************************************************************
ian@0 52 *
ian@0 53 * FUNCTION: acpi_ns_attach_object
ian@0 54 *
ian@0 55 * PARAMETERS: Node - Parent Node
ian@0 56 * Object - Object to be attached
ian@0 57 * Type - Type of object, or ACPI_TYPE_ANY if not
ian@0 58 * known
ian@0 59 *
ian@0 60 * RETURN: Status
ian@0 61 *
ian@0 62 * DESCRIPTION: Record the given object as the value associated with the
ian@0 63 * name whose acpi_handle is passed. If Object is NULL
ian@0 64 * and Type is ACPI_TYPE_ANY, set the name as having no value.
ian@0 65 * Note: Future may require that the Node->Flags field be passed
ian@0 66 * as a parameter.
ian@0 67 *
ian@0 68 * MUTEX: Assumes namespace is locked
ian@0 69 *
ian@0 70 ******************************************************************************/
ian@0 71 acpi_status
ian@0 72 acpi_ns_attach_object(struct acpi_namespace_node *node,
ian@0 73 union acpi_operand_object *object, acpi_object_type type)
ian@0 74 {
ian@0 75 union acpi_operand_object *obj_desc;
ian@0 76 union acpi_operand_object *last_obj_desc;
ian@0 77 acpi_object_type object_type = ACPI_TYPE_ANY;
ian@0 78
ian@0 79 ACPI_FUNCTION_TRACE(ns_attach_object);
ian@0 80
ian@0 81 /*
ian@0 82 * Parameter validation
ian@0 83 */
ian@0 84 if (!node) {
ian@0 85
ian@0 86 /* Invalid handle */
ian@0 87
ian@0 88 ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
ian@0 89 return_ACPI_STATUS(AE_BAD_PARAMETER);
ian@0 90 }
ian@0 91
ian@0 92 if (!object && (ACPI_TYPE_ANY != type)) {
ian@0 93
ian@0 94 /* Null object */
ian@0 95
ian@0 96 ACPI_ERROR((AE_INFO,
ian@0 97 "Null object, but type not ACPI_TYPE_ANY"));
ian@0 98 return_ACPI_STATUS(AE_BAD_PARAMETER);
ian@0 99 }
ian@0 100
ian@0 101 if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
ian@0 102
ian@0 103 /* Not a name handle */
ian@0 104
ian@0 105 ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
ian@0 106 node, acpi_ut_get_descriptor_name(node)));
ian@0 107 return_ACPI_STATUS(AE_BAD_PARAMETER);
ian@0 108 }
ian@0 109
ian@0 110 /* Check if this object is already attached */
ian@0 111
ian@0 112 if (node->object == object) {
ian@0 113 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
ian@0 114 "Obj %p already installed in NameObj %p\n",
ian@0 115 object, node));
ian@0 116
ian@0 117 return_ACPI_STATUS(AE_OK);
ian@0 118 }
ian@0 119
ian@0 120 /* If null object, we will just install it */
ian@0 121
ian@0 122 if (!object) {
ian@0 123 obj_desc = NULL;
ian@0 124 object_type = ACPI_TYPE_ANY;
ian@0 125 }
ian@0 126
ian@0 127 /*
ian@0 128 * If the source object is a namespace Node with an attached object,
ian@0 129 * we will use that (attached) object
ian@0 130 */
ian@0 131 else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
ian@0 132 ((struct acpi_namespace_node *)object)->object) {
ian@0 133 /*
ian@0 134 * Value passed is a name handle and that name has a
ian@0 135 * non-null value. Use that name's value and type.
ian@0 136 */
ian@0 137 obj_desc = ((struct acpi_namespace_node *)object)->object;
ian@0 138 object_type = ((struct acpi_namespace_node *)object)->type;
ian@0 139 }
ian@0 140
ian@0 141 /*
ian@0 142 * Otherwise, we will use the parameter object, but we must type
ian@0 143 * it first
ian@0 144 */
ian@0 145 else {
ian@0 146 obj_desc = (union acpi_operand_object *)object;
ian@0 147
ian@0 148 /* Use the given type */
ian@0 149
ian@0 150 object_type = type;
ian@0 151 }
ian@0 152
ian@0 153 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
ian@0 154 obj_desc, node, acpi_ut_get_node_name(node)));
ian@0 155
ian@0 156 /* Detach an existing attached object if present */
ian@0 157
ian@0 158 if (node->object) {
ian@0 159 acpi_ns_detach_object(node);
ian@0 160 }
ian@0 161
ian@0 162 if (obj_desc) {
ian@0 163 /*
ian@0 164 * Must increment the new value's reference count
ian@0 165 * (if it is an internal object)
ian@0 166 */
ian@0 167 acpi_ut_add_reference(obj_desc);
ian@0 168
ian@0 169 /*
ian@0 170 * Handle objects with multiple descriptors - walk
ian@0 171 * to the end of the descriptor list
ian@0 172 */
ian@0 173 last_obj_desc = obj_desc;
ian@0 174 while (last_obj_desc->common.next_object) {
ian@0 175 last_obj_desc = last_obj_desc->common.next_object;
ian@0 176 }
ian@0 177
ian@0 178 /* Install the object at the front of the object list */
ian@0 179
ian@0 180 last_obj_desc->common.next_object = node->object;
ian@0 181 }
ian@0 182
ian@0 183 node->type = (u8) object_type;
ian@0 184 node->object = obj_desc;
ian@0 185
ian@0 186 return_ACPI_STATUS(AE_OK);
ian@0 187 }
ian@0 188
ian@0 189 /*******************************************************************************
ian@0 190 *
ian@0 191 * FUNCTION: acpi_ns_detach_object
ian@0 192 *
ian@0 193 * PARAMETERS: Node - A Namespace node whose object will be detached
ian@0 194 *
ian@0 195 * RETURN: None.
ian@0 196 *
ian@0 197 * DESCRIPTION: Detach/delete an object associated with a namespace node.
ian@0 198 * if the object is an allocated object, it is freed.
ian@0 199 * Otherwise, the field is simply cleared.
ian@0 200 *
ian@0 201 ******************************************************************************/
ian@0 202
ian@0 203 void acpi_ns_detach_object(struct acpi_namespace_node *node)
ian@0 204 {
ian@0 205 union acpi_operand_object *obj_desc;
ian@0 206
ian@0 207 ACPI_FUNCTION_TRACE(ns_detach_object);
ian@0 208
ian@0 209 obj_desc = node->object;
ian@0 210
ian@0 211 if (!obj_desc ||
ian@0 212 (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA)) {
ian@0 213 return_VOID;
ian@0 214 }
ian@0 215
ian@0 216 /* Clear the entry in all cases */
ian@0 217
ian@0 218 node->object = NULL;
ian@0 219 if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) {
ian@0 220 node->object = obj_desc->common.next_object;
ian@0 221 if (node->object &&
ian@0 222 (ACPI_GET_OBJECT_TYPE(node->object) !=
ian@0 223 ACPI_TYPE_LOCAL_DATA)) {
ian@0 224 node->object = node->object->common.next_object;
ian@0 225 }
ian@0 226 }
ian@0 227
ian@0 228 /* Reset the node type to untyped */
ian@0 229
ian@0 230 node->type = ACPI_TYPE_ANY;
ian@0 231
ian@0 232 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
ian@0 233 node, acpi_ut_get_node_name(node), obj_desc));
ian@0 234
ian@0 235 /* Remove one reference on the object (and all subobjects) */
ian@0 236
ian@0 237 acpi_ut_remove_reference(obj_desc);
ian@0 238 return_VOID;
ian@0 239 }
ian@0 240
ian@0 241 /*******************************************************************************
ian@0 242 *
ian@0 243 * FUNCTION: acpi_ns_get_attached_object
ian@0 244 *
ian@0 245 * PARAMETERS: Node - Namespace node
ian@0 246 *
ian@0 247 * RETURN: Current value of the object field from the Node whose
ian@0 248 * handle is passed
ian@0 249 *
ian@0 250 * DESCRIPTION: Obtain the object attached to a namespace node.
ian@0 251 *
ian@0 252 ******************************************************************************/
ian@0 253
ian@0 254 union acpi_operand_object *acpi_ns_get_attached_object(struct
ian@0 255 acpi_namespace_node
ian@0 256 *node)
ian@0 257 {
ian@0 258 ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node);
ian@0 259
ian@0 260 if (!node) {
ian@0 261 ACPI_WARNING((AE_INFO, "Null Node ptr"));
ian@0 262 return_PTR(NULL);
ian@0 263 }
ian@0 264
ian@0 265 if (!node->object ||
ian@0 266 ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND)
ian@0 267 && (ACPI_GET_DESCRIPTOR_TYPE(node->object) !=
ian@0 268 ACPI_DESC_TYPE_NAMED))
ian@0 269 || (ACPI_GET_OBJECT_TYPE(node->object) == ACPI_TYPE_LOCAL_DATA)) {
ian@0 270 return_PTR(NULL);
ian@0 271 }
ian@0 272
ian@0 273 return_PTR(node->object);
ian@0 274 }
ian@0 275
ian@0 276 /*******************************************************************************
ian@0 277 *
ian@0 278 * FUNCTION: acpi_ns_get_secondary_object
ian@0 279 *
ian@0 280 * PARAMETERS: Node - Namespace node
ian@0 281 *
ian@0 282 * RETURN: Current value of the object field from the Node whose
ian@0 283 * handle is passed.
ian@0 284 *
ian@0 285 * DESCRIPTION: Obtain a secondary object associated with a namespace node.
ian@0 286 *
ian@0 287 ******************************************************************************/
ian@0 288
ian@0 289 union acpi_operand_object *acpi_ns_get_secondary_object(union
ian@0 290 acpi_operand_object
ian@0 291 *obj_desc)
ian@0 292 {
ian@0 293 ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc);
ian@0 294
ian@0 295 if ((!obj_desc) ||
ian@0 296 (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
ian@0 297 (!obj_desc->common.next_object) ||
ian@0 298 (ACPI_GET_OBJECT_TYPE(obj_desc->common.next_object) ==
ian@0 299 ACPI_TYPE_LOCAL_DATA)) {
ian@0 300 return_PTR(NULL);
ian@0 301 }
ian@0 302
ian@0 303 return_PTR(obj_desc->common.next_object);
ian@0 304 }
ian@0 305
ian@0 306 /*******************************************************************************
ian@0 307 *
ian@0 308 * FUNCTION: acpi_ns_attach_data
ian@0 309 *
ian@0 310 * PARAMETERS: Node - Namespace node
ian@0 311 * Handler - Handler to be associated with the data
ian@0 312 * Data - Data to be attached
ian@0 313 *
ian@0 314 * RETURN: Status
ian@0 315 *
ian@0 316 * DESCRIPTION: Low-level attach data. Create and attach a Data object.
ian@0 317 *
ian@0 318 ******************************************************************************/
ian@0 319
ian@0 320 acpi_status
ian@0 321 acpi_ns_attach_data(struct acpi_namespace_node *node,
ian@0 322 acpi_object_handler handler, void *data)
ian@0 323 {
ian@0 324 union acpi_operand_object *prev_obj_desc;
ian@0 325 union acpi_operand_object *obj_desc;
ian@0 326 union acpi_operand_object *data_desc;
ian@0 327
ian@0 328 /* We only allow one attachment per handler */
ian@0 329
ian@0 330 prev_obj_desc = NULL;
ian@0 331 obj_desc = node->object;
ian@0 332 while (obj_desc) {
ian@0 333 if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
ian@0 334 (obj_desc->data.handler == handler)) {
ian@0 335 return (AE_ALREADY_EXISTS);
ian@0 336 }
ian@0 337
ian@0 338 prev_obj_desc = obj_desc;
ian@0 339 obj_desc = obj_desc->common.next_object;
ian@0 340 }
ian@0 341
ian@0 342 /* Create an internal object for the data */
ian@0 343
ian@0 344 data_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_DATA);
ian@0 345 if (!data_desc) {
ian@0 346 return (AE_NO_MEMORY);
ian@0 347 }
ian@0 348
ian@0 349 data_desc->data.handler = handler;
ian@0 350 data_desc->data.pointer = data;
ian@0 351
ian@0 352 /* Install the data object */
ian@0 353
ian@0 354 if (prev_obj_desc) {
ian@0 355 prev_obj_desc->common.next_object = data_desc;
ian@0 356 } else {
ian@0 357 node->object = data_desc;
ian@0 358 }
ian@0 359
ian@0 360 return (AE_OK);
ian@0 361 }
ian@0 362
ian@0 363 /*******************************************************************************
ian@0 364 *
ian@0 365 * FUNCTION: acpi_ns_detach_data
ian@0 366 *
ian@0 367 * PARAMETERS: Node - Namespace node
ian@0 368 * Handler - Handler associated with the data
ian@0 369 *
ian@0 370 * RETURN: Status
ian@0 371 *
ian@0 372 * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
ian@0 373 * is responsible for the actual data.
ian@0 374 *
ian@0 375 ******************************************************************************/
ian@0 376
ian@0 377 acpi_status
ian@0 378 acpi_ns_detach_data(struct acpi_namespace_node * node,
ian@0 379 acpi_object_handler handler)
ian@0 380 {
ian@0 381 union acpi_operand_object *obj_desc;
ian@0 382 union acpi_operand_object *prev_obj_desc;
ian@0 383
ian@0 384 prev_obj_desc = NULL;
ian@0 385 obj_desc = node->object;
ian@0 386 while (obj_desc) {
ian@0 387 if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
ian@0 388 (obj_desc->data.handler == handler)) {
ian@0 389 if (prev_obj_desc) {
ian@0 390 prev_obj_desc->common.next_object =
ian@0 391 obj_desc->common.next_object;
ian@0 392 } else {
ian@0 393 node->object = obj_desc->common.next_object;
ian@0 394 }
ian@0 395
ian@0 396 acpi_ut_remove_reference(obj_desc);
ian@0 397 return (AE_OK);
ian@0 398 }
ian@0 399
ian@0 400 prev_obj_desc = obj_desc;
ian@0 401 obj_desc = obj_desc->common.next_object;
ian@0 402 }
ian@0 403
ian@0 404 return (AE_NOT_FOUND);
ian@0 405 }
ian@0 406
ian@0 407 /*******************************************************************************
ian@0 408 *
ian@0 409 * FUNCTION: acpi_ns_get_attached_data
ian@0 410 *
ian@0 411 * PARAMETERS: Node - Namespace node
ian@0 412 * Handler - Handler associated with the data
ian@0 413 * Data - Where the data is returned
ian@0 414 *
ian@0 415 * RETURN: Status
ian@0 416 *
ian@0 417 * DESCRIPTION: Low level interface to obtain data previously associated with
ian@0 418 * a namespace node.
ian@0 419 *
ian@0 420 ******************************************************************************/
ian@0 421
ian@0 422 acpi_status
ian@0 423 acpi_ns_get_attached_data(struct acpi_namespace_node * node,
ian@0 424 acpi_object_handler handler, void **data)
ian@0 425 {
ian@0 426 union acpi_operand_object *obj_desc;
ian@0 427
ian@0 428 obj_desc = node->object;
ian@0 429 while (obj_desc) {
ian@0 430 if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
ian@0 431 (obj_desc->data.handler == handler)) {
ian@0 432 *data = obj_desc->data.pointer;
ian@0 433 return (AE_OK);
ian@0 434 }
ian@0 435
ian@0 436 obj_desc = obj_desc->common.next_object;
ian@0 437 }
ian@0 438
ian@0 439 return (AE_NOT_FOUND);
ian@0 440 }