ia64/xen-unstable

view tools/python/xen/xend/balloon.py @ 19848:5839491bbf20

[IA64] replace MAX_VCPUS with d->max_vcpus where necessary.

don't use MAX_VCPUS, and use vcpu::max_vcpus.
The changeset of 2f9e1348aa98 introduced max_vcpus to allow more vcpus
per guest. This patch is ia64 counter part.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Mon Jun 29 11:26:05 2009 +0900 (2009-06-29)
parents f210a633571c
children
line source
1 #===========================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
16 # Copyright (C) 2005 XenSource Ltd
17 #============================================================================
20 import time
22 import xen.lowlevel.xc
24 import XendDomain
25 import XendOptions
26 from XendLogging import log
27 from XendError import VmError
28 import osdep
29 from xen.xend.XendConstants import *
31 RETRY_LIMIT = 20
32 RETRY_LIMIT_INCR = 5
33 ##
34 # The time to sleep between retries grows linearly, using this value (in
35 # seconds). When the system is lightly loaded, memory should be scrubbed and
36 # returned to the system very quickly, whereas when it is loaded, the system
37 # needs idle time to get the scrubbing done. This linear growth accommodates
38 # such requirements.
39 SLEEP_TIME_GROWTH = 0.1
41 # A mapping between easy-to-remember labels and the more verbose
42 # label actually shown in the PROC_XEN_BALLOON file.
43 #labels = { 'current' : 'Current allocation',
44 # 'target' : 'Requested target',
45 # 'low-balloon' : 'Low-mem balloon',
46 # 'high-balloon' : 'High-mem balloon',
47 # 'limit' : 'Xen hard limit' }
49 def _get_proc_balloon(label):
50 """Returns the value for the named label. Returns None if the label was
51 not found or the value was non-numeric."""
53 return osdep.lookup_balloon_stat(label)
55 def get_dom0_current_alloc():
56 """Returns the current memory allocation (in KiB) of dom0."""
58 kb = _get_proc_balloon('current')
59 if kb == None:
60 raise VmError('Failed to query current memory allocation of dom0.')
61 return kb
63 def get_dom0_target_alloc():
64 """Returns the target memory allocation (in KiB) of dom0."""
66 kb = _get_proc_balloon('target')
67 if kb == None:
68 raise VmError('Failed to query target memory allocation of dom0.')
69 return kb
71 def free(need_mem, dominfo):
72 """Balloon out memory from the privileged domain so that there is the
73 specified required amount (in KiB) free.
74 """
76 # We check whether there is enough free memory, and if not, instruct dom0
77 # to balloon out to free some up. Memory freed by a destroyed domain may
78 # not appear in the free_memory field immediately, because it needs to be
79 # scrubbed before it can be released to the free list, which is done
80 # asynchronously by Xen; ballooning is asynchronous also. Such memory
81 # does, however, need to be accounted for when calculating how much dom0
82 # needs to balloon. No matter where we expect the free memory to come
83 # from, we need to wait for it to become available.
84 #
85 # We are not allowed to balloon below dom0_min_mem, or if dom0_ballooning
86 # is False, we cannot balloon at all. Memory can still become available
87 # through a rebooting domain, however.
88 #
89 # Eventually, we time out (presumably because there really isn't enough
90 # free memory).
91 #
92 # We don't want to set the memory target (triggering a watch) when that
93 # has already been done, but we do want to respond to changing memory
94 # usage, so we recheck the required alloc each time around the loop, but
95 # track the last used value so that we don't trigger too many watches.
97 xoptions = XendOptions.instance()
98 dom0 = XendDomain.instance().privilegedDomain()
99 xc = xen.lowlevel.xc.xc()
101 try:
102 dom0_min_mem = xoptions.get_dom0_min_mem() * 1024
103 dom0_ballooning = xoptions.get_enable_dom0_ballooning()
104 dom0_alloc = get_dom0_current_alloc()
106 retries = 0
107 sleep_time = SLEEP_TIME_GROWTH
108 new_alloc = 0
109 last_new_alloc = None
110 last_free = None
111 rlimit = RETRY_LIMIT
113 # stop tmem from absorbing any more memory (must THAW when done!)
114 xc.tmem_control(0,TMEMC_FREEZE,-1, 0, 0, "")
116 # If unreasonable memory size is required, we give up waiting
117 # for ballooning or scrubbing, as if had retried.
118 physinfo = xc.physinfo()
119 free_mem = physinfo['free_memory']
120 scrub_mem = physinfo['scrub_memory']
121 total_mem = physinfo['total_memory']
122 if dom0_ballooning:
123 max_free_mem = total_mem - dom0_min_mem
124 else:
125 max_free_mem = total_mem - dom0_alloc
126 if need_mem >= max_free_mem:
127 retries = rlimit
129 freeable_mem = free_mem + scrub_mem
130 if freeable_mem < need_mem and need_mem < max_free_mem:
131 # flush memory from tmem to scrub_mem and reobtain physinfo
132 need_tmem_kb = need_mem - freeable_mem
133 tmem_kb = xc.tmem_control(0,TMEMC_FLUSH,-1, need_tmem_kb, 0, "")
134 log.debug("Balloon: tmem relinquished %d KiB of %d KiB requested.",
135 tmem_kb, need_tmem_kb)
136 physinfo = xc.physinfo()
137 free_mem = physinfo['free_memory']
138 scrub_mem = physinfo['scrub_memory']
140 # Check whethercurrent machine is a numa system and the new
141 # created hvm has all its vcpus in the same node, if all the
142 # conditions above are fit. We will wait until all the pages
143 # in scrub list are freed (if waiting time go beyond 20s,
144 # we will stop waiting it.)
145 if physinfo['nr_nodes'] > 1 and retries == 0:
146 oldnode = -1
147 waitscrub = 1
148 vcpus = dominfo.info['cpus'][0]
149 for vcpu in vcpus:
150 nodenum = 0
151 for node in physinfo['node_to_cpu']:
152 for cpu in node:
153 if vcpu == cpu:
154 if oldnode == -1:
155 oldnode = nodenum
156 elif oldnode != nodenum:
157 waitscrub = 0
158 nodenum = nodenum + 1
160 if waitscrub == 1 and scrub_mem > 0:
161 log.debug("wait for scrub %s", scrub_mem)
162 while scrub_mem > 0 and retries < rlimit:
163 time.sleep(sleep_time)
164 physinfo = xc.physinfo()
165 free_mem = physinfo['free_memory']
166 scrub_mem = physinfo['scrub_memory']
167 retries += 1
168 sleep_time += SLEEP_TIME_GROWTH
169 log.debug("scrub for %d times", retries)
171 retries = 0
172 sleep_time = SLEEP_TIME_GROWTH
174 while retries < rlimit:
175 physinfo = xc.physinfo()
176 free_mem = physinfo['free_memory']
177 scrub_mem = physinfo['scrub_memory']
179 if free_mem >= need_mem:
180 log.debug("Balloon: %d KiB free; need %d; done.",
181 free_mem, need_mem)
182 return
184 if retries == 0:
185 rlimit += ((need_mem - free_mem)/1024/1024) * RETRY_LIMIT_INCR
186 log.debug("Balloon: %d KiB free; %d to scrub; need %d; retries: %d.",
187 free_mem, scrub_mem, need_mem, rlimit)
189 if dom0_ballooning:
190 dom0_alloc = get_dom0_current_alloc()
191 new_alloc = dom0_alloc - (need_mem - free_mem - scrub_mem)
193 if free_mem + scrub_mem >= need_mem:
194 if last_new_alloc == None:
195 log.debug("Balloon: waiting on scrubbing")
196 last_new_alloc = dom0_alloc
197 else:
198 if (new_alloc >= dom0_min_mem and
199 new_alloc != last_new_alloc):
200 new_alloc_mb = new_alloc / 1024 # Round down
201 log.debug("Balloon: setting dom0 target to %d MiB.",
202 new_alloc_mb)
203 dom0.setMemoryTarget(new_alloc_mb)
204 last_new_alloc = new_alloc
205 # Continue to retry, waiting for ballooning or scrubbing.
207 time.sleep(sleep_time)
208 if retries < 2 * RETRY_LIMIT:
209 sleep_time += SLEEP_TIME_GROWTH
210 if last_free != None and last_free >= free_mem + scrub_mem:
211 retries += 1
212 last_free = free_mem + scrub_mem
214 # Not enough memory; diagnose the problem.
215 if not dom0_ballooning:
216 raise VmError(('Not enough free memory and enable-dom0-ballooning '
217 'is False, so I cannot release any more. '
218 'I need %d KiB but only have %d.') %
219 (need_mem, free_mem))
220 elif new_alloc < dom0_min_mem:
221 raise VmError(
222 ('I need %d KiB, but dom0_min_mem is %d and shrinking to '
223 '%d KiB would leave only %d KiB free.') %
224 (need_mem, dom0_min_mem, dom0_min_mem,
225 free_mem + scrub_mem + dom0_alloc - dom0_min_mem))
226 else:
227 dom0_start_alloc_mb = get_dom0_current_alloc() / 1024
228 dom0.setMemoryTarget(dom0_start_alloc_mb)
229 raise VmError(
230 ('Not enough memory is available, and dom0 cannot'
231 ' be shrunk any further'))
233 finally:
234 # allow tmem to accept pages again
235 xc.tmem_control(0,TMEMC_THAW,-1, 0, 0, "")
236 del xc