[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] libxl: carve out memory specific functions from libxl.c
commit c8cbddd8d62cee152c9d45e16995453551017802 Author: Juergen Gross <jgross@xxxxxxxx> AuthorDate: Wed Feb 8 17:09:30 2017 +0100 Commit: Wei Liu <wei.liu2@xxxxxxxxxx> CommitDate: Mon Feb 13 10:59:19 2017 +0000 libxl: carve out memory specific functions from libxl.c libxl.c has grown to an uncomfortable size. Carve out the memory related functions to libxl_mem.c. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> Reviewed-by: Wei Liu <wei.liu2@xxxxxxxxxx> Acked-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> --- tools/libxl/Makefile | 2 +- tools/libxl/libxl.c | 577 ---------------------------------------------- tools/libxl/libxl_mem.c | 601 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 602 insertions(+), 578 deletions(-) diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile index dd7aa41..4b05e34 100644 --- a/tools/libxl/Makefile +++ b/tools/libxl/Makefile @@ -137,7 +137,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \ libxl_qmp.o libxl_event.o libxl_fork.o \ libxl_dom_suspend.o libxl_dom_save.o libxl_usb.o \ libxl_vtpm.o libxl_nic.o libxl_disk.o libxl_console.o \ - libxl_cpupool.o libxl_sched.o \ + libxl_cpupool.o libxl_mem.o libxl_sched.o \ $(LIBXL_OBJS-y) LIBXL_OBJS += libxl_genid.o LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index bdf39602..9f2e6b3 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -15,7 +15,6 @@ #include "libxl_osdeps.h" #include "libxl_internal.h" -#include "libxl_arch.h" #define PAGE_TO_MEMKB(pages) ((pages) * 4) @@ -1952,582 +1951,6 @@ out: } /******************************************************************************/ - -/* - * 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, but the related - * Xenstore entry memory/static-max isn't modified! - */ -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__domain_userdata_lock *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 = 0; -out: - libxl_domain_config_dispose(&d_config); - if (lock) libxl__unlock_domain_userdata(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__domain_userdata_lock *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; - } - } - - 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_getinfolist(ctx->xch, domid, 1, &info); - if (r != 1 || info.domain != domid) { - 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_domain_userdata(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(libxl_ctx *ctx, - const libxl_domain_build_info *b_info_in, - uint64_t *need_memkb) -{ - GC_INIT(ctx); - libxl_domain_build_info b_info[1]; - int rc; - - 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; - - *need_memkb = b_info->target_memkb; - switch (b_info->type) { - case LIBXL_DOMAIN_TYPE_HVM: - *need_memkb += b_info->shadow_memkb + LIBXL_HVM_EXTRA_MEMORY; - if (libxl_defbool_val(b_info->device_model_stubdomain)) - *need_memkb += 32 * 1024; - break; - case LIBXL_DOMAIN_TYPE_PV: - *need_memkb += b_info->shadow_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: - GC_FREE; - libxl_domain_build_info_dispose(b_info); - 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(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; - 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; -} - int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo) { xc_physinfo_t xcphysinfo = { 0 }; diff --git a/tools/libxl/libxl_mem.c b/tools/libxl/libxl_mem.c new file mode 100644 index 0000000..f5d2530 --- /dev/null +++ b/tools/libxl/libxl_mem.c @@ -0,0 +1,601 @@ +/* + * 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, but the related + * Xenstore entry memory/static-max isn't modified! + */ +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__domain_userdata_lock *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 = 0; +out: + libxl_domain_config_dispose(&d_config); + if (lock) libxl__unlock_domain_userdata(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__domain_userdata_lock *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; + } + } + + 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_getinfolist(ctx->xch, domid, 1, &info); + if (r != 1 || info.domain != domid) { + 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_domain_userdata(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(libxl_ctx *ctx, + const libxl_domain_build_info *b_info_in, + uint64_t *need_memkb) +{ + GC_INIT(ctx); + libxl_domain_build_info b_info[1]; + int rc; + + 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; + + *need_memkb = b_info->target_memkb; + switch (b_info->type) { + case LIBXL_DOMAIN_TYPE_HVM: + *need_memkb += b_info->shadow_memkb + LIBXL_HVM_EXTRA_MEMORY; + if (libxl_defbool_val(b_info->device_model_stubdomain)) + *need_memkb += 32 * 1024; + break; + case LIBXL_DOMAIN_TYPE_PV: + *need_memkb += b_info->shadow_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: + GC_FREE; + libxl_domain_build_info_dispose(b_info); + 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(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; + 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: + */ -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |