ia64/linux-2.6.18-xen.hg

view arch/mips/sgi-ip27/ip27-klnuma.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 * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00.
3 * Copyright 2000 - 2001 Silicon Graphics, Inc.
4 * Copyright 2000 - 2001 Kanoj Sarcar (kanoj@sgi.com)
5 */
6 #include <linux/init.h>
7 #include <linux/mmzone.h>
8 #include <linux/kernel.h>
9 #include <linux/nodemask.h>
10 #include <linux/string.h>
12 #include <asm/page.h>
13 #include <asm/sections.h>
14 #include <asm/smp.h>
15 #include <asm/sn/types.h>
16 #include <asm/sn/arch.h>
17 #include <asm/sn/gda.h>
18 #include <asm/sn/hub.h>
19 #include <asm/sn/mapped_kernel.h>
20 #include <asm/sn/sn_private.h>
22 static cpumask_t ktext_repmask;
24 /*
25 * XXX - This needs to be much smarter about where it puts copies of the
26 * kernel. For example, we should never put a copy on a headless node,
27 * and we should respect the topology of the machine.
28 */
29 void __init setup_replication_mask()
30 {
31 cnodeid_t cnode;
33 /* Set only the master cnode's bit. The master cnode is always 0. */
34 cpus_clear(ktext_repmask);
35 cpu_set(0, ktext_repmask);
37 #ifdef CONFIG_REPLICATE_KTEXT
38 #ifndef CONFIG_MAPPED_KERNEL
39 #error Kernel replication works with mapped kernel support. No calias support.
40 #endif
41 for_each_online_node(cnode) {
42 if (cnode == 0)
43 continue;
44 /* Advertise that we have a copy of the kernel */
45 cpu_set(cnode, ktext_repmask);
46 }
47 #endif
48 /* Set up a GDA pointer to the replication mask. */
49 GDA->g_ktext_repmask = &ktext_repmask;
50 }
53 static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid)
54 {
55 cnodeid_t client_cnode;
56 kern_vars_t *kvp;
58 client_cnode = NASID_TO_COMPACT_NODEID(client_nasid);
60 kvp = &hub_data(client_nasid)->kern_vars;
62 KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp;
64 kvp->kv_magic = KV_MAGIC;
65 kvp->kv_ro_nasid = server_nasid;
66 kvp->kv_rw_nasid = master_nasid;
67 kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid);
68 kvp->kv_rw_baseaddr = NODE_CAC_BASE(master_nasid);
69 printk("REPLICATION: ON nasid %d, ktext from nasid %d, kdata from nasid %d\n", client_nasid, server_nasid, master_nasid);
70 }
72 /* XXX - When the BTE works, we should use it instead of this. */
73 static __init void copy_kernel(nasid_t dest_nasid)
74 {
75 unsigned long dest_kern_start, source_start, source_end, kern_size;
77 source_start = (unsigned long) _stext;
78 source_end = (unsigned long) _etext;
79 kern_size = source_end - source_start;
81 dest_kern_start = CHANGE_ADDR_NASID(MAPPED_KERN_RO_TO_K0(source_start),
82 dest_nasid);
83 memcpy((void *)dest_kern_start, (void *)source_start, kern_size);
84 }
86 void __init replicate_kernel_text()
87 {
88 cnodeid_t cnode;
89 nasid_t client_nasid;
90 nasid_t server_nasid;
92 server_nasid = master_nasid;
94 /* Record where the master node should get its kernel text */
95 set_ktext_source(master_nasid, master_nasid);
97 for_each_online_node(cnode) {
98 if (cnode == 0)
99 continue;
100 client_nasid = COMPACT_TO_NASID_NODEID(cnode);
102 /* Check if this node should get a copy of the kernel */
103 if (cpu_isset(cnode, ktext_repmask)) {
104 server_nasid = client_nasid;
105 copy_kernel(server_nasid);
106 }
108 /* Record where this node should get its kernel text */
109 set_ktext_source(client_nasid, server_nasid);
110 }
111 }
113 /*
114 * Return pfn of first free page of memory on a node. PROM may allocate
115 * data structures on the first couple of pages of the first slot of each
116 * node. If this is the case, getfirstfree(node) > getslotstart(node, 0).
117 */
118 pfn_t node_getfirstfree(cnodeid_t cnode)
119 {
120 unsigned long loadbase = REP_BASE;
121 nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
122 unsigned long offset;
124 #ifdef CONFIG_MAPPED_KERNEL
125 loadbase += 16777216;
126 #endif
127 offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase;
128 if ((cnode == 0) || (cpu_isset(cnode, ktext_repmask)))
129 return (TO_NODE(nasid, offset) >> PAGE_SHIFT);
130 else
131 return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >>
132 PAGE_SHIFT);
133 }