ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/err_common.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 /*
2 * linux/arch/alpha/kernel/err_common.c
3 *
4 * Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
5 *
6 * Error handling code supporting Alpha systems
7 */
9 #include <linux/init.h>
10 #include <linux/pci.h>
11 #include <linux/sched.h>
13 #include <asm/io.h>
14 #include <asm/hwrpb.h>
15 #include <asm/smp.h>
16 #include <asm/err_common.h>
18 #include "err_impl.h"
19 #include "proto.h"
21 /*
22 * err_print_prefix -- error handling print routines should prefix
23 * all prints with this
24 */
25 char *err_print_prefix = KERN_NOTICE;
28 /*
29 * Generic
30 */
31 void
32 mchk_dump_mem(void *data, size_t length, char **annotation)
33 {
34 unsigned long *ldata = data;
35 size_t i;
37 for (i = 0; (i * sizeof(*ldata)) < length; i++) {
38 if (annotation && !annotation[i])
39 annotation = NULL;
40 printk("%s %08x: %016lx %s\n",
41 err_print_prefix,
42 (unsigned)(i * sizeof(*ldata)), ldata[i],
43 annotation ? annotation[i] : "");
44 }
45 }
47 void
48 mchk_dump_logout_frame(struct el_common *mchk_header)
49 {
50 printk("%s -- Frame Header --\n"
51 " Frame Size: %d (0x%x) bytes\n"
52 " Flags: %s%s\n"
53 " MCHK Code: 0x%x\n"
54 " Frame Rev: %d\n"
55 " Proc Offset: 0x%08x\n"
56 " Sys Offset: 0x%08x\n"
57 " -- Processor Region --\n",
58 err_print_prefix,
59 mchk_header->size, mchk_header->size,
60 mchk_header->retry ? "RETRY " : "",
61 mchk_header->err2 ? "SECOND_ERR " : "",
62 mchk_header->code,
63 mchk_header->frame_rev,
64 mchk_header->proc_offset,
65 mchk_header->sys_offset);
67 mchk_dump_mem((void *)
68 ((unsigned long)mchk_header + mchk_header->proc_offset),
69 mchk_header->sys_offset - mchk_header->proc_offset,
70 NULL);
72 printk("%s -- System Region --\n", err_print_prefix);
73 mchk_dump_mem((void *)
74 ((unsigned long)mchk_header + mchk_header->sys_offset),
75 mchk_header->size - mchk_header->sys_offset,
76 NULL);
77 printk("%s -- End of Frame --\n", err_print_prefix);
78 }
81 /*
82 * Console Data Log
83 */
84 /* Data */
85 static struct el_subpacket_handler *subpacket_handler_list = NULL;
86 static struct el_subpacket_annotation *subpacket_annotation_list = NULL;
88 static struct el_subpacket *
89 el_process_header_subpacket(struct el_subpacket *header)
90 {
91 union el_timestamp timestamp;
92 char *name = "UNKNOWN EVENT";
93 int packet_count = 0;
94 int length = 0;
96 if (header->class != EL_CLASS__HEADER) {
97 printk("%s** Unexpected header CLASS %d TYPE %d, aborting\n",
98 err_print_prefix,
99 header->class, header->type);
100 return NULL;
101 }
103 switch(header->type) {
104 case EL_TYPE__HEADER__SYSTEM_ERROR_FRAME:
105 name = "SYSTEM ERROR";
106 length = header->by_type.sys_err.frame_length;
107 packet_count =
108 header->by_type.sys_err.frame_packet_count;
109 timestamp.as_int = 0;
110 break;
111 case EL_TYPE__HEADER__SYSTEM_EVENT_FRAME:
112 name = "SYSTEM EVENT";
113 length = header->by_type.sys_event.frame_length;
114 packet_count =
115 header->by_type.sys_event.frame_packet_count;
116 timestamp = header->by_type.sys_event.timestamp;
117 break;
118 case EL_TYPE__HEADER__HALT_FRAME:
119 name = "ERROR HALT";
120 length = header->by_type.err_halt.frame_length;
121 packet_count =
122 header->by_type.err_halt.frame_packet_count;
123 timestamp = header->by_type.err_halt.timestamp;
124 break;
125 case EL_TYPE__HEADER__LOGOUT_FRAME:
126 name = "LOGOUT FRAME";
127 length = header->by_type.logout_header.frame_length;
128 packet_count = 1;
129 timestamp.as_int = 0;
130 break;
131 default: /* Unknown */
132 printk("%s** Unknown header - CLASS %d TYPE %d, aborting\n",
133 err_print_prefix,
134 header->class, header->type);
135 return NULL;
136 }
138 printk("%s*** %s:\n"
139 " CLASS %d, TYPE %d\n",
140 err_print_prefix,
141 name,
142 header->class, header->type);
143 el_print_timestamp(&timestamp);
145 /*
146 * Process the subpackets
147 */
148 el_process_subpackets(header, packet_count);
150 /* return the next header */
151 header = (struct el_subpacket *)
152 ((unsigned long)header + header->length + length);
153 return header;
154 }
156 static struct el_subpacket *
157 el_process_subpacket_reg(struct el_subpacket *header)
158 {
159 struct el_subpacket *next = NULL;
160 struct el_subpacket_handler *h = subpacket_handler_list;
162 for (; h && h->class != header->class; h = h->next);
163 if (h) next = h->handler(header);
165 return next;
166 }
168 void
169 el_print_timestamp(union el_timestamp *timestamp)
170 {
171 if (timestamp->as_int)
172 printk("%s TIMESTAMP: %d/%d/%02d %d:%02d:%0d\n",
173 err_print_prefix,
174 timestamp->b.month, timestamp->b.day,
175 timestamp->b.year, timestamp->b.hour,
176 timestamp->b.minute, timestamp->b.second);
177 }
179 void
180 el_process_subpackets(struct el_subpacket *header, int packet_count)
181 {
182 struct el_subpacket *subpacket;
183 int i;
185 subpacket = (struct el_subpacket *)
186 ((unsigned long)header + header->length);
188 for (i = 0; subpacket && i < packet_count; i++) {
189 printk("%sPROCESSING SUBPACKET %d\n", err_print_prefix, i);
190 subpacket = el_process_subpacket(subpacket);
191 }
192 }
194 struct el_subpacket *
195 el_process_subpacket(struct el_subpacket *header)
196 {
197 struct el_subpacket *next = NULL;
199 switch(header->class) {
200 case EL_CLASS__TERMINATION:
201 /* Termination packet, there are no more */
202 break;
203 case EL_CLASS__HEADER:
204 next = el_process_header_subpacket(header);
205 break;
206 default:
207 if (NULL == (next = el_process_subpacket_reg(header))) {
208 printk("%s** Unexpected header CLASS %d TYPE %d"
209 " -- aborting.\n",
210 err_print_prefix,
211 header->class, header->type);
212 }
213 break;
214 }
216 return next;
217 }
219 void
220 el_annotate_subpacket(struct el_subpacket *header)
221 {
222 struct el_subpacket_annotation *a;
223 char **annotation = NULL;
225 for (a = subpacket_annotation_list; a; a = a->next) {
226 if (a->class == header->class &&
227 a->type == header->type &&
228 a->revision == header->revision) {
229 /*
230 * We found the annotation
231 */
232 annotation = a->annotation;
233 printk("%s %s\n", err_print_prefix, a->description);
234 break;
235 }
236 }
238 mchk_dump_mem(header, header->length, annotation);
239 }
241 static void __init
242 cdl_process_console_data_log(int cpu, struct percpu_struct *pcpu)
243 {
244 struct el_subpacket *header = (struct el_subpacket *)
245 (IDENT_ADDR | pcpu->console_data_log_pa);
246 int err;
248 printk("%s******* CONSOLE DATA LOG FOR CPU %d. *******\n"
249 "*** Error(s) were logged on a previous boot\n",
250 err_print_prefix, cpu);
252 for (err = 0; header && (header->class != EL_CLASS__TERMINATION); err++)
253 header = el_process_subpacket(header);
255 /* let the console know it's ok to clear the error(s) at restart */
256 pcpu->console_data_log_pa = 0;
258 printk("%s*** %d total error(s) logged\n"
259 "**** END OF CONSOLE DATA LOG FOR CPU %d ****\n",
260 err_print_prefix, err, cpu);
261 }
263 void __init
264 cdl_check_console_data_log(void)
265 {
266 struct percpu_struct *pcpu;
267 unsigned long cpu;
269 for (cpu = 0; cpu < hwrpb->nr_processors; cpu++) {
270 pcpu = (struct percpu_struct *)
271 ((unsigned long)hwrpb + hwrpb->processor_offset
272 + cpu * hwrpb->processor_size);
273 if (pcpu->console_data_log_pa)
274 cdl_process_console_data_log(cpu, pcpu);
275 }
277 }
279 int __init
280 cdl_register_subpacket_annotation(struct el_subpacket_annotation *new)
281 {
282 struct el_subpacket_annotation *a = subpacket_annotation_list;
284 if (a == NULL) subpacket_annotation_list = new;
285 else {
286 for (; a->next != NULL; a = a->next) {
287 if ((a->class == new->class && a->type == new->type) ||
288 a == new) {
289 printk("Attempted to re-register "
290 "subpacket annotation\n");
291 return -EINVAL;
292 }
293 }
294 a->next = new;
295 }
296 new->next = NULL;
298 return 0;
299 }
301 int __init
302 cdl_register_subpacket_handler(struct el_subpacket_handler *new)
303 {
304 struct el_subpacket_handler *h = subpacket_handler_list;
306 if (h == NULL) subpacket_handler_list = new;
307 else {
308 for (; h->next != NULL; h = h->next) {
309 if (h->class == new->class || h == new) {
310 printk("Attempted to re-register "
311 "subpacket handler\n");
312 return -EINVAL;
313 }
314 }
315 h->next = new;
316 }
317 new->next = NULL;
319 return 0;
320 }