ia64/linux-2.6.18-xen.hg

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