[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 6/9] 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>
---
 tools/libxl/Makefile         |   2 +-
 tools/libxl/libxl.c          | 583 +----------------------------------------
 tools/libxl/libxl_internal.h |   7 +
 tools/libxl/libxl_mem.c      | 601 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 612 insertions(+), 581 deletions(-)
 create mode 100644 tools/libxl/libxl_mem.c

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 a0663eb..d040e12 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)
 
@@ -593,9 +592,9 @@ int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid,
     return 0;
 }
 
-static void xcinfo2xlinfo(libxl_ctx *ctx,
-                          const xc_domaininfo_t *xcinfo,
-                          libxl_dominfo *xlinfo)
+void xcinfo2xlinfo(libxl_ctx *ctx,
+                   const xc_domaininfo_t *xcinfo,
+                   libxl_dominfo *xlinfo)
 {
     size_t size;
 
@@ -1954,582 +1953,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, &current_target_memkb,
-                                           &current_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);
-    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 */
-static 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_internal.h b/tools/libxl/libxl_internal.h
index 5f46578..43456a9 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -4239,6 +4239,13 @@ uint64_t libxl__get_targetmem_fudge(libxl__gc *gc,
     return info->video_memkb + mem_target_fudge;
 }
 
+int libxl__get_memory_target(libxl__gc *gc, uint32_t domid, 
+                             uint64_t *out_target_memkb,
+                             uint64_t *out_max_memkb);
+void xcinfo2xlinfo(libxl_ctx *ctx,
+                   const xc_domaininfo_t *xcinfo,
+                   libxl_dominfo *xlinfo);
+
 /* Macros used to compare device identifier. Returns true if the two
  * devices have same identifier. */
 #define COMPARE_DEVID(a, b) ((a)->devid == (b)->devid)
diff --git a/tools/libxl/libxl_mem.c b/tools/libxl/libxl_mem.c
new file mode 100644
index 0000000..a4cc99a
--- /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, &current_target_memkb,
+                                           &current_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);
+    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:
+ */
-- 
2.10.2


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.