ia64/linux-2.6.18-xen.hg

annotate arch/sparc/prom/tree.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 /* $Id: tree.c,v 1.26 2000/08/26 02:38:03 anton Exp $
ian@0 2 * tree.c: Basic device tree traversal/scanning for the Linux
ian@0 3 * prom library.
ian@0 4 *
ian@0 5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
ian@0 6 */
ian@0 7
ian@0 8 #define PROMLIB_INTERNAL
ian@0 9
ian@0 10 #include <linux/string.h>
ian@0 11 #include <linux/types.h>
ian@0 12 #include <linux/kernel.h>
ian@0 13 #include <linux/sched.h>
ian@0 14 #include <linux/ctype.h>
ian@0 15
ian@0 16 #include <asm/openprom.h>
ian@0 17 #include <asm/oplib.h>
ian@0 18
ian@0 19 extern void restore_current(void);
ian@0 20
ian@0 21 static char promlib_buf[128];
ian@0 22
ian@0 23 /* Internal version of prom_getchild that does not alter return values. */
ian@0 24 int __prom_getchild(int node)
ian@0 25 {
ian@0 26 unsigned long flags;
ian@0 27 int cnode;
ian@0 28
ian@0 29 spin_lock_irqsave(&prom_lock, flags);
ian@0 30 cnode = prom_nodeops->no_child(node);
ian@0 31 restore_current();
ian@0 32 spin_unlock_irqrestore(&prom_lock, flags);
ian@0 33
ian@0 34 return cnode;
ian@0 35 }
ian@0 36
ian@0 37 /* Return the child of node 'node' or zero if no this node has no
ian@0 38 * direct descendent.
ian@0 39 */
ian@0 40 int prom_getchild(int node)
ian@0 41 {
ian@0 42 int cnode;
ian@0 43
ian@0 44 if (node == -1)
ian@0 45 return 0;
ian@0 46
ian@0 47 cnode = __prom_getchild(node);
ian@0 48 if (cnode == 0 || cnode == -1)
ian@0 49 return 0;
ian@0 50
ian@0 51 return cnode;
ian@0 52 }
ian@0 53
ian@0 54 /* Internal version of prom_getsibling that does not alter return values. */
ian@0 55 int __prom_getsibling(int node)
ian@0 56 {
ian@0 57 unsigned long flags;
ian@0 58 int cnode;
ian@0 59
ian@0 60 spin_lock_irqsave(&prom_lock, flags);
ian@0 61 cnode = prom_nodeops->no_nextnode(node);
ian@0 62 restore_current();
ian@0 63 spin_unlock_irqrestore(&prom_lock, flags);
ian@0 64
ian@0 65 return cnode;
ian@0 66 }
ian@0 67
ian@0 68 /* Return the next sibling of node 'node' or zero if no more siblings
ian@0 69 * at this level of depth in the tree.
ian@0 70 */
ian@0 71 int prom_getsibling(int node)
ian@0 72 {
ian@0 73 int sibnode;
ian@0 74
ian@0 75 if (node == -1)
ian@0 76 return 0;
ian@0 77
ian@0 78 sibnode = __prom_getsibling(node);
ian@0 79 if (sibnode == 0 || sibnode == -1)
ian@0 80 return 0;
ian@0 81
ian@0 82 return sibnode;
ian@0 83 }
ian@0 84
ian@0 85 /* Return the length in bytes of property 'prop' at node 'node'.
ian@0 86 * Return -1 on error.
ian@0 87 */
ian@0 88 int prom_getproplen(int node, char *prop)
ian@0 89 {
ian@0 90 int ret;
ian@0 91 unsigned long flags;
ian@0 92
ian@0 93 if((!node) || (!prop))
ian@0 94 return -1;
ian@0 95
ian@0 96 spin_lock_irqsave(&prom_lock, flags);
ian@0 97 ret = prom_nodeops->no_proplen(node, prop);
ian@0 98 restore_current();
ian@0 99 spin_unlock_irqrestore(&prom_lock, flags);
ian@0 100 return ret;
ian@0 101 }
ian@0 102
ian@0 103 /* Acquire a property 'prop' at node 'node' and place it in
ian@0 104 * 'buffer' which has a size of 'bufsize'. If the acquisition
ian@0 105 * was successful the length will be returned, else -1 is returned.
ian@0 106 */
ian@0 107 int prom_getproperty(int node, char *prop, char *buffer, int bufsize)
ian@0 108 {
ian@0 109 int plen, ret;
ian@0 110 unsigned long flags;
ian@0 111
ian@0 112 plen = prom_getproplen(node, prop);
ian@0 113 if((plen > bufsize) || (plen == 0) || (plen == -1))
ian@0 114 return -1;
ian@0 115 /* Ok, things seem all right. */
ian@0 116 spin_lock_irqsave(&prom_lock, flags);
ian@0 117 ret = prom_nodeops->no_getprop(node, prop, buffer);
ian@0 118 restore_current();
ian@0 119 spin_unlock_irqrestore(&prom_lock, flags);
ian@0 120 return ret;
ian@0 121 }
ian@0 122
ian@0 123 /* Acquire an integer property and return its value. Returns -1
ian@0 124 * on failure.
ian@0 125 */
ian@0 126 int prom_getint(int node, char *prop)
ian@0 127 {
ian@0 128 static int intprop;
ian@0 129
ian@0 130 if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
ian@0 131 return intprop;
ian@0 132
ian@0 133 return -1;
ian@0 134 }
ian@0 135
ian@0 136 /* Acquire an integer property, upon error return the passed default
ian@0 137 * integer.
ian@0 138 */
ian@0 139 int prom_getintdefault(int node, char *property, int deflt)
ian@0 140 {
ian@0 141 int retval;
ian@0 142
ian@0 143 retval = prom_getint(node, property);
ian@0 144 if(retval == -1) return deflt;
ian@0 145
ian@0 146 return retval;
ian@0 147 }
ian@0 148
ian@0 149 /* Acquire a boolean property, 1=TRUE 0=FALSE. */
ian@0 150 int prom_getbool(int node, char *prop)
ian@0 151 {
ian@0 152 int retval;
ian@0 153
ian@0 154 retval = prom_getproplen(node, prop);
ian@0 155 if(retval == -1) return 0;
ian@0 156 return 1;
ian@0 157 }
ian@0 158
ian@0 159 /* Acquire a property whose value is a string, returns a null
ian@0 160 * string on error. The char pointer is the user supplied string
ian@0 161 * buffer.
ian@0 162 */
ian@0 163 void prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
ian@0 164 {
ian@0 165 int len;
ian@0 166
ian@0 167 len = prom_getproperty(node, prop, user_buf, ubuf_size);
ian@0 168 if(len != -1) return;
ian@0 169 user_buf[0] = 0;
ian@0 170 return;
ian@0 171 }
ian@0 172
ian@0 173
ian@0 174 /* Does the device at node 'node' have name 'name'?
ian@0 175 * YES = 1 NO = 0
ian@0 176 */
ian@0 177 int prom_nodematch(int node, char *name)
ian@0 178 {
ian@0 179 int error;
ian@0 180
ian@0 181 static char namebuf[128];
ian@0 182 error = prom_getproperty(node, "name", namebuf, sizeof(namebuf));
ian@0 183 if (error == -1) return 0;
ian@0 184 if(strcmp(namebuf, name) == 0) return 1;
ian@0 185 return 0;
ian@0 186 }
ian@0 187
ian@0 188 /* Search siblings at 'node_start' for a node with name
ian@0 189 * 'nodename'. Return node if successful, zero if not.
ian@0 190 */
ian@0 191 int prom_searchsiblings(int node_start, char *nodename)
ian@0 192 {
ian@0 193
ian@0 194 int thisnode, error;
ian@0 195
ian@0 196 for(thisnode = node_start; thisnode;
ian@0 197 thisnode=prom_getsibling(thisnode)) {
ian@0 198 error = prom_getproperty(thisnode, "name", promlib_buf,
ian@0 199 sizeof(promlib_buf));
ian@0 200 /* Should this ever happen? */
ian@0 201 if(error == -1) continue;
ian@0 202 if(strcmp(nodename, promlib_buf)==0) return thisnode;
ian@0 203 }
ian@0 204
ian@0 205 return 0;
ian@0 206 }
ian@0 207
ian@0 208 /* Interal version of nextprop that does not alter return values. */
ian@0 209 char * __prom_nextprop(int node, char * oprop)
ian@0 210 {
ian@0 211 unsigned long flags;
ian@0 212 char *prop;
ian@0 213
ian@0 214 spin_lock_irqsave(&prom_lock, flags);
ian@0 215 prop = prom_nodeops->no_nextprop(node, oprop);
ian@0 216 restore_current();
ian@0 217 spin_unlock_irqrestore(&prom_lock, flags);
ian@0 218
ian@0 219 return prop;
ian@0 220 }
ian@0 221
ian@0 222 /* Return the first property name for node 'node'. */
ian@0 223 /* buffer is unused argument, but as v9 uses it, we need to have the same interface */
ian@0 224 char * prom_firstprop(int node, char *bufer)
ian@0 225 {
ian@0 226 if (node == 0 || node == -1)
ian@0 227 return "";
ian@0 228
ian@0 229 return __prom_nextprop(node, "");
ian@0 230 }
ian@0 231
ian@0 232 /* Return the property type string after property type 'oprop'
ian@0 233 * at node 'node' . Returns empty string if no more
ian@0 234 * property types for this node.
ian@0 235 */
ian@0 236 char * prom_nextprop(int node, char *oprop, char *buffer)
ian@0 237 {
ian@0 238 if (node == 0 || node == -1)
ian@0 239 return "";
ian@0 240
ian@0 241 return __prom_nextprop(node, oprop);
ian@0 242 }
ian@0 243
ian@0 244 int prom_finddevice(char *name)
ian@0 245 {
ian@0 246 char nbuf[128];
ian@0 247 char *s = name, *d;
ian@0 248 int node = prom_root_node, node2;
ian@0 249 unsigned int which_io, phys_addr;
ian@0 250 struct linux_prom_registers reg[PROMREG_MAX];
ian@0 251
ian@0 252 while (*s++) {
ian@0 253 if (!*s) return node; /* path '.../' is legal */
ian@0 254 node = prom_getchild(node);
ian@0 255
ian@0 256 for (d = nbuf; *s != 0 && *s != '@' && *s != '/';)
ian@0 257 *d++ = *s++;
ian@0 258 *d = 0;
ian@0 259
ian@0 260 node = prom_searchsiblings(node, nbuf);
ian@0 261 if (!node)
ian@0 262 return 0;
ian@0 263
ian@0 264 if (*s == '@') {
ian@0 265 if (isxdigit(s[1]) && s[2] == ',') {
ian@0 266 which_io = simple_strtoul(s+1, NULL, 16);
ian@0 267 phys_addr = simple_strtoul(s+3, &d, 16);
ian@0 268 if (d != s + 3 && (!*d || *d == '/')
ian@0 269 && d <= s + 3 + 8) {
ian@0 270 node2 = node;
ian@0 271 while (node2 && node2 != -1) {
ian@0 272 if (prom_getproperty (node2, "reg", (char *)reg, sizeof (reg)) > 0) {
ian@0 273 if (which_io == reg[0].which_io && phys_addr == reg[0].phys_addr) {
ian@0 274 node = node2;
ian@0 275 break;
ian@0 276 }
ian@0 277 }
ian@0 278 node2 = prom_getsibling(node2);
ian@0 279 if (!node2 || node2 == -1)
ian@0 280 break;
ian@0 281 node2 = prom_searchsiblings(prom_getsibling(node2), nbuf);
ian@0 282 }
ian@0 283 }
ian@0 284 }
ian@0 285 while (*s != 0 && *s != '/') s++;
ian@0 286 }
ian@0 287 }
ian@0 288 return node;
ian@0 289 }
ian@0 290
ian@0 291 int prom_node_has_property(int node, char *prop)
ian@0 292 {
ian@0 293 char *current_property = "";
ian@0 294
ian@0 295 do {
ian@0 296 current_property = prom_nextprop(node, current_property, NULL);
ian@0 297 if(!strcmp(current_property, prop))
ian@0 298 return 1;
ian@0 299 } while (*current_property);
ian@0 300 return 0;
ian@0 301 }
ian@0 302
ian@0 303 /* Set property 'pname' at node 'node' to value 'value' which has a length
ian@0 304 * of 'size' bytes. Return the number of bytes the prom accepted.
ian@0 305 */
ian@0 306 int prom_setprop(int node, char *pname, char *value, int size)
ian@0 307 {
ian@0 308 unsigned long flags;
ian@0 309 int ret;
ian@0 310
ian@0 311 if(size == 0) return 0;
ian@0 312 if((pname == 0) || (value == 0)) return 0;
ian@0 313 spin_lock_irqsave(&prom_lock, flags);
ian@0 314 ret = prom_nodeops->no_setprop(node, pname, value, size);
ian@0 315 restore_current();
ian@0 316 spin_unlock_irqrestore(&prom_lock, flags);
ian@0 317 return ret;
ian@0 318 }
ian@0 319
ian@0 320 int prom_inst2pkg(int inst)
ian@0 321 {
ian@0 322 int node;
ian@0 323 unsigned long flags;
ian@0 324
ian@0 325 spin_lock_irqsave(&prom_lock, flags);
ian@0 326 node = (*romvec->pv_v2devops.v2_inst2pkg)(inst);
ian@0 327 restore_current();
ian@0 328 spin_unlock_irqrestore(&prom_lock, flags);
ian@0 329 if (node == -1) return 0;
ian@0 330 return node;
ian@0 331 }
ian@0 332
ian@0 333 /* Return 'node' assigned to a particular prom 'path'
ian@0 334 * FIXME: Should work for v0 as well
ian@0 335 */
ian@0 336 int prom_pathtoinode(char *path)
ian@0 337 {
ian@0 338 int node, inst;
ian@0 339
ian@0 340 inst = prom_devopen (path);
ian@0 341 if (inst == -1) return 0;
ian@0 342 node = prom_inst2pkg (inst);
ian@0 343 prom_devclose (inst);
ian@0 344 if (node == -1) return 0;
ian@0 345 return node;
ian@0 346 }