⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 balloon.py

📁 xen 3.2.2 源码
💻 PY
字号:
#===========================================================================# This library is free software; you can redistribute it and/or# modify it under the terms of version 2.1 of the GNU Lesser General Public# License as published by the Free Software Foundation.## This library is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU# Lesser General Public License for more details.## You should have received a copy of the GNU Lesser General Public# License along with this library; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA#============================================================================# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com># Copyright (C) 2005 XenSource Ltd#============================================================================import timeimport xen.lowlevel.xcimport XendDomainimport XendOptionsfrom XendLogging import logfrom XendError import VmErrorimport osdepRETRY_LIMIT = 20RETRY_LIMIT_INCR = 5### The time to sleep between retries grows linearly, using this value (in# seconds).  When the system is lightly loaded, memory should be scrubbed and# returned to the system very quickly, whereas when it is loaded, the system# needs idle time to get the scrubbing done.  This linear growth accommodates# such requirements.SLEEP_TIME_GROWTH = 0.1# A mapping between easy-to-remember labels and the more verbose# label actually shown in the PROC_XEN_BALLOON file.labels = { 'current'      : 'Current allocation',           'target'       : 'Requested target',           'low-balloon'  : 'Low-mem balloon',           'high-balloon' : 'High-mem balloon',           'limit'        : 'Xen hard limit' }def _get_proc_balloon(label):    """Returns the value for the named label.  Returns None if the label was       not found or the value was non-numeric."""    return osdep.lookup_balloon_stat(label)def get_dom0_current_alloc():    """Returns the current memory allocation (in KiB) of dom0."""    kb = _get_proc_balloon(labels['current'])    if kb == None:        raise VmError('Failed to query current memory allocation of dom0.')    return kbdef get_dom0_target_alloc():    """Returns the target memory allocation (in KiB) of dom0."""    kb = _get_proc_balloon(labels['target'])    if kb == None:        raise VmError('Failed to query target memory allocation of dom0.')    return kbdef free(need_mem):    """Balloon out memory from the privileged domain so that there is the    specified required amount (in KiB) free.    """    # We check whether there is enough free memory, and if not, instruct dom0    # to balloon out to free some up.  Memory freed by a destroyed domain may    # not appear in the free_memory field immediately, because it needs to be    # scrubbed before it can be released to the free list, which is done    # asynchronously by Xen; ballooning is asynchronous also.  Such memory    # does, however, need to be accounted for when calculating how much dom0    # needs to balloon.  No matter where we expect the free memory to come    # from, we need to wait for it to become available.    #    # We are not allowed to balloon below dom0_min_mem, or if dom0_min_mem    # is 0, we cannot balloon at all.  Memory can still become available    # through a rebooting domain, however.    #    # Eventually, we time out (presumably because there really isn't enough    # free memory).    #    # We don't want to set the memory target (triggering a watch) when that    # has already been done, but we do want to respond to changing memory    # usage, so we recheck the required alloc each time around the loop, but    # track the last used value so that we don't trigger too many watches.    xoptions = XendOptions.instance()    dom0 = XendDomain.instance().privilegedDomain()    xc = xen.lowlevel.xc.xc()    dom0_start_alloc_mb = get_dom0_current_alloc() / 1024    try:        dom0_min_mem = xoptions.get_dom0_min_mem() * 1024        dom0_alloc = get_dom0_current_alloc()        retries = 0        sleep_time = SLEEP_TIME_GROWTH        new_alloc = 0        last_new_alloc = None        last_free = None        rlimit = RETRY_LIMIT        # If unreasonable memory size is required, we give up waiting        # for ballooning or scrubbing, as if had retried.        physinfo = xc.physinfo()        free_mem = physinfo['free_memory']        scrub_mem = physinfo['scrub_memory']        total_mem = physinfo['total_memory']        if dom0_min_mem > 0:            max_free_mem = total_mem - dom0_min_mem        else:            max_free_mem = total_mem - dom0_alloc        if need_mem >= max_free_mem:            retries = rlimit        while retries < rlimit:            physinfo = xc.physinfo()            free_mem = physinfo['free_memory']            scrub_mem = physinfo['scrub_memory']            if free_mem >= need_mem:                log.debug("Balloon: %d KiB free; need %d; done.",                          free_mem, need_mem)                return            if retries == 0:                rlimit += ((need_mem - free_mem)/1024/1024) * RETRY_LIMIT_INCR                log.debug("Balloon: %d KiB free; %d to scrub; need %d; retries: %d.",                          free_mem, scrub_mem, need_mem, rlimit)            if dom0_min_mem > 0:                dom0_alloc = get_dom0_current_alloc()                new_alloc = dom0_alloc - (need_mem - free_mem - scrub_mem)                if free_mem + scrub_mem >= need_mem:                    if last_new_alloc == None:                        log.debug("Balloon: waiting on scrubbing")                        last_new_alloc = dom0_alloc                else:                    if (new_alloc >= dom0_min_mem and                        new_alloc != last_new_alloc):                        new_alloc_mb = new_alloc / 1024  # Round down                        log.debug("Balloon: setting dom0 target to %d MiB.",                                  new_alloc_mb)                        dom0.setMemoryTarget(new_alloc_mb)                        last_new_alloc = new_alloc                # Continue to retry, waiting for ballooning or scrubbing.            time.sleep(sleep_time)            if retries < 2 * RETRY_LIMIT:                sleep_time += SLEEP_TIME_GROWTH            if last_free != None and last_free >= free_mem + scrub_mem:                retries += 1            last_free = free_mem + scrub_mem        # Not enough memory; diagnose the problem.        if dom0_min_mem == 0:            raise VmError(('Not enough free memory and dom0_min_mem is 0, so '                           'I cannot release any more.  I need %d KiB but '                           'only have %d.') %                          (need_mem, free_mem))        elif new_alloc < dom0_min_mem:            raise VmError(                ('I need %d KiB, but dom0_min_mem is %d and shrinking to '                 '%d KiB would leave only %d KiB free.') %                (need_mem, dom0_min_mem, dom0_min_mem,                 free_mem + scrub_mem + dom0_alloc - dom0_min_mem))        else:            dom0.setMemoryTarget(dom0_start_alloc_mb)            raise VmError(                ('Not enough memory is available, and dom0 cannot'                 ' be shrunk any further'))    finally:        del xc

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -