ia64/linux-2.6.18-xen.hg

view arch/sparc/prom/console.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: console.c,v 1.25 2001/10/30 04:54:22 davem Exp $
2 * console.c: Routines that deal with sending and receiving IO
3 * to/from the current console device using the PROM.
4 *
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 * Copyright (C) 1998 Pete Zaitcev <zaitcev@yahoo.com>
7 */
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/sched.h>
12 #include <asm/openprom.h>
13 #include <asm/sun4prom.h>
14 #include <asm/oplib.h>
15 #include <asm/system.h>
16 #include <linux/string.h>
18 extern void restore_current(void);
20 static char con_name_jmc[] = "/obio/su@"; /* "/obio/su@0,3002f8"; */
21 #define CON_SIZE_JMC (sizeof(con_name_jmc))
23 /* Non blocking get character from console input device, returns -1
24 * if no input was taken. This can be used for polling.
25 */
26 int
27 prom_nbgetchar(void)
28 {
29 static char inc;
30 int i = -1;
31 unsigned long flags;
33 spin_lock_irqsave(&prom_lock, flags);
34 switch(prom_vers) {
35 case PROM_V0:
36 case PROM_SUN4:
37 i = (*(romvec->pv_nbgetchar))();
38 break;
39 case PROM_V2:
40 case PROM_V3:
41 if( (*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin , &inc, 0x1) == 1) {
42 i = inc;
43 } else {
44 i = -1;
45 }
46 break;
47 default:
48 i = -1;
49 break;
50 };
51 restore_current();
52 spin_unlock_irqrestore(&prom_lock, flags);
53 return i; /* Ugh, we could spin forever on unsupported proms ;( */
54 }
56 /* Non blocking put character to console device, returns -1 if
57 * unsuccessful.
58 */
59 int
60 prom_nbputchar(char c)
61 {
62 static char outc;
63 unsigned long flags;
64 int i = -1;
66 spin_lock_irqsave(&prom_lock, flags);
67 switch(prom_vers) {
68 case PROM_V0:
69 case PROM_SUN4:
70 i = (*(romvec->pv_nbputchar))(c);
71 break;
72 case PROM_V2:
73 case PROM_V3:
74 outc = c;
75 if( (*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, &outc, 0x1) == 1)
76 i = 0;
77 else
78 i = -1;
79 break;
80 default:
81 i = -1;
82 break;
83 };
84 restore_current();
85 spin_unlock_irqrestore(&prom_lock, flags);
86 return i; /* Ugh, we could spin forever on unsupported proms ;( */
87 }
89 /* Blocking version of get character routine above. */
90 char
91 prom_getchar(void)
92 {
93 int character;
94 while((character = prom_nbgetchar()) == -1) ;
95 return (char) character;
96 }
98 /* Blocking version of put character routine above. */
99 void
100 prom_putchar(char c)
101 {
102 while(prom_nbputchar(c) == -1) ;
103 return;
104 }
106 /* Query for input device type */
107 enum prom_input_device
108 prom_query_input_device(void)
109 {
110 unsigned long flags;
111 int st_p;
112 char propb[64];
113 char *p;
114 int propl;
116 switch(prom_vers) {
117 case PROM_V0:
118 case PROM_V2:
119 case PROM_SUN4:
120 default:
121 switch(*romvec->pv_stdin) {
122 case PROMDEV_KBD: return PROMDEV_IKBD;
123 case PROMDEV_TTYA: return PROMDEV_ITTYA;
124 case PROMDEV_TTYB: return PROMDEV_ITTYB;
125 default:
126 return PROMDEV_I_UNK;
127 };
128 case PROM_V3:
129 spin_lock_irqsave(&prom_lock, flags);
130 st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
131 restore_current();
132 spin_unlock_irqrestore(&prom_lock, flags);
133 if(prom_node_has_property(st_p, "keyboard"))
134 return PROMDEV_IKBD;
135 if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) {
136 if(strncmp(propb, "keyboard", sizeof("serial")) == 0)
137 return PROMDEV_IKBD;
138 }
139 if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) {
140 if(strncmp(propb, "serial", sizeof("serial")))
141 return PROMDEV_I_UNK;
142 }
143 propl = prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
144 if(propl > 2) {
145 p = propb;
146 while(*p) p++; p -= 2;
147 if(p[0] == ':') {
148 if(p[1] == 'a')
149 return PROMDEV_ITTYA;
150 else if(p[1] == 'b')
151 return PROMDEV_ITTYB;
152 }
153 }
154 return PROMDEV_I_UNK;
155 }
156 }
158 /* Query for output device type */
160 enum prom_output_device
161 prom_query_output_device(void)
162 {
163 unsigned long flags;
164 int st_p;
165 char propb[64];
166 char *p;
167 int propl;
169 switch(prom_vers) {
170 case PROM_V0:
171 case PROM_SUN4:
172 switch(*romvec->pv_stdin) {
173 case PROMDEV_SCREEN: return PROMDEV_OSCREEN;
174 case PROMDEV_TTYA: return PROMDEV_OTTYA;
175 case PROMDEV_TTYB: return PROMDEV_OTTYB;
176 };
177 break;
178 case PROM_V2:
179 case PROM_V3:
180 spin_lock_irqsave(&prom_lock, flags);
181 st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
182 restore_current();
183 spin_unlock_irqrestore(&prom_lock, flags);
184 propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
185 if (propl == sizeof("display") &&
186 strncmp("display", propb, sizeof("display")) == 0)
187 {
188 return PROMDEV_OSCREEN;
189 }
190 if(prom_vers == PROM_V3) {
191 if(propl >= 0 &&
192 strncmp("serial", propb, sizeof("serial")) != 0)
193 return PROMDEV_O_UNK;
194 propl = prom_getproperty(prom_root_node, "stdout-path",
195 propb, sizeof(propb));
196 if(propl == CON_SIZE_JMC &&
197 strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0)
198 return PROMDEV_OTTYA;
199 if(propl > 2) {
200 p = propb;
201 while(*p) p++; p-= 2;
202 if(p[0]==':') {
203 if(p[1] == 'a')
204 return PROMDEV_OTTYA;
205 else if(p[1] == 'b')
206 return PROMDEV_OTTYB;
207 }
208 }
209 } else {
210 switch(*romvec->pv_stdin) {
211 case PROMDEV_TTYA: return PROMDEV_OTTYA;
212 case PROMDEV_TTYB: return PROMDEV_OTTYB;
213 };
214 }
215 break;
216 default:
217 ;
218 };
219 return PROMDEV_O_UNK;
220 }