ia64/linux-2.6.18-xen.hg

annotate drivers/acpi/utilities/utcache.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: utcache - local cache allocation routines
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
ian@0 46 #define _COMPONENT ACPI_UTILITIES
ian@0 47 ACPI_MODULE_NAME("utcache")
ian@0 48
ian@0 49 #ifdef ACPI_USE_LOCAL_CACHE
ian@0 50 /*******************************************************************************
ian@0 51 *
ian@0 52 * FUNCTION: acpi_os_create_cache
ian@0 53 *
ian@0 54 * PARAMETERS: cache_name - Ascii name for the cache
ian@0 55 * object_size - Size of each cached object
ian@0 56 * max_depth - Maximum depth of the cache (in objects)
ian@0 57 * return_cache - Where the new cache object is returned
ian@0 58 *
ian@0 59 * RETURN: Status
ian@0 60 *
ian@0 61 * DESCRIPTION: Create a cache object
ian@0 62 *
ian@0 63 ******************************************************************************/
ian@0 64 acpi_status
ian@0 65 acpi_os_create_cache(char *cache_name,
ian@0 66 u16 object_size,
ian@0 67 u16 max_depth, struct acpi_memory_list **return_cache)
ian@0 68 {
ian@0 69 struct acpi_memory_list *cache;
ian@0 70
ian@0 71 ACPI_FUNCTION_ENTRY();
ian@0 72
ian@0 73 if (!cache_name || !return_cache || (object_size < 16)) {
ian@0 74 return (AE_BAD_PARAMETER);
ian@0 75 }
ian@0 76
ian@0 77 /* Create the cache object */
ian@0 78
ian@0 79 cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
ian@0 80 if (!cache) {
ian@0 81 return (AE_NO_MEMORY);
ian@0 82 }
ian@0 83
ian@0 84 /* Populate the cache object and return it */
ian@0 85
ian@0 86 ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
ian@0 87 cache->link_offset = 8;
ian@0 88 cache->list_name = cache_name;
ian@0 89 cache->object_size = object_size;
ian@0 90 cache->max_depth = max_depth;
ian@0 91
ian@0 92 *return_cache = cache;
ian@0 93 return (AE_OK);
ian@0 94 }
ian@0 95
ian@0 96 /*******************************************************************************
ian@0 97 *
ian@0 98 * FUNCTION: acpi_os_purge_cache
ian@0 99 *
ian@0 100 * PARAMETERS: Cache - Handle to cache object
ian@0 101 *
ian@0 102 * RETURN: Status
ian@0 103 *
ian@0 104 * DESCRIPTION: Free all objects within the requested cache.
ian@0 105 *
ian@0 106 ******************************************************************************/
ian@0 107
ian@0 108 acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
ian@0 109 {
ian@0 110 char *next;
ian@0 111
ian@0 112 ACPI_FUNCTION_ENTRY();
ian@0 113
ian@0 114 if (!cache) {
ian@0 115 return (AE_BAD_PARAMETER);
ian@0 116 }
ian@0 117
ian@0 118 /* Walk the list of objects in this cache */
ian@0 119
ian@0 120 while (cache->list_head) {
ian@0 121
ian@0 122 /* Delete and unlink one cached state object */
ian@0 123
ian@0 124 next = *(ACPI_CAST_INDIRECT_PTR(char,
ian@0 125 &(((char *)cache->
ian@0 126 list_head)[cache->
ian@0 127 link_offset])));
ian@0 128 ACPI_FREE(cache->list_head);
ian@0 129
ian@0 130 cache->list_head = next;
ian@0 131 cache->current_depth--;
ian@0 132 }
ian@0 133
ian@0 134 return (AE_OK);
ian@0 135 }
ian@0 136
ian@0 137 /*******************************************************************************
ian@0 138 *
ian@0 139 * FUNCTION: acpi_os_delete_cache
ian@0 140 *
ian@0 141 * PARAMETERS: Cache - Handle to cache object
ian@0 142 *
ian@0 143 * RETURN: Status
ian@0 144 *
ian@0 145 * DESCRIPTION: Free all objects within the requested cache and delete the
ian@0 146 * cache object.
ian@0 147 *
ian@0 148 ******************************************************************************/
ian@0 149
ian@0 150 acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
ian@0 151 {
ian@0 152 acpi_status status;
ian@0 153
ian@0 154 ACPI_FUNCTION_ENTRY();
ian@0 155
ian@0 156 /* Purge all objects in the cache */
ian@0 157
ian@0 158 status = acpi_os_purge_cache(cache);
ian@0 159 if (ACPI_FAILURE(status)) {
ian@0 160 return (status);
ian@0 161 }
ian@0 162
ian@0 163 /* Now we can delete the cache object */
ian@0 164
ian@0 165 ACPI_FREE(cache);
ian@0 166 return (AE_OK);
ian@0 167 }
ian@0 168
ian@0 169 /*******************************************************************************
ian@0 170 *
ian@0 171 * FUNCTION: acpi_os_release_object
ian@0 172 *
ian@0 173 * PARAMETERS: Cache - Handle to cache object
ian@0 174 * Object - The object to be released
ian@0 175 *
ian@0 176 * RETURN: None
ian@0 177 *
ian@0 178 * DESCRIPTION: Release an object to the specified cache. If cache is full,
ian@0 179 * the object is deleted.
ian@0 180 *
ian@0 181 ******************************************************************************/
ian@0 182
ian@0 183 acpi_status
ian@0 184 acpi_os_release_object(struct acpi_memory_list * cache, void *object)
ian@0 185 {
ian@0 186 acpi_status status;
ian@0 187
ian@0 188 ACPI_FUNCTION_ENTRY();
ian@0 189
ian@0 190 if (!cache || !object) {
ian@0 191 return (AE_BAD_PARAMETER);
ian@0 192 }
ian@0 193
ian@0 194 /* If cache is full, just free this object */
ian@0 195
ian@0 196 if (cache->current_depth >= cache->max_depth) {
ian@0 197 ACPI_FREE(object);
ian@0 198 ACPI_MEM_TRACKING(cache->total_freed++);
ian@0 199 }
ian@0 200
ian@0 201 /* Otherwise put this object back into the cache */
ian@0 202
ian@0 203 else {
ian@0 204 status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
ian@0 205 if (ACPI_FAILURE(status)) {
ian@0 206 return (status);
ian@0 207 }
ian@0 208
ian@0 209 /* Mark the object as cached */
ian@0 210
ian@0 211 ACPI_MEMSET(object, 0xCA, cache->object_size);
ian@0 212 ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
ian@0 213
ian@0 214 /* Put the object at the head of the cache list */
ian@0 215
ian@0 216 *(ACPI_CAST_INDIRECT_PTR(char,
ian@0 217 &(((char *)object)[cache->
ian@0 218 link_offset]))) =
ian@0 219 cache->list_head;
ian@0 220 cache->list_head = object;
ian@0 221 cache->current_depth++;
ian@0 222
ian@0 223 (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
ian@0 224 }
ian@0 225
ian@0 226 return (AE_OK);
ian@0 227 }
ian@0 228
ian@0 229 /*******************************************************************************
ian@0 230 *
ian@0 231 * FUNCTION: acpi_os_acquire_object
ian@0 232 *
ian@0 233 * PARAMETERS: Cache - Handle to cache object
ian@0 234 *
ian@0 235 * RETURN: the acquired object. NULL on error
ian@0 236 *
ian@0 237 * DESCRIPTION: Get an object from the specified cache. If cache is empty,
ian@0 238 * the object is allocated.
ian@0 239 *
ian@0 240 ******************************************************************************/
ian@0 241
ian@0 242 void *acpi_os_acquire_object(struct acpi_memory_list *cache)
ian@0 243 {
ian@0 244 acpi_status status;
ian@0 245 void *object;
ian@0 246
ian@0 247 ACPI_FUNCTION_NAME(os_acquire_object);
ian@0 248
ian@0 249 if (!cache) {
ian@0 250 return (NULL);
ian@0 251 }
ian@0 252
ian@0 253 status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
ian@0 254 if (ACPI_FAILURE(status)) {
ian@0 255 return (NULL);
ian@0 256 }
ian@0 257
ian@0 258 ACPI_MEM_TRACKING(cache->requests++);
ian@0 259
ian@0 260 /* Check the cache first */
ian@0 261
ian@0 262 if (cache->list_head) {
ian@0 263
ian@0 264 /* There is an object available, use it */
ian@0 265
ian@0 266 object = cache->list_head;
ian@0 267 cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char,
ian@0 268 &(((char *)
ian@0 269 object)[cache->
ian@0 270 link_offset])));
ian@0 271
ian@0 272 cache->current_depth--;
ian@0 273
ian@0 274 ACPI_MEM_TRACKING(cache->hits++);
ian@0 275 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
ian@0 276 "Object %p from %s cache\n", object,
ian@0 277 cache->list_name));
ian@0 278
ian@0 279 status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
ian@0 280 if (ACPI_FAILURE(status)) {
ian@0 281 return (NULL);
ian@0 282 }
ian@0 283
ian@0 284 /* Clear (zero) the previously used Object */
ian@0 285
ian@0 286 ACPI_MEMSET(object, 0, cache->object_size);
ian@0 287 } else {
ian@0 288 /* The cache is empty, create a new object */
ian@0 289
ian@0 290 ACPI_MEM_TRACKING(cache->total_allocated++);
ian@0 291
ian@0 292 /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
ian@0 293
ian@0 294 status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
ian@0 295 if (ACPI_FAILURE(status)) {
ian@0 296 return (NULL);
ian@0 297 }
ian@0 298
ian@0 299 object = ACPI_ALLOCATE_ZEROED(cache->object_size);
ian@0 300 if (!object) {
ian@0 301 return (NULL);
ian@0 302 }
ian@0 303 }
ian@0 304
ian@0 305 return (object);
ian@0 306 }
ian@0 307 #endif /* ACPI_USE_LOCAL_CACHE */