ia64/linux-2.6.18-xen.hg

annotate drivers/acpi/namespace/nswalk.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: nswalk - Functions for walking the ACPI namespace
ian@0 4 *
ian@0 5 *****************************************************************************/
ian@0 6
ian@0 7 /*
ian@0 8 * Copyright (C) 2000 - 2006, R. Byron Moore
ian@0 9 * All rights reserved.
ian@0 10 *
ian@0 11 * Redistribution and use in source and binary forms, with or without
ian@0 12 * modification, are permitted provided that the following conditions
ian@0 13 * are met:
ian@0 14 * 1. Redistributions of source code must retain the above copyright
ian@0 15 * notice, this list of conditions, and the following disclaimer,
ian@0 16 * without modification.
ian@0 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
ian@0 18 * substantially similar to the "NO WARRANTY" disclaimer below
ian@0 19 * ("Disclaimer") and any redistribution must be conditioned upon
ian@0 20 * including a substantially similar Disclaimer requirement for further
ian@0 21 * binary redistribution.
ian@0 22 * 3. Neither the names of the above-listed copyright holders nor the names
ian@0 23 * of any contributors may be used to endorse or promote products derived
ian@0 24 * from this software without specific prior written permission.
ian@0 25 *
ian@0 26 * Alternatively, this software may be distributed under the terms of the
ian@0 27 * GNU General Public License ("GPL") version 2 as published by the Free
ian@0 28 * Software Foundation.
ian@0 29 *
ian@0 30 * NO WARRANTY
ian@0 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
ian@0 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
ian@0 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
ian@0 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
ian@0 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ian@0 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
ian@0 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ian@0 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
ian@0 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
ian@0 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
ian@0 41 * POSSIBILITY OF SUCH DAMAGES.
ian@0 42 */
ian@0 43
ian@0 44 #include <acpi/acpi.h>
ian@0 45 #include <acpi/acnamesp.h>
ian@0 46
ian@0 47 #define _COMPONENT ACPI_NAMESPACE
ian@0 48 ACPI_MODULE_NAME("nswalk")
ian@0 49
ian@0 50 /*******************************************************************************
ian@0 51 *
ian@0 52 * FUNCTION: acpi_ns_get_next_node
ian@0 53 *
ian@0 54 * PARAMETERS: Type - Type of node to be searched for
ian@0 55 * parent_node - Parent node whose children we are
ian@0 56 * getting
ian@0 57 * child_node - Previous child that was found.
ian@0 58 * The NEXT child will be returned
ian@0 59 *
ian@0 60 * RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if
ian@0 61 * none is found.
ian@0 62 *
ian@0 63 * DESCRIPTION: Return the next peer node within the namespace. If Handle
ian@0 64 * is valid, Scope is ignored. Otherwise, the first node
ian@0 65 * within Scope is returned.
ian@0 66 *
ian@0 67 ******************************************************************************/
ian@0 68 struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
ian@0 69 struct acpi_namespace_node
ian@0 70 *parent_node,
ian@0 71 struct acpi_namespace_node
ian@0 72 *child_node)
ian@0 73 {
ian@0 74 struct acpi_namespace_node *next_node = NULL;
ian@0 75
ian@0 76 ACPI_FUNCTION_ENTRY();
ian@0 77
ian@0 78 if (!child_node) {
ian@0 79
ian@0 80 /* It's really the parent's _scope_ that we want */
ian@0 81
ian@0 82 if (parent_node->child) {
ian@0 83 next_node = parent_node->child;
ian@0 84 }
ian@0 85 }
ian@0 86
ian@0 87 else {
ian@0 88 /* Start search at the NEXT node */
ian@0 89
ian@0 90 next_node = acpi_ns_get_next_valid_node(child_node);
ian@0 91 }
ian@0 92
ian@0 93 /* If any type is OK, we are done */
ian@0 94
ian@0 95 if (type == ACPI_TYPE_ANY) {
ian@0 96
ian@0 97 /* next_node is NULL if we are at the end-of-list */
ian@0 98
ian@0 99 return (next_node);
ian@0 100 }
ian@0 101
ian@0 102 /* Must search for the node -- but within this scope only */
ian@0 103
ian@0 104 while (next_node) {
ian@0 105
ian@0 106 /* If type matches, we are done */
ian@0 107
ian@0 108 if (next_node->type == type) {
ian@0 109 return (next_node);
ian@0 110 }
ian@0 111
ian@0 112 /* Otherwise, move on to the next node */
ian@0 113
ian@0 114 next_node = acpi_ns_get_next_valid_node(next_node);
ian@0 115 }
ian@0 116
ian@0 117 /* Not found */
ian@0 118
ian@0 119 return (NULL);
ian@0 120 }
ian@0 121
ian@0 122 /*******************************************************************************
ian@0 123 *
ian@0 124 * FUNCTION: acpi_ns_walk_namespace
ian@0 125 *
ian@0 126 * PARAMETERS: Type - acpi_object_type to search for
ian@0 127 * start_node - Handle in namespace where search begins
ian@0 128 * max_depth - Depth to which search is to reach
ian@0 129 * unlock_before_callback- Whether to unlock the NS before invoking
ian@0 130 * the callback routine
ian@0 131 * user_function - Called when an object of "Type" is found
ian@0 132 * Context - Passed to user function
ian@0 133 * return_value - from the user_function if terminated early.
ian@0 134 * Otherwise, returns NULL.
ian@0 135 * RETURNS: Status
ian@0 136 *
ian@0 137 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
ian@0 138 * starting (and ending) at the node specified by start_handle.
ian@0 139 * The user_function is called whenever a node that matches
ian@0 140 * the type parameter is found. If the user function returns
ian@0 141 * a non-zero value, the search is terminated immediately and this
ian@0 142 * value is returned to the caller.
ian@0 143 *
ian@0 144 * The point of this procedure is to provide a generic namespace
ian@0 145 * walk routine that can be called from multiple places to
ian@0 146 * provide multiple services; the User Function can be tailored
ian@0 147 * to each task, whether it is a print function, a compare
ian@0 148 * function, etc.
ian@0 149 *
ian@0 150 ******************************************************************************/
ian@0 151
ian@0 152 acpi_status
ian@0 153 acpi_ns_walk_namespace(acpi_object_type type,
ian@0 154 acpi_handle start_node,
ian@0 155 u32 max_depth,
ian@0 156 u8 unlock_before_callback,
ian@0 157 acpi_walk_callback user_function,
ian@0 158 void *context, void **return_value)
ian@0 159 {
ian@0 160 acpi_status status;
ian@0 161 acpi_status mutex_status;
ian@0 162 struct acpi_namespace_node *child_node;
ian@0 163 struct acpi_namespace_node *parent_node;
ian@0 164 acpi_object_type child_type;
ian@0 165 u32 level;
ian@0 166
ian@0 167 ACPI_FUNCTION_TRACE(ns_walk_namespace);
ian@0 168
ian@0 169 /* Special case for the namespace Root Node */
ian@0 170
ian@0 171 if (start_node == ACPI_ROOT_OBJECT) {
ian@0 172 start_node = acpi_gbl_root_node;
ian@0 173 }
ian@0 174
ian@0 175 /* Null child means "get first node" */
ian@0 176
ian@0 177 parent_node = start_node;
ian@0 178 child_node = NULL;
ian@0 179 child_type = ACPI_TYPE_ANY;
ian@0 180 level = 1;
ian@0 181
ian@0 182 /*
ian@0 183 * Traverse the tree of nodes until we bubble back up to where we
ian@0 184 * started. When Level is zero, the loop is done because we have
ian@0 185 * bubbled up to (and passed) the original parent handle (start_entry)
ian@0 186 */
ian@0 187 while (level > 0) {
ian@0 188
ian@0 189 /* Get the next node in this scope. Null if not found */
ian@0 190
ian@0 191 status = AE_OK;
ian@0 192 child_node =
ian@0 193 acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
ian@0 194 child_node);
ian@0 195 if (child_node) {
ian@0 196 /*
ian@0 197 * Found node, Get the type if we are not
ian@0 198 * searching for ANY
ian@0 199 */
ian@0 200 if (type != ACPI_TYPE_ANY) {
ian@0 201 child_type = child_node->type;
ian@0 202 }
ian@0 203
ian@0 204 if (child_type == type) {
ian@0 205 /*
ian@0 206 * Found a matching node, invoke the user
ian@0 207 * callback function
ian@0 208 */
ian@0 209 if (unlock_before_callback) {
ian@0 210 mutex_status =
ian@0 211 acpi_ut_release_mutex
ian@0 212 (ACPI_MTX_NAMESPACE);
ian@0 213 if (ACPI_FAILURE(mutex_status)) {
ian@0 214 return_ACPI_STATUS
ian@0 215 (mutex_status);
ian@0 216 }
ian@0 217 }
ian@0 218
ian@0 219 status = user_function(child_node, level,
ian@0 220 context, return_value);
ian@0 221
ian@0 222 if (unlock_before_callback) {
ian@0 223 mutex_status =
ian@0 224 acpi_ut_acquire_mutex
ian@0 225 (ACPI_MTX_NAMESPACE);
ian@0 226 if (ACPI_FAILURE(mutex_status)) {
ian@0 227 return_ACPI_STATUS
ian@0 228 (mutex_status);
ian@0 229 }
ian@0 230 }
ian@0 231
ian@0 232 switch (status) {
ian@0 233 case AE_OK:
ian@0 234 case AE_CTRL_DEPTH:
ian@0 235
ian@0 236 /* Just keep going */
ian@0 237 break;
ian@0 238
ian@0 239 case AE_CTRL_TERMINATE:
ian@0 240
ian@0 241 /* Exit now, with OK status */
ian@0 242
ian@0 243 return_ACPI_STATUS(AE_OK);
ian@0 244
ian@0 245 default:
ian@0 246
ian@0 247 /* All others are valid exceptions */
ian@0 248
ian@0 249 return_ACPI_STATUS(status);
ian@0 250 }
ian@0 251 }
ian@0 252
ian@0 253 /*
ian@0 254 * Depth first search:
ian@0 255 * Attempt to go down another level in the namespace
ian@0 256 * if we are allowed to. Don't go any further if we
ian@0 257 * have reached the caller specified maximum depth
ian@0 258 * or if the user function has specified that the
ian@0 259 * maximum depth has been reached.
ian@0 260 */
ian@0 261 if ((level < max_depth) && (status != AE_CTRL_DEPTH)) {
ian@0 262 if (acpi_ns_get_next_node
ian@0 263 (ACPI_TYPE_ANY, child_node, NULL)) {
ian@0 264 /*
ian@0 265 * There is at least one child of this
ian@0 266 * node, visit the onde
ian@0 267 */
ian@0 268 level++;
ian@0 269 parent_node = child_node;
ian@0 270 child_node = NULL;
ian@0 271 }
ian@0 272 }
ian@0 273 } else {
ian@0 274 /*
ian@0 275 * No more children of this node (acpi_ns_get_next_node
ian@0 276 * failed), go back upwards in the namespace tree to
ian@0 277 * the node's parent.
ian@0 278 */
ian@0 279 level--;
ian@0 280 child_node = parent_node;
ian@0 281 parent_node = acpi_ns_get_parent_node(parent_node);
ian@0 282 }
ian@0 283 }
ian@0 284
ian@0 285 /* Complete walk, not terminated by user function */
ian@0 286
ian@0 287 return_ACPI_STATUS(AE_OK);
ian@0 288 }