ia64/xen-unstable

annotate tools/python/xen/xend/balloon.py @ 17827:4c1e740e392c

xend: minor ballooning cleanup

In xend/balloon.py, there's only one place where dom0_start_alloc_mb
is used. Move its initialization to right before its usage.

Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jun 10 14:53:01 2008 +0100 (2008-06-10)
parents 6143f5bd32a7
children 0bf73f557f41
rev   line source
emellor@8161 1 #===========================================================================
emellor@8161 2 # This library is free software; you can redistribute it and/or
emellor@8161 3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
emellor@8161 4 # License as published by the Free Software Foundation.
emellor@8161 5 #
emellor@8161 6 # This library is distributed in the hope that it will be useful,
emellor@8161 7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
emellor@8161 8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
emellor@8161 9 # Lesser General Public License for more details.
emellor@8161 10 #
emellor@8161 11 # You should have received a copy of the GNU Lesser General Public
emellor@8161 12 # License along with this library; if not, write to the Free Software
emellor@8161 13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
emellor@8161 14 #============================================================================
emellor@8161 15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
emellor@8161 16 # Copyright (C) 2005 XenSource Ltd
emellor@8161 17 #============================================================================
emellor@8161 18
emellor@8161 19
emellor@8161 20 import time
emellor@8161 21
emellor@8161 22 import xen.lowlevel.xc
emellor@8161 23
emellor@8161 24 import XendDomain
ewan@13484 25 import XendOptions
emellor@8161 26 from XendLogging import log
emellor@8161 27 from XendError import VmError
keir@14686 28 import osdep
emellor@9221 29
emellor@10521 30 RETRY_LIMIT = 20
kaf24@10185 31 RETRY_LIMIT_INCR = 5
emellor@8277 32 ##
emellor@8277 33 # The time to sleep between retries grows linearly, using this value (in
emellor@8277 34 # seconds). When the system is lightly loaded, memory should be scrubbed and
emellor@8277 35 # returned to the system very quickly, whereas when it is loaded, the system
emellor@8277 36 # needs idle time to get the scrubbing done. This linear growth accommodates
emellor@8277 37 # such requirements.
emellor@8277 38 SLEEP_TIME_GROWTH = 0.1
emellor@8161 39
emellor@9221 40 # A mapping between easy-to-remember labels and the more verbose
emellor@9221 41 # label actually shown in the PROC_XEN_BALLOON file.
emellor@9221 42 labels = { 'current' : 'Current allocation',
emellor@9221 43 'target' : 'Requested target',
emellor@9221 44 'low-balloon' : 'Low-mem balloon',
emellor@9221 45 'high-balloon' : 'High-mem balloon',
emellor@9221 46 'limit' : 'Xen hard limit' }
emellor@9221 47
emellor@9221 48 def _get_proc_balloon(label):
emellor@9221 49 """Returns the value for the named label. Returns None if the label was
emellor@9221 50 not found or the value was non-numeric."""
emellor@9221 51
keir@14686 52 return osdep.lookup_balloon_stat(label)
emellor@9221 53
emellor@9221 54 def get_dom0_current_alloc():
kaf24@10541 55 """Returns the current memory allocation (in KiB) of dom0."""
emellor@9221 56
emellor@9221 57 kb = _get_proc_balloon(labels['current'])
emellor@9221 58 if kb == None:
emellor@9221 59 raise VmError('Failed to query current memory allocation of dom0.')
kaf24@10541 60 return kb
emellor@9221 61
emellor@9221 62 def get_dom0_target_alloc():
kaf24@10541 63 """Returns the target memory allocation (in KiB) of dom0."""
emellor@9221 64
emellor@9221 65 kb = _get_proc_balloon(labels['target'])
emellor@9221 66 if kb == None:
emellor@9221 67 raise VmError('Failed to query target memory allocation of dom0.')
kaf24@10541 68 return kb
emellor@8161 69
kaf24@10541 70 def free(need_mem):
emellor@8161 71 """Balloon out memory from the privileged domain so that there is the
emellor@8161 72 specified required amount (in KiB) free.
emellor@8161 73 """
emellor@8277 74
emellor@8277 75 # We check whether there is enough free memory, and if not, instruct dom0
emellor@8277 76 # to balloon out to free some up. Memory freed by a destroyed domain may
emellor@8277 77 # not appear in the free_memory field immediately, because it needs to be
emellor@8277 78 # scrubbed before it can be released to the free list, which is done
kaf24@10541 79 # asynchronously by Xen; ballooning is asynchronous also. Such memory
kaf24@10541 80 # does, however, need to be accounted for when calculating how much dom0
kaf24@10541 81 # needs to balloon. No matter where we expect the free memory to come
kaf24@10541 82 # from, we need to wait for it to become available.
emellor@8277 83 #
keir@17401 84 # We are not allowed to balloon below dom0_min_mem, or if dom0_ballooning
keir@17401 85 # is False, we cannot balloon at all. Memory can still become available
emellor@8277 86 # through a rebooting domain, however.
emellor@8277 87 #
emellor@8277 88 # Eventually, we time out (presumably because there really isn't enough
emellor@8277 89 # free memory).
emellor@8277 90 #
emellor@8277 91 # We don't want to set the memory target (triggering a watch) when that
emellor@8277 92 # has already been done, but we do want to respond to changing memory
emellor@8277 93 # usage, so we recheck the required alloc each time around the loop, but
emellor@8277 94 # track the last used value so that we don't trigger too many watches.
emellor@8277 95
ewan@13484 96 xoptions = XendOptions.instance()
kfraser@15628 97 dom0 = XendDomain.instance().privilegedDomain()
emellor@8161 98 xc = xen.lowlevel.xc.xc()
emellor@8161 99
emellor@8161 100 try:
ewan@13484 101 dom0_min_mem = xoptions.get_dom0_min_mem() * 1024
keir@17401 102 dom0_ballooning = xoptions.get_enable_dom0_ballooning()
keir@15976 103 dom0_alloc = get_dom0_current_alloc()
emellor@8161 104
emellor@8277 105 retries = 0
emellor@8277 106 sleep_time = SLEEP_TIME_GROWTH
keir@15976 107 new_alloc = 0
emellor@8277 108 last_new_alloc = None
kfraser@15306 109 last_free = None
kaf24@10185 110 rlimit = RETRY_LIMIT
keir@15976 111
keir@15976 112 # If unreasonable memory size is required, we give up waiting
keir@15976 113 # for ballooning or scrubbing, as if had retried.
keir@15976 114 physinfo = xc.physinfo()
keir@15976 115 free_mem = physinfo['free_memory']
keir@15976 116 scrub_mem = physinfo['scrub_memory']
keir@15976 117 total_mem = physinfo['total_memory']
keir@17401 118 if dom0_ballooning:
keir@15976 119 max_free_mem = total_mem - dom0_min_mem
keir@15976 120 else:
keir@15976 121 max_free_mem = total_mem - dom0_alloc
keir@15976 122 if need_mem >= max_free_mem:
keir@15976 123 retries = rlimit
keir@15976 124
kaf24@10185 125 while retries < rlimit:
kaf24@10541 126 physinfo = xc.physinfo()
kaf24@10541 127 free_mem = physinfo['free_memory']
kaf24@10541 128 scrub_mem = physinfo['scrub_memory']
emellor@8161 129
emellor@8277 130 if free_mem >= need_mem:
kaf24@10541 131 log.debug("Balloon: %d KiB free; need %d; done.",
kaf24@10541 132 free_mem, need_mem)
emellor@8277 133 return
emellor@8277 134
emellor@8277 135 if retries == 0:
kaf24@10541 136 rlimit += ((need_mem - free_mem)/1024/1024) * RETRY_LIMIT_INCR
kaf24@10541 137 log.debug("Balloon: %d KiB free; %d to scrub; need %d; retries: %d.",
kaf24@10541 138 free_mem, scrub_mem, need_mem, rlimit)
emellor@8277 139
keir@17401 140 if dom0_ballooning:
emellor@9221 141 dom0_alloc = get_dom0_current_alloc()
kaf24@10541 142 new_alloc = dom0_alloc - (need_mem - free_mem - scrub_mem)
emellor@8277 143
kaf24@10541 144 if free_mem + scrub_mem >= need_mem:
kaf24@10541 145 if last_new_alloc == None:
kaf24@10541 146 log.debug("Balloon: waiting on scrubbing")
kaf24@10541 147 last_new_alloc = dom0_alloc
kaf24@10541 148 else:
kaf24@10541 149 if (new_alloc >= dom0_min_mem and
kaf24@10541 150 new_alloc != last_new_alloc):
kaf24@10541 151 new_alloc_mb = new_alloc / 1024 # Round down
kaf24@10541 152 log.debug("Balloon: setting dom0 target to %d MiB.",
kaf24@10541 153 new_alloc_mb)
kaf24@10541 154 dom0.setMemoryTarget(new_alloc_mb)
kaf24@10541 155 last_new_alloc = new_alloc
kaf24@10541 156 # Continue to retry, waiting for ballooning or scrubbing.
emellor@8277 157
emellor@8277 158 time.sleep(sleep_time)
kaf24@10185 159 if retries < 2 * RETRY_LIMIT:
kaf24@10185 160 sleep_time += SLEEP_TIME_GROWTH
kfraser@15306 161 if last_free != None and last_free >= free_mem + scrub_mem:
kfraser@15306 162 retries += 1
kfraser@15306 163 last_free = free_mem + scrub_mem
emellor@8277 164
emellor@8277 165 # Not enough memory; diagnose the problem.
keir@17401 166 if not dom0_ballooning:
keir@17401 167 raise VmError(('Not enough free memory and enable-dom0-ballooning '
keir@17401 168 'is False, so I cannot release any more. '
keir@17401 169 'I need %d KiB but only have %d.') %
emellor@8277 170 (need_mem, free_mem))
kaf24@9562 171 elif new_alloc < dom0_min_mem:
emellor@8161 172 raise VmError(
kaf24@10541 173 ('I need %d KiB, but dom0_min_mem is %d and shrinking to '
kaf24@10541 174 '%d KiB would leave only %d KiB free.') %
emellor@8161 175 (need_mem, dom0_min_mem, dom0_min_mem,
kaf24@10541 176 free_mem + scrub_mem + dom0_alloc - dom0_min_mem))
emellor@8277 177 else:
keir@17827 178 dom0_start_alloc_mb = get_dom0_current_alloc() / 1024
kfraser@15628 179 dom0.setMemoryTarget(dom0_start_alloc_mb)
kfraser@15628 180 raise VmError(
kfraser@15628 181 ('Not enough memory is available, and dom0 cannot'
kfraser@15628 182 ' be shrunk any further'))
emellor@8161 183
emellor@8161 184 finally:
emellor@8161 185 del xc