mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
xc_domain_getinfolist() internally relies on a sysctl that performs a linear search for the domids. Many callers of xc_domain_getinfolist() who require information about a precise domid are much better off calling xc_domain_getinfo_single() instead, that will use the getdomaininfo domctl instead and ensure the returned domid matches the requested one. The domtctl will find the domid faster too, because that uses hashed lists. Signed-off-by: Alejandro Vallejo <alejandro.vallejo@cloud.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Acked-by: Christian Lindig <christian.lindig@cloud.com> Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
660 lines
18 KiB
C
660 lines
18 KiB
C
/*
|
|
* Copyright 2009-2017 Citrix Ltd and other contributors
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; version 2.1 only. with the special
|
|
* exception on linking described in file LICENSE.
|
|
*
|
|
* This program 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.
|
|
*/
|
|
|
|
#include "libxl_osdeps.h"
|
|
|
|
#include "libxl_internal.h"
|
|
#include "libxl_arch.h"
|
|
|
|
/*
|
|
* Set the maximum memory size of the domain in the hypervisor. There is no
|
|
* change of the current memory size involved. The specified memory size can
|
|
* even be above the configured maxmem size of the domain.
|
|
*/
|
|
int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint64_t max_memkb)
|
|
{
|
|
GC_INIT(ctx);
|
|
char *mem, *endptr;
|
|
uint64_t memorykb, size;
|
|
char *dompath = libxl__xs_get_dompath(gc, domid);
|
|
int rc = 1;
|
|
libxl__flock *lock = NULL;
|
|
libxl_domain_config d_config;
|
|
|
|
libxl_domain_config_init(&d_config);
|
|
|
|
CTX_LOCK;
|
|
|
|
lock = libxl__lock_domain_userdata(gc, domid);
|
|
if (!lock) {
|
|
rc = ERROR_LOCK_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
mem = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/memory/target", dompath));
|
|
if (!mem) {
|
|
LOGED(ERROR, domid, "Cannot get memory info from %s/memory/target",
|
|
dompath);
|
|
goto out;
|
|
}
|
|
memorykb = strtoull(mem, &endptr, 10);
|
|
if (*endptr != '\0') {
|
|
LOGED(ERROR, domid, "Invalid memory %s from %s/memory/target\n",
|
|
mem, dompath);
|
|
goto out;
|
|
}
|
|
|
|
if (max_memkb < memorykb) {
|
|
LOGED(ERROR, domid,
|
|
"memory_static_max must be greater than or or equal to memory_dynamic_max");
|
|
goto out;
|
|
}
|
|
|
|
rc = libxl__get_domain_configuration(gc, domid, &d_config);
|
|
if (rc < 0) {
|
|
LOGE(ERROR, "unable to retrieve domain configuration");
|
|
goto out;
|
|
}
|
|
|
|
rc = libxl__arch_extra_memory(gc, &d_config.b_info, &size);
|
|
if (rc < 0) {
|
|
LOGE(ERROR, "Couldn't get arch extra constant memory size");
|
|
goto out;
|
|
}
|
|
|
|
rc = xc_domain_setmaxmem(ctx->xch, domid, max_memkb + size);
|
|
if (rc != 0) {
|
|
LOGED(ERROR, domid,
|
|
"xc_domain_setmaxmem domid=%d memkb=%"PRIu64" failed ""rc=%d\n",
|
|
domid, max_memkb + size, rc);
|
|
goto out;
|
|
}
|
|
|
|
rc = libxl__xs_printf(gc, XBT_NULL,
|
|
GCSPRINTF("%s/memory/static-max", dompath),
|
|
"%"PRIu64, max_memkb);
|
|
if (rc != 0) {
|
|
LOGED(ERROR, domid, "Couldn't set %s/memory/static-max, rc=%d\n",
|
|
dompath, rc);
|
|
goto out;
|
|
}
|
|
|
|
rc = 0;
|
|
out:
|
|
libxl_domain_config_dispose(&d_config);
|
|
if (lock) libxl__unlock_file(lock);
|
|
CTX_UNLOCK;
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
static int libxl__fill_dom0_memory_info(libxl__gc *gc, uint64_t *target_memkb,
|
|
uint64_t *max_memkb)
|
|
{
|
|
int rc;
|
|
libxl_dominfo info;
|
|
libxl_physinfo physinfo;
|
|
char *target = NULL, *staticmax = NULL, *endptr = NULL;
|
|
char *target_path = "/local/domain/0/memory/target";
|
|
char *max_path = "/local/domain/0/memory/static-max";
|
|
xs_transaction_t t;
|
|
libxl_ctx *ctx = libxl__gc_owner(gc);
|
|
|
|
libxl_dominfo_init(&info);
|
|
|
|
retry_transaction:
|
|
t = xs_transaction_start(ctx->xsh);
|
|
|
|
target = libxl__xs_read(gc, t, target_path);
|
|
staticmax = libxl__xs_read(gc, t, max_path);
|
|
if (target && staticmax) {
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
if (target) {
|
|
*target_memkb = strtoull(target, &endptr, 10);
|
|
if (*endptr != '\0') {
|
|
LOGED(ERROR, 0, "Invalid memory target %s from %s\n", target,
|
|
target_path);
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
if (staticmax) {
|
|
*max_memkb = strtoull(staticmax, &endptr, 10);
|
|
if (*endptr != '\0') {
|
|
LOGED(ERROR, 0, "Invalid memory static-max %s from %s\n",
|
|
staticmax,
|
|
max_path);
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
libxl_dominfo_dispose(&info);
|
|
libxl_dominfo_init(&info);
|
|
rc = libxl_domain_info(ctx, &info, 0);
|
|
if (rc < 0)
|
|
goto out;
|
|
|
|
rc = libxl_get_physinfo(ctx, &physinfo);
|
|
if (rc < 0)
|
|
goto out;
|
|
|
|
if (target == NULL) {
|
|
libxl__xs_printf(gc, t, target_path, "%"PRIu64, info.current_memkb);
|
|
*target_memkb = info.current_memkb;
|
|
}
|
|
if (staticmax == NULL) {
|
|
libxl__xs_printf(gc, t, max_path, "%"PRIu64, info.max_memkb);
|
|
*max_memkb = info.max_memkb;
|
|
}
|
|
|
|
rc = 0;
|
|
|
|
out:
|
|
if (!xs_transaction_end(ctx->xsh, t, 0)) {
|
|
if (errno == EAGAIN)
|
|
goto retry_transaction;
|
|
else
|
|
rc = ERROR_FAIL;
|
|
}
|
|
|
|
libxl_dominfo_dispose(&info);
|
|
return rc;
|
|
}
|
|
|
|
int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid,
|
|
int64_t target_memkb, int relative, int enforce)
|
|
{
|
|
GC_INIT(ctx);
|
|
int rc, r, lrc, abort_transaction = 0;
|
|
uint64_t memorykb, size;
|
|
uint64_t videoram = 0;
|
|
uint64_t current_target_memkb = 0, new_target_memkb = 0;
|
|
uint64_t current_max_memkb = 0;
|
|
char *memmax, *endptr, *videoram_s = NULL, *target = NULL;
|
|
char *dompath = libxl__xs_get_dompath(gc, domid);
|
|
xc_domaininfo_t info;
|
|
libxl_dominfo ptr;
|
|
char *uuid;
|
|
xs_transaction_t t;
|
|
libxl__flock *lock;
|
|
libxl_domain_config d_config;
|
|
|
|
libxl_domain_config_init(&d_config);
|
|
|
|
CTX_LOCK;
|
|
|
|
lock = libxl__lock_domain_userdata(gc, domid);
|
|
if (!lock) {
|
|
rc = ERROR_LOCK_FAIL;
|
|
goto out_no_transaction;
|
|
}
|
|
|
|
rc = libxl__get_domain_configuration(gc, domid, &d_config);
|
|
if (rc < 0) {
|
|
LOGE(ERROR, "unable to retrieve domain configuration");
|
|
goto out_no_transaction;
|
|
}
|
|
|
|
rc = libxl__arch_extra_memory(gc, &d_config.b_info, &size);
|
|
if (rc < 0) {
|
|
LOGE(ERROR, "Couldn't get arch extra constant memory size");
|
|
goto out_no_transaction;
|
|
}
|
|
|
|
retry_transaction:
|
|
t = xs_transaction_start(ctx->xsh);
|
|
|
|
target = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/target", dompath));
|
|
if (!target && !domid) {
|
|
if (!xs_transaction_end(ctx->xsh, t, 1)) {
|
|
rc = ERROR_FAIL;
|
|
goto out_no_transaction;
|
|
}
|
|
lrc = libxl__fill_dom0_memory_info(gc, ¤t_target_memkb,
|
|
¤t_max_memkb);
|
|
if (lrc < 0) { rc = ERROR_FAIL; goto out_no_transaction; }
|
|
goto retry_transaction;
|
|
} else if (!target) {
|
|
LOGED(ERROR, domid, "Cannot get target memory info from %s/memory/target",
|
|
dompath);
|
|
abort_transaction = 1;
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
} else {
|
|
current_target_memkb = strtoull(target, &endptr, 10);
|
|
if (*endptr != '\0') {
|
|
LOGED(ERROR, domid, "Invalid memory target %s from %s/memory/target\n",
|
|
target, dompath);
|
|
abort_transaction = 1;
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
}
|
|
memmax = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/static-max", dompath));
|
|
if (!memmax) {
|
|
LOGED(ERROR, domid, "Cannot get memory info from %s/memory/static-max",
|
|
dompath);
|
|
abort_transaction = 1;
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
memorykb = strtoull(memmax, &endptr, 10);
|
|
if (*endptr != '\0') {
|
|
LOGED(ERROR, domid, "Invalid max memory %s from %s/memory/static-max\n",
|
|
memmax, dompath);
|
|
abort_transaction = 1;
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
videoram_s = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/videoram",
|
|
dompath));
|
|
videoram = videoram_s ? atoi(videoram_s) : 0;
|
|
|
|
if (relative) {
|
|
if (target_memkb < 0 && llabs(target_memkb) > current_target_memkb)
|
|
new_target_memkb = 0;
|
|
else
|
|
new_target_memkb = current_target_memkb + target_memkb;
|
|
} else
|
|
new_target_memkb = target_memkb - videoram;
|
|
if (new_target_memkb > memorykb) {
|
|
LOGD(ERROR, domid,
|
|
"memory_dynamic_max must be less than or equal to"
|
|
" memory_static_max\n");
|
|
abort_transaction = 1;
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
if (!domid && new_target_memkb < LIBXL_MIN_DOM0_MEM) {
|
|
LOGD(ERROR, domid,
|
|
"New target %"PRIu64" for dom0 is below the minimum threshold",
|
|
new_target_memkb);
|
|
abort_transaction = 1;
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
if (enforce) {
|
|
memorykb = new_target_memkb + videoram;
|
|
r = xc_domain_setmaxmem(ctx->xch, domid, memorykb + size);
|
|
if (r != 0) {
|
|
LOGED(ERROR, domid,
|
|
"xc_domain_setmaxmem memkb=%"PRIu64" failed ""rc=%d\n",
|
|
memorykb + size,
|
|
r);
|
|
abort_transaction = 1;
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
if (d_config.c_info.type != LIBXL_DOMAIN_TYPE_PV) {
|
|
r = xc_domain_set_pod_target(ctx->xch, domid,
|
|
(new_target_memkb + size) / 4, NULL, NULL, NULL);
|
|
if (r != 0) {
|
|
LOGED(ERROR, domid,
|
|
"xc_domain_set_pod_target memkb=%"PRIu64" failed rc=%d\n",
|
|
(new_target_memkb + size) / 4,
|
|
r);
|
|
abort_transaction = 1;
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
libxl__xs_printf(gc, t, GCSPRINTF("%s/memory/target", dompath),
|
|
"%"PRIu64, new_target_memkb);
|
|
|
|
r = xc_domain_getinfo_single(ctx->xch, domid, &info);
|
|
if (r < 0) {
|
|
abort_transaction = 1;
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
libxl_dominfo_init(&ptr);
|
|
libxl__xcinfo2xlinfo(ctx, &info, &ptr);
|
|
uuid = libxl__uuid2string(gc, ptr.uuid);
|
|
libxl__xs_printf(gc, t, GCSPRINTF("/vm/%s/memory", uuid),
|
|
"%"PRIu64, new_target_memkb / 1024);
|
|
libxl_dominfo_dispose(&ptr);
|
|
|
|
rc = 0;
|
|
out:
|
|
if (!xs_transaction_end(ctx->xsh, t, abort_transaction)
|
|
&& !abort_transaction)
|
|
if (errno == EAGAIN)
|
|
goto retry_transaction;
|
|
|
|
out_no_transaction:
|
|
libxl_domain_config_dispose(&d_config);
|
|
if (lock) libxl__unlock_file(lock);
|
|
CTX_UNLOCK;
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
/* out_target_memkb and out_max_memkb can be NULL */
|
|
int libxl__get_memory_target(libxl__gc *gc, uint32_t domid,
|
|
uint64_t *out_target_memkb,
|
|
uint64_t *out_max_memkb)
|
|
{
|
|
int rc;
|
|
char *target = NULL, *static_max = NULL, *endptr = NULL;
|
|
char *dompath = libxl__xs_get_dompath(gc, domid);
|
|
uint64_t target_memkb, max_memkb;
|
|
|
|
target = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/memory/target",
|
|
dompath));
|
|
static_max = libxl__xs_read(gc, XBT_NULL,
|
|
GCSPRINTF("%s/memory/static-max", dompath));
|
|
|
|
rc = ERROR_FAIL;
|
|
if ((!target || !static_max) && !domid) {
|
|
rc = libxl__fill_dom0_memory_info(gc, &target_memkb,
|
|
&max_memkb);
|
|
if (rc < 0)
|
|
goto out;
|
|
} else if (!target) {
|
|
LOGED(ERROR, domid, "Cannot get target memory info from %s/memory/target",
|
|
dompath);
|
|
goto out;
|
|
} else if (!static_max) {
|
|
LOGED(ERROR, domid,
|
|
"Cannot get target memory info from %s/memory/static-max",
|
|
dompath);
|
|
goto out;
|
|
} else {
|
|
target_memkb = strtoull(target, &endptr, 10);
|
|
if (*endptr != '\0') {
|
|
LOGED(ERROR, domid, "Invalid memory target %s from %s/memory/target\n",
|
|
target, dompath);
|
|
goto out;
|
|
}
|
|
max_memkb = strtoull(static_max, &endptr, 10);
|
|
if (*endptr != '\0') {
|
|
LOGED(ERROR, domid,
|
|
"Invalid memory target %s from %s/memory/static-max\n",
|
|
static_max,
|
|
dompath);
|
|
goto out;
|
|
}
|
|
|
|
}
|
|
|
|
if (out_target_memkb)
|
|
*out_target_memkb = target_memkb;
|
|
|
|
if (out_max_memkb)
|
|
*out_max_memkb = max_memkb;
|
|
|
|
rc = 0;
|
|
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
static int libxl__memkb_64to32(libxl_ctx *ctx, int rc,
|
|
uint64_t val64, uint32_t *ptr32)
|
|
{
|
|
GC_INIT(ctx);
|
|
|
|
if (rc)
|
|
goto out;
|
|
|
|
*ptr32 = val64;
|
|
if (*ptr32 == val64)
|
|
goto out;
|
|
|
|
LOGE(ERROR, "memory size %"PRIu64" too large for 32 bit value\n", val64);
|
|
rc = ERROR_FAIL;
|
|
|
|
out:
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_get_memory_target(libxl_ctx *ctx, uint32_t domid,
|
|
uint64_t *out_target)
|
|
{
|
|
GC_INIT(ctx);
|
|
int rc;
|
|
|
|
rc = libxl__get_memory_target(gc, domid, out_target, NULL);
|
|
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_get_memory_target_0x040700(
|
|
libxl_ctx *ctx, uint32_t domid, uint32_t *out_target)
|
|
{
|
|
uint64_t my_out_target;
|
|
int rc;
|
|
|
|
rc = libxl_get_memory_target(ctx, domid, &my_out_target);
|
|
return libxl__memkb_64to32(ctx, rc, my_out_target, out_target);
|
|
}
|
|
|
|
int libxl__domain_need_memory_calculate(libxl__gc *gc,
|
|
libxl_domain_build_info *b_info,
|
|
uint64_t *need_memkb)
|
|
{
|
|
int rc;
|
|
|
|
*need_memkb = b_info->target_memkb;
|
|
*need_memkb += b_info->shadow_memkb + b_info->iommu_memkb;
|
|
|
|
switch (b_info->type) {
|
|
case LIBXL_DOMAIN_TYPE_PVH:
|
|
case LIBXL_DOMAIN_TYPE_HVM:
|
|
*need_memkb += LIBXL_HVM_EXTRA_MEMORY;
|
|
if (libxl_defbool_val(b_info->device_model_stubdomain)) {
|
|
*need_memkb += b_info->stubdomain_memkb;
|
|
*need_memkb += b_info->video_memkb;
|
|
}
|
|
break;
|
|
case LIBXL_DOMAIN_TYPE_PV:
|
|
*need_memkb += LIBXL_PV_EXTRA_MEMORY;
|
|
break;
|
|
default:
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
if (*need_memkb % (2 * 1024))
|
|
*need_memkb += (2 * 1024) - (*need_memkb % (2 * 1024));
|
|
rc = 0;
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
int libxl_domain_need_memory(libxl_ctx *ctx,
|
|
libxl_domain_config *d_config,
|
|
uint32_t domid_for_logging,
|
|
uint64_t *need_memkb)
|
|
{
|
|
GC_INIT(ctx);
|
|
int rc;
|
|
|
|
ctx->libxl_domain_need_memory_called = 1;
|
|
|
|
rc = libxl__domain_config_setdefault(gc,
|
|
d_config,
|
|
domid_for_logging);
|
|
if (rc) goto out;
|
|
|
|
rc = libxl__domain_need_memory_calculate(gc,
|
|
&d_config->b_info,
|
|
need_memkb);
|
|
if (rc) goto out;
|
|
|
|
rc = 0;
|
|
out:
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_domain_need_memory_0x041200(libxl_ctx *ctx,
|
|
const libxl_domain_build_info *b_info_in,
|
|
uint64_t *need_memkb)
|
|
{
|
|
GC_INIT(ctx);
|
|
int rc;
|
|
|
|
ctx->libxl_domain_need_memory_0x041200_called = 1;
|
|
|
|
libxl_domain_build_info b_info[1];
|
|
libxl_domain_build_info_init(b_info);
|
|
libxl_domain_build_info_copy(ctx, b_info, b_info_in);
|
|
|
|
rc = libxl__domain_build_info_setdefault(gc, b_info);
|
|
if (rc) goto out;
|
|
|
|
rc = libxl__domain_need_memory_calculate(gc,
|
|
b_info,
|
|
need_memkb);
|
|
if (rc) goto out;
|
|
|
|
rc = 0;
|
|
out:
|
|
libxl_domain_build_info_dispose(b_info);
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_domain_need_memory_0x040700(libxl_ctx *ctx,
|
|
const libxl_domain_build_info *b_info_in,
|
|
uint32_t *need_memkb)
|
|
{
|
|
uint64_t my_need_memkb;
|
|
int rc;
|
|
|
|
rc = libxl_domain_need_memory_0x041200(ctx, b_info_in, &my_need_memkb);
|
|
return libxl__memkb_64to32(ctx, rc, my_need_memkb, need_memkb);
|
|
}
|
|
|
|
int libxl_get_free_memory(libxl_ctx *ctx, uint64_t *memkb)
|
|
{
|
|
int rc = 0;
|
|
libxl_physinfo info;
|
|
GC_INIT(ctx);
|
|
|
|
rc = libxl_get_physinfo(ctx, &info);
|
|
if (rc < 0)
|
|
goto out;
|
|
|
|
*memkb = (info.free_pages + info.scrub_pages) * 4;
|
|
|
|
out:
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_get_free_memory_0x040700(libxl_ctx *ctx, uint32_t *memkb)
|
|
{
|
|
uint64_t my_memkb = 0;
|
|
int rc;
|
|
|
|
rc = libxl_get_free_memory(ctx, &my_memkb);
|
|
return libxl__memkb_64to32(ctx, rc, my_memkb, memkb);
|
|
}
|
|
|
|
int libxl_wait_for_free_memory(libxl_ctx *ctx, uint32_t domid,
|
|
uint64_t memory_kb, int wait_secs)
|
|
{
|
|
int rc = 0;
|
|
libxl_physinfo info;
|
|
GC_INIT(ctx);
|
|
|
|
while (wait_secs > 0) {
|
|
rc = libxl_get_physinfo(ctx, &info);
|
|
if (rc < 0)
|
|
goto out;
|
|
if (info.free_pages * 4 >= memory_kb) {
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
wait_secs--;
|
|
sleep(1);
|
|
}
|
|
rc = ERROR_NOMEM;
|
|
|
|
out:
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_wait_for_memory_target(libxl_ctx *ctx, uint32_t domid, int wait_secs)
|
|
{
|
|
int rc = 0;
|
|
uint64_t target_memkb = 0;
|
|
uint64_t current_memkb, prev_memkb;
|
|
libxl_dominfo info;
|
|
|
|
rc = libxl_get_memory_target(ctx, domid, &target_memkb);
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
libxl_dominfo_init(&info);
|
|
prev_memkb = UINT64_MAX;
|
|
|
|
do {
|
|
sleep(2);
|
|
|
|
libxl_dominfo_dispose(&info);
|
|
libxl_dominfo_init(&info);
|
|
rc = libxl_domain_info(ctx, &info, domid);
|
|
if (rc < 0)
|
|
goto out;
|
|
|
|
current_memkb = info.current_memkb + info.outstanding_memkb;
|
|
|
|
if (current_memkb > prev_memkb)
|
|
{
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
else if (current_memkb == prev_memkb)
|
|
wait_secs -= 2;
|
|
/* if current_memkb < prev_memkb loop for free as progress has
|
|
* been made */
|
|
|
|
prev_memkb = current_memkb;
|
|
} while (wait_secs > 0 && current_memkb > target_memkb);
|
|
|
|
if (current_memkb <= target_memkb)
|
|
rc = 0;
|
|
else
|
|
rc = ERROR_FAIL;
|
|
|
|
out:
|
|
libxl_dominfo_dispose(&info);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-basic-offset: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|