ia64/linux-2.6.18-xen.hg

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