* [PATCH v2 00/12] libxl: split up libxl.c
@ 2017-02-09 9:30 Juergen Gross
2017-02-09 9:30 ` [PATCH v2 01/12] libxl: adjust copyright comment of libxl.c Juergen Gross
` (13 more replies)
0 siblings, 14 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
libxl.c has become rather large. Split it up into multiple files.
Changes are:
- modification of Copyright comment (patch 1)
- made two functions non-static: libxl__get_memory_target(),
xcinfo2xlinfo() (patch 2)
- white space cleanup of libxl.c (patch 3)
- moving functions into new or existing sources (patches 4-11):
just code movement, no functional changes besides needed Makefile
adjustments for new sources
- made one function static: libxl__device_frontend_path() (patch 12)
Changes in V2:
- address comments of Ian Jackson: add new patches 1-3, 12
Juergen Gross (12):
libxl: adjust copyright comment of libxl.c
libxl: make some functions global to prepare splitting up libxl.c
libxl: white space cleanup
libxl: carve out cpupool specific functions from libxl.c
libxl: carve out scheduler specific functions from libxl.c
libxl: carve out disk specific functions from libxl.c
libxl: carve out console specific functions from libxl.c
libxl: carve out memory specific functions from libxl.c
libxl: move device specific functions out of libxl.c
libxl: carve out tmem specific functions from libxl.c
libxl: carve out domain specific functions from libxl.c
libxl: make one function static
tools/libxl/Makefile | 4 +-
tools/libxl/libxl.c | 6254 +-----------------------------------------
tools/libxl/libxl_console.c | 862 ++++++
tools/libxl/libxl_cpupool.c | 443 +++
tools/libxl/libxl_device.c | 416 ++-
tools/libxl/libxl_disk.c | 1258 +++++++++
tools/libxl/libxl_domain.c | 1744 ++++++++++++
tools/libxl/libxl_internal.h | 8 +-
tools/libxl/libxl_mem.c | 601 ++++
tools/libxl/libxl_sched.c | 915 ++++++
tools/libxl/libxl_tmem.c | 167 ++
11 files changed, 6417 insertions(+), 6255 deletions(-)
create mode 100644 tools/libxl/libxl_console.c
create mode 100644 tools/libxl/libxl_cpupool.c
create mode 100644 tools/libxl/libxl_disk.c
create mode 100644 tools/libxl/libxl_domain.c
create mode 100644 tools/libxl/libxl_mem.c
create mode 100644 tools/libxl/libxl_sched.c
create mode 100644 tools/libxl/libxl_tmem.c
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 01/12] libxl: adjust copyright comment of libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 10:18 ` Wei Liu
2017-02-09 11:37 ` Ian Jackson
2017-02-09 9:30 ` [PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c Juergen Gross
` (12 subsequent siblings)
13 siblings, 2 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
The copyright of libxl.c is a little bit outdated.
Adjust it to reality.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/libxl.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index d400fa2..0641a8a 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1,7 +1,5 @@
/*
- * Copyright (C) 2009 Citrix Ltd.
- * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
- * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+ * 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
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
2017-02-09 9:30 ` [PATCH v2 01/12] libxl: adjust copyright comment of libxl.c Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 11:36 ` Ian Jackson
2017-02-09 9:30 ` [PATCH v2 03/12] libxl: white space cleanup Juergen Gross
` (11 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
Splitting up libxl.c will require two functions to be globally visible.
Add their prototypes to libxl_internal.h.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/libxl.c | 12 ++++++------
tools/libxl/libxl_internal.h | 7 +++++++
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 0641a8a..ea66149 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -594,9 +594,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;
@@ -4342,9 +4342,9 @@ out_no_transaction:
}
/* 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 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;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index a093bc6..b880801 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -4246,6 +4246,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)
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 03/12] libxl: white space cleanup
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
2017-02-09 9:30 ` [PATCH v2 01/12] libxl: adjust copyright comment of libxl.c Juergen Gross
2017-02-09 9:30 ` [PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 11:37 ` Ian Jackson
2017-02-09 9:30 ` [PATCH v2 04/12] libxl: carve out cpupool specific functions from libxl.c Juergen Gross
` (10 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
Before moving code to new sources clean up some white space issues in
libxl.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/libxl.c | 23 ++++++++++-------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index ea66149..6b87f48 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -72,7 +72,7 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version,
ctx->childproc_hooks = &libxl__childproc_default_hooks;
ctx->childproc_user = 0;
-
+
ctx->sigchld_selfpipe[0] = -1;
ctx->sigchld_selfpipe[1] = -1;
libxl__ev_fd_init(&ctx->sigchld_selfpipe_efd);
@@ -355,8 +355,6 @@ const char *libxl_defbool_to_string(libxl_defbool b)
}
/******************************************************************************/
-
-
int libxl__domain_rename(libxl__gc *gc, uint32_t domid,
const char *old_name, const char *new_name,
xs_transaction_t trans)
@@ -1242,7 +1240,7 @@ int libxl_evenable_domain_death(libxl_ctx *ctx, uint32_t domid,
GC_INIT(ctx);
libxl_evgen_domain_death *evg, *evg_search;
int rc;
-
+
CTX_LOCK;
evg = malloc(sizeof(*evg)); if (!evg) { rc = ERROR_NOMEM; goto out; }
@@ -1315,7 +1313,7 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
libxl_device_disk *disk = &ev->u.disk_eject.disk;
-
+
rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
if (rc) {
LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
@@ -1425,7 +1423,7 @@ void libxl_evdisable_disk_eject(libxl_ctx *ctx, libxl_evgen_disk_eject *evg) {
GC_INIT(ctx);
libxl__evdisable_disk_eject(gc, evg);
GC_FREE;
-}
+}
/* Callbacks for libxl_domain_destroy */
@@ -2515,7 +2513,6 @@ out:
return rc;
}
-
static int libxl__append_disk_list(libxl__gc *gc,
uint32_t domid,
libxl_device_disk **disks,
@@ -2862,7 +2859,7 @@ static char * libxl__alloc_vdev(libxl__gc *gc, void *get_vdev_user,
/* Callbacks */
-char *libxl__device_disk_find_local_path(libxl__gc *gc,
+char *libxl__device_disk_find_local_path(libxl__gc *gc,
libxl_domid guest_domid,
const libxl_device_disk *disk,
bool qdisk_direct)
@@ -2884,7 +2881,7 @@ char *libxl__device_disk_find_local_path(libxl__gc *gc,
path = libxl__strdup(gc, disk->pdev_path);
LOG(DEBUG, "Directly accessing local RAW disk %s", path);
goto out;
- }
+ }
/*
* If we're being called for a qemu path, we can pass the target
@@ -2894,9 +2891,9 @@ char *libxl__device_disk_find_local_path(libxl__gc *gc,
path = libxl__strdup(gc, disk->pdev_path);
LOG(DEBUG, "Directly accessing local QDISK target %s", path);
goto out;
- }
+ }
- /*
+ /*
* If the format isn't raw and / or we're using a script, then see
* if the script has written a path to the "cooked" node
*/
@@ -2965,7 +2962,7 @@ void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
if (in_disk->script != NULL)
disk->script = libxl__strdup(gc, in_disk->script);
disk->vdev = NULL;
-
+
rc = libxl__device_disk_setdefault(gc, disk, LIBXL_TOOLSTACK_DOMID);
if (rc) goto out;
@@ -3042,7 +3039,7 @@ void libxl__device_disk_local_initiate_detach(libxl__egc *egc,
rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID,
disk, device);
if (rc != 0) goto out;
-
+
aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
aodev->dev = device;
aodev->callback = local_device_detach_cb;
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 04/12] libxl: carve out cpupool specific functions from libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (2 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 03/12] libxl: white space cleanup Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 9:30 ` [PATCH v2 05/12] libxl: carve out scheduler " Juergen Gross
` (9 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
libxl.c has grown to an uncomfortable size. Carve out the cpupool
related functions to libxl_cpupool.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/Makefile | 1 +
tools/libxl/libxl.c | 418 -----------------------------------------
tools/libxl/libxl_cpupool.c | 443 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 444 insertions(+), 418 deletions(-)
create mode 100644 tools/libxl/libxl_cpupool.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 91e2f97..0125871 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -137,6 +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_cpupool.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 6b87f48..d0080ca 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -683,100 +683,6 @@ int libxl_domain_info(libxl_ctx *ctx, libxl_dominfo *info_r,
return 0;
}
-/* Returns:
- * 0 - success
- * ERROR_FAIL + errno == ENOENT - no entry found
- * ERROR_$FOO + errno != ENOENT - other failure
- */
-static int cpupool_info(libxl__gc *gc,
- libxl_cpupoolinfo *info,
- uint32_t poolid,
- bool exact /* exactly poolid or >= poolid */)
-{
- xc_cpupoolinfo_t *xcinfo;
- int rc = ERROR_FAIL;
-
- xcinfo = xc_cpupool_getinfo(CTX->xch, poolid);
- if (xcinfo == NULL)
- {
- if (exact || errno != ENOENT)
- LOGE(ERROR, "failed to get info for cpupool%d", poolid);
- return ERROR_FAIL;
- }
-
- if (exact && xcinfo->cpupool_id != poolid)
- {
- LOG(ERROR, "got info for cpupool%d, wanted cpupool%d\n",
- xcinfo->cpupool_id, poolid);
- goto out;
- }
-
- info->poolid = xcinfo->cpupool_id;
- info->pool_name = libxl_cpupoolid_to_name(CTX, info->poolid);
- if (!info->pool_name) {
- rc = ERROR_FAIL;
- goto out;
- }
- info->sched = xcinfo->sched_id;
- info->n_dom = xcinfo->n_dom;
- rc = libxl_cpu_bitmap_alloc(CTX, &info->cpumap, 0);
- if (rc)
- goto out;
-
- memcpy(info->cpumap.map, xcinfo->cpumap, info->cpumap.size);
-
- rc = 0;
-out:
- xc_cpupool_infofree(CTX->xch, xcinfo);
- return rc;
-}
-
-int libxl_cpupool_info(libxl_ctx *ctx,
- libxl_cpupoolinfo *info, uint32_t poolid)
-{
- GC_INIT(ctx);
- int rc = cpupool_info(gc, info, poolid, true);
- GC_FREE;
- return rc;
-}
-
-libxl_cpupoolinfo * libxl_list_cpupool(libxl_ctx *ctx, int *nb_pool_out)
-{
- GC_INIT(ctx);
- libxl_cpupoolinfo info, *ptr;
-
- int i;
- uint32_t poolid;
-
- ptr = NULL;
-
- poolid = 0;
- for (i = 0;; i++) {
- libxl_cpupoolinfo_init(&info);
- if (cpupool_info(gc, &info, poolid, false)) {
- libxl_cpupoolinfo_dispose(&info);
- if (errno != ENOENT) goto out;
- break;
- }
-
- ptr = libxl__realloc(NOGC, ptr, (i+1) * sizeof(libxl_cpupoolinfo));
- ptr[i] = info;
- poolid = info.poolid + 1;
- /* Don't dispose of info because it will be returned to caller */
- }
-
- *nb_pool_out = i;
-
- GC_FREE;
- return ptr;
-
-out:
- libxl_cpupoolinfo_list_free(ptr, i);
- *nb_pool_out = 0;
- GC_FREE;
- return NULL;
-}
-
/* this API call only list VM running on this host. A VM can
* be an aggregate of multiple domains. */
libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm_out)
@@ -6253,330 +6159,6 @@ out:
return rc;
}
-int libxl_get_freecpus(libxl_ctx *ctx, libxl_bitmap *cpumap)
-{
- int ncpus;
-
- ncpus = libxl_get_max_cpus(ctx);
- if (ncpus < 0)
- return ncpus;
-
- cpumap->map = xc_cpupool_freeinfo(ctx->xch);
- if (cpumap->map == NULL)
- return ERROR_FAIL;
-
- cpumap->size = (ncpus + 7) / 8;
-
- return 0;
-}
-
-int libxl_cpupool_create(libxl_ctx *ctx, const char *name,
- libxl_scheduler sched,
- libxl_bitmap cpumap, libxl_uuid *uuid,
- uint32_t *poolid)
-{
- GC_INIT(ctx);
- int rc;
- int i;
- xs_transaction_t t;
- char *uuid_string;
-
- uuid_string = libxl__uuid2string(gc, *uuid);
- if (!uuid_string) {
- GC_FREE;
- return ERROR_NOMEM;
- }
-
- rc = xc_cpupool_create(ctx->xch, poolid, sched);
- if (rc) {
- LOGEV(ERROR, rc, "Could not create cpupool");
- GC_FREE;
- return ERROR_FAIL;
- }
-
- libxl_for_each_bit(i, cpumap)
- if (libxl_bitmap_test(&cpumap, i)) {
- rc = xc_cpupool_addcpu(ctx->xch, *poolid, i);
- if (rc) {
- LOGEV(ERROR, rc, "Error moving cpu to cpupool");
- libxl_cpupool_destroy(ctx, *poolid);
- GC_FREE;
- return ERROR_FAIL;
- }
- }
-
- for (;;) {
- t = xs_transaction_start(ctx->xsh);
-
- xs_mkdir(ctx->xsh, t, GCSPRINTF("/local/pool/%d", *poolid));
- libxl__xs_printf(gc, t,
- GCSPRINTF("/local/pool/%d/uuid", *poolid),
- "%s", uuid_string);
- libxl__xs_printf(gc, t,
- GCSPRINTF("/local/pool/%d/name", *poolid),
- "%s", name);
-
- if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) {
- GC_FREE;
- return 0;
- }
- }
-}
-
-int libxl_cpupool_destroy(libxl_ctx *ctx, uint32_t poolid)
-{
- GC_INIT(ctx);
- int rc, i;
- xc_cpupoolinfo_t *info;
- xs_transaction_t t;
- libxl_bitmap cpumap;
-
- info = xc_cpupool_getinfo(ctx->xch, poolid);
- if (info == NULL) {
- GC_FREE;
- return ERROR_NOMEM;
- }
-
- rc = ERROR_INVAL;
- if ((info->cpupool_id != poolid) || (info->n_dom))
- goto out;
-
- rc = libxl_cpu_bitmap_alloc(ctx, &cpumap, 0);
- if (rc)
- goto out;
-
- memcpy(cpumap.map, info->cpumap, cpumap.size);
- libxl_for_each_bit(i, cpumap)
- if (libxl_bitmap_test(&cpumap, i)) {
- rc = xc_cpupool_removecpu(ctx->xch, poolid, i);
- if (rc) {
- LOGEV(ERROR, rc, "Error removing cpu from cpupool");
- rc = ERROR_FAIL;
- goto out1;
- }
- }
-
- rc = xc_cpupool_destroy(ctx->xch, poolid);
- if (rc) {
- LOGEV(ERROR, rc, "Could not destroy cpupool");
- rc = ERROR_FAIL;
- goto out1;
- }
-
- for (;;) {
- t = xs_transaction_start(ctx->xsh);
-
- xs_rm(ctx->xsh, XBT_NULL, GCSPRINTF("/local/pool/%d", poolid));
-
- if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN))
- break;
- }
-
- rc = 0;
-
-out1:
- libxl_bitmap_dispose(&cpumap);
-out:
- xc_cpupool_infofree(ctx->xch, info);
- GC_FREE;
-
- return rc;
-}
-
-int libxl_cpupool_rename(libxl_ctx *ctx, const char *name, uint32_t poolid)
-{
- GC_INIT(ctx);
- xs_transaction_t t;
- xc_cpupoolinfo_t *info;
- int rc;
-
- info = xc_cpupool_getinfo(ctx->xch, poolid);
- if (info == NULL) {
- GC_FREE;
- return ERROR_NOMEM;
- }
-
- rc = ERROR_INVAL;
- if (info->cpupool_id != poolid)
- goto out;
-
- rc = 0;
-
- for (;;) {
- t = xs_transaction_start(ctx->xsh);
-
- libxl__xs_printf(gc, t,
- GCSPRINTF("/local/pool/%d/name", poolid),
- "%s", name);
-
- if (xs_transaction_end(ctx->xsh, t, 0))
- break;
-
- if (errno == EAGAIN)
- continue;
-
- rc = ERROR_FAIL;
- break;
- }
-
-out:
- xc_cpupool_infofree(ctx->xch, info);
- GC_FREE;
-
- return rc;
-}
-
-int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu)
-{
- GC_INIT(ctx);
- int rc = 0;
-
- rc = xc_cpupool_addcpu(ctx->xch, poolid, cpu);
- if (rc) {
- LOGE(ERROR, "Error moving cpu %d to cpupool", cpu);
- rc = ERROR_FAIL;
- }
-
- GC_FREE;
- return rc;
-}
-
-int libxl_cpupool_cpuadd_cpumap(libxl_ctx *ctx, uint32_t poolid,
- const libxl_bitmap *cpumap)
-{
- int c, ncpus = 0, rc = 0;
-
- libxl_for_each_set_bit(c, *cpumap) {
- if (!libxl_cpupool_cpuadd(ctx, poolid, c))
- ncpus++;
- }
-
- if (ncpus != libxl_bitmap_count_set(cpumap))
- rc = ERROR_FAIL;
-
- return rc;
-}
-
-int libxl_cpupool_cpuadd_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus)
-{
- int rc = 0;
- int cpu, nr;
- libxl_bitmap freemap;
- libxl_cputopology *topology;
-
- if (libxl_get_freecpus(ctx, &freemap)) {
- return ERROR_FAIL;
- }
-
- topology = libxl_get_cpu_topology(ctx, &nr);
- if (!topology) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- *cpus = 0;
- for (cpu = 0; cpu < nr; cpu++) {
- if (libxl_bitmap_test(&freemap, cpu) && (topology[cpu].node == node) &&
- !libxl_cpupool_cpuadd(ctx, poolid, cpu)) {
- (*cpus)++;
- }
- libxl_cputopology_dispose(&topology[cpu]);
- }
-
- free(topology);
-out:
- libxl_bitmap_dispose(&freemap);
- return rc;
-}
-
-int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu)
-{
- GC_INIT(ctx);
- int rc = 0;
-
- rc = xc_cpupool_removecpu(ctx->xch, poolid, cpu);
- if (rc) {
- LOGE(ERROR, "Error removing cpu %d from cpupool", cpu);
- rc = ERROR_FAIL;
- }
-
- GC_FREE;
- return rc;
-}
-
-int libxl_cpupool_cpuremove_cpumap(libxl_ctx *ctx, uint32_t poolid,
- const libxl_bitmap *cpumap)
-{
- int c, ncpus = 0, rc = 0;
-
- libxl_for_each_set_bit(c, *cpumap) {
- if (!libxl_cpupool_cpuremove(ctx, poolid, c))
- ncpus++;
- }
-
- if (ncpus != libxl_bitmap_count_set(cpumap))
- rc = ERROR_FAIL;
-
- return rc;
-}
-
-int libxl_cpupool_cpuremove_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus)
-{
- int ret = 0;
- int n_pools;
- int p;
- int cpu, nr_cpus;
- libxl_cputopology *topology;
- libxl_cpupoolinfo *poolinfo;
-
- poolinfo = libxl_list_cpupool(ctx, &n_pools);
- if (!poolinfo) {
- return ERROR_NOMEM;
- }
-
- topology = libxl_get_cpu_topology(ctx, &nr_cpus);
- if (!topology) {
- ret = ERROR_FAIL;
- goto out;
- }
-
- *cpus = 0;
- for (p = 0; p < n_pools; p++) {
- if (poolinfo[p].poolid == poolid) {
- for (cpu = 0; cpu < nr_cpus; cpu++) {
- if ((topology[cpu].node == node) &&
- libxl_bitmap_test(&poolinfo[p].cpumap, cpu) &&
- !libxl_cpupool_cpuremove(ctx, poolid, cpu)) {
- (*cpus)++;
- }
- }
- }
- }
-
- libxl_cputopology_list_free(topology, nr_cpus);
-
-out:
- libxl_cpupoolinfo_list_free(poolinfo, n_pools);
-
- return ret;
-}
-
-int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid)
-{
- GC_INIT(ctx);
- int rc;
-
- rc = xc_cpupool_movedomain(ctx->xch, poolid, domid);
- if (rc) {
- LOGEVD(ERROR, rc, domid, "Error moving domain to cpupool");
- GC_FREE;
- return ERROR_FAIL;
- }
-
- GC_FREE;
- return 0;
-}
-
static int fd_set_flags(libxl_ctx *ctx, int fd,
int fcntlgetop, int fcntlsetop, const char *fl,
int flagmask, int set_p)
diff --git a/tools/libxl/libxl_cpupool.c b/tools/libxl/libxl_cpupool.c
new file mode 100644
index 0000000..f3d22b1
--- /dev/null
+++ b/tools/libxl/libxl_cpupool.c
@@ -0,0 +1,443 @@
+/*
+ * 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"
+
+/* Returns:
+ * 0 - success
+ * ERROR_FAIL + errno == ENOENT - no entry found
+ * ERROR_$FOO + errno != ENOENT - other failure
+ */
+static int cpupool_info(libxl__gc *gc,
+ libxl_cpupoolinfo *info,
+ uint32_t poolid,
+ bool exact /* exactly poolid or >= poolid */)
+{
+ xc_cpupoolinfo_t *xcinfo;
+ int rc = ERROR_FAIL;
+
+ xcinfo = xc_cpupool_getinfo(CTX->xch, poolid);
+ if (xcinfo == NULL)
+ {
+ if (exact || errno != ENOENT)
+ LOGE(ERROR, "failed to get info for cpupool%d", poolid);
+ return ERROR_FAIL;
+ }
+
+ if (exact && xcinfo->cpupool_id != poolid)
+ {
+ LOG(ERROR, "got info for cpupool%d, wanted cpupool%d\n",
+ xcinfo->cpupool_id, poolid);
+ goto out;
+ }
+
+ info->poolid = xcinfo->cpupool_id;
+ info->pool_name = libxl_cpupoolid_to_name(CTX, info->poolid);
+ if (!info->pool_name) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ info->sched = xcinfo->sched_id;
+ info->n_dom = xcinfo->n_dom;
+ rc = libxl_cpu_bitmap_alloc(CTX, &info->cpumap, 0);
+ if (rc)
+ goto out;
+
+ memcpy(info->cpumap.map, xcinfo->cpumap, info->cpumap.size);
+
+ rc = 0;
+out:
+ xc_cpupool_infofree(CTX->xch, xcinfo);
+ return rc;
+}
+
+int libxl_cpupool_info(libxl_ctx *ctx,
+ libxl_cpupoolinfo *info, uint32_t poolid)
+{
+ GC_INIT(ctx);
+ int rc = cpupool_info(gc, info, poolid, true);
+ GC_FREE;
+ return rc;
+}
+
+libxl_cpupoolinfo * libxl_list_cpupool(libxl_ctx *ctx, int *nb_pool_out)
+{
+ GC_INIT(ctx);
+ libxl_cpupoolinfo info, *ptr;
+
+ int i;
+ uint32_t poolid;
+
+ ptr = NULL;
+
+ poolid = 0;
+ for (i = 0;; i++) {
+ libxl_cpupoolinfo_init(&info);
+ if (cpupool_info(gc, &info, poolid, false)) {
+ libxl_cpupoolinfo_dispose(&info);
+ if (errno != ENOENT) goto out;
+ break;
+ }
+
+ ptr = libxl__realloc(NOGC, ptr, (i+1) * sizeof(libxl_cpupoolinfo));
+ ptr[i] = info;
+ poolid = info.poolid + 1;
+ /* Don't dispose of info because it will be returned to caller */
+ }
+
+ *nb_pool_out = i;
+
+ GC_FREE;
+ return ptr;
+
+out:
+ libxl_cpupoolinfo_list_free(ptr, i);
+ *nb_pool_out = 0;
+ GC_FREE;
+ return NULL;
+}
+
+int libxl_get_freecpus(libxl_ctx *ctx, libxl_bitmap *cpumap)
+{
+ int ncpus;
+
+ ncpus = libxl_get_max_cpus(ctx);
+ if (ncpus < 0)
+ return ncpus;
+
+ cpumap->map = xc_cpupool_freeinfo(ctx->xch);
+ if (cpumap->map == NULL)
+ return ERROR_FAIL;
+
+ cpumap->size = (ncpus + 7) / 8;
+
+ return 0;
+}
+
+int libxl_cpupool_create(libxl_ctx *ctx, const char *name,
+ libxl_scheduler sched,
+ libxl_bitmap cpumap, libxl_uuid *uuid,
+ uint32_t *poolid)
+{
+ GC_INIT(ctx);
+ int rc;
+ int i;
+ xs_transaction_t t;
+ char *uuid_string;
+
+ uuid_string = libxl__uuid2string(gc, *uuid);
+ if (!uuid_string) {
+ GC_FREE;
+ return ERROR_NOMEM;
+ }
+
+ rc = xc_cpupool_create(ctx->xch, poolid, sched);
+ if (rc) {
+ LOGEV(ERROR, rc, "Could not create cpupool");
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+
+ libxl_for_each_bit(i, cpumap)
+ if (libxl_bitmap_test(&cpumap, i)) {
+ rc = xc_cpupool_addcpu(ctx->xch, *poolid, i);
+ if (rc) {
+ LOGEV(ERROR, rc, "Error moving cpu to cpupool");
+ libxl_cpupool_destroy(ctx, *poolid);
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+ }
+
+ for (;;) {
+ t = xs_transaction_start(ctx->xsh);
+
+ xs_mkdir(ctx->xsh, t, GCSPRINTF("/local/pool/%d", *poolid));
+ libxl__xs_printf(gc, t,
+ GCSPRINTF("/local/pool/%d/uuid", *poolid),
+ "%s", uuid_string);
+ libxl__xs_printf(gc, t,
+ GCSPRINTF("/local/pool/%d/name", *poolid),
+ "%s", name);
+
+ if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) {
+ GC_FREE;
+ return 0;
+ }
+ }
+}
+
+int libxl_cpupool_destroy(libxl_ctx *ctx, uint32_t poolid)
+{
+ GC_INIT(ctx);
+ int rc, i;
+ xc_cpupoolinfo_t *info;
+ xs_transaction_t t;
+ libxl_bitmap cpumap;
+
+ info = xc_cpupool_getinfo(ctx->xch, poolid);
+ if (info == NULL) {
+ GC_FREE;
+ return ERROR_NOMEM;
+ }
+
+ rc = ERROR_INVAL;
+ if ((info->cpupool_id != poolid) || (info->n_dom))
+ goto out;
+
+ rc = libxl_cpu_bitmap_alloc(ctx, &cpumap, 0);
+ if (rc)
+ goto out;
+
+ memcpy(cpumap.map, info->cpumap, cpumap.size);
+ libxl_for_each_bit(i, cpumap)
+ if (libxl_bitmap_test(&cpumap, i)) {
+ rc = xc_cpupool_removecpu(ctx->xch, poolid, i);
+ if (rc) {
+ LOGEV(ERROR, rc, "Error removing cpu from cpupool");
+ rc = ERROR_FAIL;
+ goto out1;
+ }
+ }
+
+ rc = xc_cpupool_destroy(ctx->xch, poolid);
+ if (rc) {
+ LOGEV(ERROR, rc, "Could not destroy cpupool");
+ rc = ERROR_FAIL;
+ goto out1;
+ }
+
+ for (;;) {
+ t = xs_transaction_start(ctx->xsh);
+
+ xs_rm(ctx->xsh, XBT_NULL, GCSPRINTF("/local/pool/%d", poolid));
+
+ if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN))
+ break;
+ }
+
+ rc = 0;
+
+out1:
+ libxl_bitmap_dispose(&cpumap);
+out:
+ xc_cpupool_infofree(ctx->xch, info);
+ GC_FREE;
+
+ return rc;
+}
+
+int libxl_cpupool_rename(libxl_ctx *ctx, const char *name, uint32_t poolid)
+{
+ GC_INIT(ctx);
+ xs_transaction_t t;
+ xc_cpupoolinfo_t *info;
+ int rc;
+
+ info = xc_cpupool_getinfo(ctx->xch, poolid);
+ if (info == NULL) {
+ GC_FREE;
+ return ERROR_NOMEM;
+ }
+
+ rc = ERROR_INVAL;
+ if (info->cpupool_id != poolid)
+ goto out;
+
+ rc = 0;
+
+ for (;;) {
+ t = xs_transaction_start(ctx->xsh);
+
+ libxl__xs_printf(gc, t,
+ GCSPRINTF("/local/pool/%d/name", poolid),
+ "%s", name);
+
+ if (xs_transaction_end(ctx->xsh, t, 0))
+ break;
+
+ if (errno == EAGAIN)
+ continue;
+
+ rc = ERROR_FAIL;
+ break;
+ }
+
+out:
+ xc_cpupool_infofree(ctx->xch, info);
+ GC_FREE;
+
+ return rc;
+}
+
+int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu)
+{
+ GC_INIT(ctx);
+ int rc = 0;
+
+ rc = xc_cpupool_addcpu(ctx->xch, poolid, cpu);
+ if (rc) {
+ LOGE(ERROR, "Error moving cpu %d to cpupool", cpu);
+ rc = ERROR_FAIL;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+int libxl_cpupool_cpuadd_cpumap(libxl_ctx *ctx, uint32_t poolid,
+ const libxl_bitmap *cpumap)
+{
+ int c, ncpus = 0, rc = 0;
+
+ libxl_for_each_set_bit(c, *cpumap) {
+ if (!libxl_cpupool_cpuadd(ctx, poolid, c))
+ ncpus++;
+ }
+
+ if (ncpus != libxl_bitmap_count_set(cpumap))
+ rc = ERROR_FAIL;
+
+ return rc;
+}
+
+int libxl_cpupool_cpuadd_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus)
+{
+ int rc = 0;
+ int cpu, nr;
+ libxl_bitmap freemap;
+ libxl_cputopology *topology;
+
+ if (libxl_get_freecpus(ctx, &freemap)) {
+ return ERROR_FAIL;
+ }
+
+ topology = libxl_get_cpu_topology(ctx, &nr);
+ if (!topology) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ *cpus = 0;
+ for (cpu = 0; cpu < nr; cpu++) {
+ if (libxl_bitmap_test(&freemap, cpu) && (topology[cpu].node == node) &&
+ !libxl_cpupool_cpuadd(ctx, poolid, cpu)) {
+ (*cpus)++;
+ }
+ libxl_cputopology_dispose(&topology[cpu]);
+ }
+
+ free(topology);
+out:
+ libxl_bitmap_dispose(&freemap);
+ return rc;
+}
+
+int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu)
+{
+ GC_INIT(ctx);
+ int rc = 0;
+
+ rc = xc_cpupool_removecpu(ctx->xch, poolid, cpu);
+ if (rc) {
+ LOGE(ERROR, "Error removing cpu %d from cpupool", cpu);
+ rc = ERROR_FAIL;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+int libxl_cpupool_cpuremove_cpumap(libxl_ctx *ctx, uint32_t poolid,
+ const libxl_bitmap *cpumap)
+{
+ int c, ncpus = 0, rc = 0;
+
+ libxl_for_each_set_bit(c, *cpumap) {
+ if (!libxl_cpupool_cpuremove(ctx, poolid, c))
+ ncpus++;
+ }
+
+ if (ncpus != libxl_bitmap_count_set(cpumap))
+ rc = ERROR_FAIL;
+
+ return rc;
+}
+
+int libxl_cpupool_cpuremove_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus)
+{
+ int ret = 0;
+ int n_pools;
+ int p;
+ int cpu, nr_cpus;
+ libxl_cputopology *topology;
+ libxl_cpupoolinfo *poolinfo;
+
+ poolinfo = libxl_list_cpupool(ctx, &n_pools);
+ if (!poolinfo) {
+ return ERROR_NOMEM;
+ }
+
+ topology = libxl_get_cpu_topology(ctx, &nr_cpus);
+ if (!topology) {
+ ret = ERROR_FAIL;
+ goto out;
+ }
+
+ *cpus = 0;
+ for (p = 0; p < n_pools; p++) {
+ if (poolinfo[p].poolid == poolid) {
+ for (cpu = 0; cpu < nr_cpus; cpu++) {
+ if ((topology[cpu].node == node) &&
+ libxl_bitmap_test(&poolinfo[p].cpumap, cpu) &&
+ !libxl_cpupool_cpuremove(ctx, poolid, cpu)) {
+ (*cpus)++;
+ }
+ }
+ }
+ }
+
+ libxl_cputopology_list_free(topology, nr_cpus);
+
+out:
+ libxl_cpupoolinfo_list_free(poolinfo, n_pools);
+
+ return ret;
+}
+
+int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid)
+{
+ GC_INIT(ctx);
+ int rc;
+
+ rc = xc_cpupool_movedomain(ctx->xch, poolid, domid);
+ if (rc) {
+ LOGEVD(ERROR, rc, domid, "Error moving domain to cpupool");
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+
+ GC_FREE;
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 05/12] libxl: carve out scheduler specific functions from libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (3 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 04/12] libxl: carve out cpupool specific functions from libxl.c Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 9:30 ` [PATCH v2 06/12] libxl: carve out disk " Juergen Gross
` (8 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
libxl.c has grown to an uncomfortable size. Carve out the scheduler
related functions to libxl_sched.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/Makefile | 2 +-
tools/libxl/libxl.c | 891 --------------------------------------------
tools/libxl/libxl_sched.c | 915 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 916 insertions(+), 892 deletions(-)
create mode 100644 tools/libxl/libxl_sched.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 0125871..7514cc2 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_cpupool.o \
+ libxl_cpupool.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 d0080ca..ae6c7d4 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -4830,146 +4830,6 @@ err:
return NULL;
}
-static int libxl__set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid,
- uint32_t vcpuid,
- const libxl_bitmap *cpumap_hard,
- const libxl_bitmap *cpumap_soft,
- unsigned flags)
-{
- GC_INIT(ctx);
- libxl_bitmap hard, soft;
- int rc;
-
- libxl_bitmap_init(&hard);
- libxl_bitmap_init(&soft);
-
- if (!cpumap_hard && !cpumap_soft && !flags) {
- rc = ERROR_INVAL;
- goto out;
- }
-
- /*
- * Xen wants writable hard and/or soft cpumaps, to put back in them
- * the effective hard and/or soft affinity that will be used.
- */
- if (cpumap_hard) {
- rc = libxl_cpu_bitmap_alloc(ctx, &hard, 0);
- if (rc)
- goto out;
-
- libxl__bitmap_copy_best_effort(gc, &hard, cpumap_hard);
- flags |= XEN_VCPUAFFINITY_HARD;
- }
- if (cpumap_soft) {
- rc = libxl_cpu_bitmap_alloc(ctx, &soft, 0);
- if (rc)
- goto out;
-
- libxl__bitmap_copy_best_effort(gc, &soft, cpumap_soft);
- flags |= XEN_VCPUAFFINITY_SOFT;
- }
-
- if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid,
- cpumap_hard ? hard.map : NULL,
- cpumap_soft ? soft.map : NULL,
- flags)) {
- LOGED(ERROR, domid, "Setting vcpu affinity");
- rc = ERROR_FAIL;
- goto out;
- }
-
- /*
- * Let's check the results. Hard affinity will never be empty, but it
- * is possible that Xen will use something different from what we asked
- * for various reasons. If that's the case, report it.
- */
- if (cpumap_hard &&
- !libxl_bitmap_equal(cpumap_hard, &hard, 0))
- LOGD(DEBUG, domid, "New hard affinity for vcpu %d has unreachable cpus", vcpuid);
- /*
- * Soft affinity can both be different from what asked and empty. Check
- * for (and report) both.
- */
- if (cpumap_soft) {
- if (!libxl_bitmap_equal(cpumap_soft, &soft, 0))
- LOGD(DEBUG, domid, "New soft affinity for vcpu %d has unreachable cpus",
- vcpuid);
- if (libxl_bitmap_is_empty(&soft))
- LOGD(WARN, domid, "All cpus in soft affinity of vcpu %d are unreachable."
- " Only hard affinity will be considered for scheduling",
- vcpuid);
- }
-
- rc = 0;
- out:
- libxl_bitmap_dispose(&hard);
- libxl_bitmap_dispose(&soft);
- GC_FREE;
- return rc;
-}
-
-int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
- const libxl_bitmap *cpumap_hard,
- const libxl_bitmap *cpumap_soft)
-{
- return libxl__set_vcpuaffinity(ctx, domid, vcpuid, cpumap_hard,
- cpumap_soft, 0);
-}
-
-int libxl_set_vcpuaffinity_force(libxl_ctx *ctx, uint32_t domid,
- uint32_t vcpuid,
- const libxl_bitmap *cpumap_hard,
- const libxl_bitmap *cpumap_soft)
-{
- return libxl__set_vcpuaffinity(ctx, domid, vcpuid, cpumap_hard,
- cpumap_soft, XEN_VCPUAFFINITY_FORCE);
-}
-
-int libxl_set_vcpuaffinity_all(libxl_ctx *ctx, uint32_t domid,
- unsigned int max_vcpus,
- const libxl_bitmap *cpumap_hard,
- const libxl_bitmap *cpumap_soft)
-{
- GC_INIT(ctx);
- int i, rc = 0;
-
- for (i = 0; i < max_vcpus; i++) {
- if (libxl_set_vcpuaffinity(ctx, domid, i, cpumap_hard, cpumap_soft)) {
- LOGD(WARN, domid, "Failed to set affinity for %d", i);
- rc = ERROR_FAIL;
- }
- }
-
- GC_FREE;
- return rc;
-}
-
-int libxl_domain_set_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
- libxl_bitmap *nodemap)
-{
- GC_INIT(ctx);
- if (xc_domain_node_setaffinity(ctx->xch, domid, nodemap->map)) {
- LOGED(ERROR, domid, "Setting node affinity");
- GC_FREE;
- return ERROR_FAIL;
- }
- GC_FREE;
- return 0;
-}
-
-int libxl_domain_get_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
- libxl_bitmap *nodemap)
-{
- GC_INIT(ctx);
- if (xc_domain_node_getaffinity(ctx->xch, domid, nodemap->map)) {
- LOGED(ERROR, domid, "Getting node affinity");
- GC_FREE;
- return ERROR_FAIL;
- }
- GC_FREE;
- return 0;
-}
-
static int libxl__set_vcpuonline_xenstore(libxl__gc *gc, uint32_t domid,
libxl_bitmap *cpumap,
const libxl_dominfo *info)
@@ -5085,757 +4945,6 @@ out:
return rc;
}
-int libxl_get_scheduler(libxl_ctx *ctx)
-{
- int r, sched;
-
- GC_INIT(ctx);
- r = xc_sched_id(ctx->xch, &sched);
- if (r != 0) {
- LOGE(ERROR, "getting current scheduler id");
- sched = ERROR_FAIL;
- }
- GC_FREE;
- return sched;
-}
-
-static int sched_arinc653_domain_set(libxl__gc *gc, uint32_t domid,
- const libxl_domain_sched_params *scinfo)
-{
- /* Currently, the ARINC 653 scheduler does not take any domain-specific
- configuration, so we simply return success. */
- return 0;
-}
-
-static int sched_credit_domain_get(libxl__gc *gc, uint32_t domid,
- libxl_domain_sched_params *scinfo)
-{
- struct xen_domctl_sched_credit sdom;
- int rc;
-
- rc = xc_sched_credit_domain_get(CTX->xch, domid, &sdom);
- if (rc != 0) {
- LOGED(ERROR, domid, "Getting domain sched credit");
- return ERROR_FAIL;
- }
-
- libxl_domain_sched_params_init(scinfo);
- scinfo->sched = LIBXL_SCHEDULER_CREDIT;
- scinfo->weight = sdom.weight;
- scinfo->cap = sdom.cap;
-
- return 0;
-}
-
-static int sched_credit_domain_set(libxl__gc *gc, uint32_t domid,
- const libxl_domain_sched_params *scinfo)
-{
- struct xen_domctl_sched_credit sdom;
- xc_domaininfo_t domaininfo;
- int rc;
-
- rc = xc_domain_getinfolist(CTX->xch, domid, 1, &domaininfo);
- if (rc < 0) {
- LOGED(ERROR, domid, "Getting domain info list");
- return ERROR_FAIL;
- }
- if (rc != 1 || domaininfo.domain != domid)
- return ERROR_INVAL;
-
- rc = xc_sched_credit_domain_get(CTX->xch, domid, &sdom);
- if (rc != 0) {
- LOGED(ERROR, domid, "Getting domain sched credit");
- return ERROR_FAIL;
- }
-
- if (scinfo->weight != LIBXL_DOMAIN_SCHED_PARAM_WEIGHT_DEFAULT) {
- if (scinfo->weight < 1 || scinfo->weight > 65535) {
- LOGD(ERROR, domid, "Cpu weight out of range, "
- "valid values are within range from 1 to 65535");
- return ERROR_INVAL;
- }
- sdom.weight = scinfo->weight;
- }
-
- if (scinfo->cap != LIBXL_DOMAIN_SCHED_PARAM_CAP_DEFAULT) {
- if (scinfo->cap < 0
- || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
- LOGD(ERROR, domid, "Cpu cap out of range, "
- "valid range is from 0 to %d for specified number of vcpus",
- ((domaininfo.max_vcpu_id + 1) * 100));
- return ERROR_INVAL;
- }
- sdom.cap = scinfo->cap;
- }
-
- rc = xc_sched_credit_domain_set(CTX->xch, domid, &sdom);
- if ( rc < 0 ) {
- LOGED(ERROR, domid, "Setting domain sched credit");
- return ERROR_FAIL;
- }
-
- return 0;
-}
-
-static int sched_ratelimit_check(libxl__gc *gc, int ratelimit)
-{
- if (ratelimit != 0 &&
- (ratelimit < XEN_SYSCTL_SCHED_RATELIMIT_MIN ||
- ratelimit > XEN_SYSCTL_SCHED_RATELIMIT_MAX)) {
- LOG(ERROR, "Ratelimit out of range, valid range is from %d to %d",
- XEN_SYSCTL_SCHED_RATELIMIT_MIN, XEN_SYSCTL_SCHED_RATELIMIT_MAX);
- return ERROR_INVAL;
- }
-
- return 0;
-}
-
-int libxl_sched_credit_params_get(libxl_ctx *ctx, uint32_t poolid,
- libxl_sched_credit_params *scinfo)
-{
- struct xen_sysctl_credit_schedule sparam;
- int r, rc;
- GC_INIT(ctx);
-
- r = xc_sched_credit_params_get(ctx->xch, poolid, &sparam);
- if (r < 0) {
- LOGE(ERROR, "getting Credit scheduler parameters");
- rc = ERROR_FAIL;
- goto out;
- }
-
- scinfo->tslice_ms = sparam.tslice_ms;
- scinfo->ratelimit_us = sparam.ratelimit_us;
-
- rc = 0;
- out:
- GC_FREE;
- return rc;
-}
-
-int libxl_sched_credit_params_set(libxl_ctx *ctx, uint32_t poolid,
- libxl_sched_credit_params *scinfo)
-{
- struct xen_sysctl_credit_schedule sparam;
- int r, rc;
- GC_INIT(ctx);
-
- if (scinfo->tslice_ms < XEN_SYSCTL_CSCHED_TSLICE_MIN
- || scinfo->tslice_ms > XEN_SYSCTL_CSCHED_TSLICE_MAX) {
- LOG(ERROR, "Time slice out of range, valid range is from %d to %d",
- XEN_SYSCTL_CSCHED_TSLICE_MIN, XEN_SYSCTL_CSCHED_TSLICE_MAX);
- rc = ERROR_INVAL;
- goto out;
- }
- rc = sched_ratelimit_check(gc, scinfo->ratelimit_us);
- if (rc) {
- goto out;
- }
- if (scinfo->ratelimit_us > scinfo->tslice_ms*1000) {
- LOG(ERROR, "Ratelimit cannot be greater than timeslice");
- rc = ERROR_INVAL;
- goto out;
- }
-
- sparam.tslice_ms = scinfo->tslice_ms;
- sparam.ratelimit_us = scinfo->ratelimit_us;
-
- r = xc_sched_credit_params_set(ctx->xch, poolid, &sparam);
- if ( r < 0 ) {
- LOGE(ERROR, "Setting Credit scheduler parameters");
- rc = ERROR_FAIL;
- goto out;
- }
-
- scinfo->tslice_ms = sparam.tslice_ms;
- scinfo->ratelimit_us = sparam.ratelimit_us;
-
- rc = 0;
- out:
- GC_FREE;
- return rc;
-}
-
-int libxl_sched_credit2_params_get(libxl_ctx *ctx, uint32_t poolid,
- libxl_sched_credit2_params *scinfo)
-{
- struct xen_sysctl_credit2_schedule sparam;
- int r, rc;
- GC_INIT(ctx);
-
- r = xc_sched_credit2_params_get(ctx->xch, poolid, &sparam);
- if (r < 0) {
- LOGE(ERROR, "getting Credit2 scheduler parameters");
- rc = ERROR_FAIL;
- goto out;
- }
-
- scinfo->ratelimit_us = sparam.ratelimit_us;
-
- rc = 0;
- out:
- GC_FREE;
- return rc;
-}
-
-
-int libxl_sched_credit2_params_set(libxl_ctx *ctx, uint32_t poolid,
- libxl_sched_credit2_params *scinfo)
-{
- struct xen_sysctl_credit2_schedule sparam;
- int r, rc;
- GC_INIT(ctx);
-
- rc = sched_ratelimit_check(gc, scinfo->ratelimit_us);
- if (rc) goto out;
-
- sparam.ratelimit_us = scinfo->ratelimit_us;
-
- r = xc_sched_credit2_params_set(ctx->xch, poolid, &sparam);
- if (r < 0) {
- LOGE(ERROR, "Setting Credit2 scheduler parameters");
- rc = ERROR_FAIL;
- goto out;
- }
-
- scinfo->ratelimit_us = sparam.ratelimit_us;
-
- rc = 0;
- out:
- GC_FREE;
- return rc;
-}
-
-static int sched_credit2_domain_get(libxl__gc *gc, uint32_t domid,
- libxl_domain_sched_params *scinfo)
-{
- struct xen_domctl_sched_credit2 sdom;
- int rc;
-
- rc = xc_sched_credit2_domain_get(CTX->xch, domid, &sdom);
- if (rc != 0) {
- LOGED(ERROR, domid, "Getting domain sched credit2");
- return ERROR_FAIL;
- }
-
- libxl_domain_sched_params_init(scinfo);
- scinfo->sched = LIBXL_SCHEDULER_CREDIT2;
- scinfo->weight = sdom.weight;
-
- return 0;
-}
-
-static int sched_credit2_domain_set(libxl__gc *gc, uint32_t domid,
- const libxl_domain_sched_params *scinfo)
-{
- struct xen_domctl_sched_credit2 sdom;
- int rc;
-
- rc = xc_sched_credit2_domain_get(CTX->xch, domid, &sdom);
- if (rc != 0) {
- LOGED(ERROR, domid, "Getting domain sched credit2");
- return ERROR_FAIL;
- }
-
- if (scinfo->weight != LIBXL_DOMAIN_SCHED_PARAM_WEIGHT_DEFAULT) {
- if (scinfo->weight < 1 || scinfo->weight > 65535) {
- LOGD(ERROR, domid, "Cpu weight out of range, "
- "valid values are within range from 1 to 65535");
- return ERROR_INVAL;
- }
- sdom.weight = scinfo->weight;
- }
-
- rc = xc_sched_credit2_domain_set(CTX->xch, domid, &sdom);
- if ( rc < 0 ) {
- LOGED(ERROR, domid, "Setting domain sched credit2");
- return ERROR_FAIL;
- }
-
- return 0;
-}
-
-static int sched_rtds_validate_params(libxl__gc *gc, int period, int budget)
-{
- int rc;
-
- if (period < 1) {
- LOG(ERROR, "Invalid VCPU period of %d (it should be >= 1)", period);
- rc = ERROR_INVAL;
- goto out;
- }
-
- if (budget < 1) {
- LOG(ERROR, "Invalid VCPU budget of %d (it should be >= 1)", budget);
- rc = ERROR_INVAL;
- goto out;
- }
-
- if (budget > period) {
- LOG(ERROR, "VCPU budget must be smaller than or equal to period, "
- "but %d > %d", budget, period);
- rc = ERROR_INVAL;
- goto out;
- }
- rc = 0;
-out:
- return rc;
-}
-
-/* Get the RTDS scheduling parameters of vcpu(s) */
-static int sched_rtds_vcpu_get(libxl__gc *gc, uint32_t domid,
- libxl_vcpu_sched_params *scinfo)
-{
- uint32_t num_vcpus;
- int i, r, rc;
- xc_dominfo_t info;
- struct xen_domctl_schedparam_vcpu *vcpus;
-
- r = xc_domain_getinfo(CTX->xch, domid, 1, &info);
- if (r < 0) {
- LOGED(ERROR, domid, "Getting domain info");
- rc = ERROR_FAIL;
- goto out;
- }
-
- if (scinfo->num_vcpus <= 0) {
- rc = ERROR_INVAL;
- goto out;
- } else {
- num_vcpus = scinfo->num_vcpus;
- GCNEW_ARRAY(vcpus, num_vcpus);
- for (i = 0; i < num_vcpus; i++) {
- if (scinfo->vcpus[i].vcpuid < 0 ||
- scinfo->vcpus[i].vcpuid > info.max_vcpu_id) {
- LOGD(ERROR, domid, "VCPU index is out of range, "
- "valid values are within range from 0 to %d",
- info.max_vcpu_id);
- rc = ERROR_INVAL;
- goto out;
- }
- vcpus[i].vcpuid = scinfo->vcpus[i].vcpuid;
- }
- }
-
- r = xc_sched_rtds_vcpu_get(CTX->xch, domid, vcpus, num_vcpus);
- if (r != 0) {
- LOGED(ERROR, domid, "Getting vcpu sched rtds");
- rc = ERROR_FAIL;
- goto out;
- }
- scinfo->sched = LIBXL_SCHEDULER_RTDS;
- for (i = 0; i < num_vcpus; i++) {
- scinfo->vcpus[i].period = vcpus[i].u.rtds.period;
- scinfo->vcpus[i].budget = vcpus[i].u.rtds.budget;
- scinfo->vcpus[i].vcpuid = vcpus[i].vcpuid;
- }
- rc = 0;
-out:
- return rc;
-}
-
-/* Get the RTDS scheduling parameters of all vcpus of a domain */
-static int sched_rtds_vcpu_get_all(libxl__gc *gc, uint32_t domid,
- libxl_vcpu_sched_params *scinfo)
-{
- uint32_t num_vcpus;
- int i, r, rc;
- xc_dominfo_t info;
- struct xen_domctl_schedparam_vcpu *vcpus;
-
- r = xc_domain_getinfo(CTX->xch, domid, 1, &info);
- if (r < 0) {
- LOGED(ERROR, domid, "Getting domain info");
- rc = ERROR_FAIL;
- goto out;
- }
-
- if (scinfo->num_vcpus > 0) {
- rc = ERROR_INVAL;
- goto out;
- } else {
- num_vcpus = info.max_vcpu_id + 1;
- GCNEW_ARRAY(vcpus, num_vcpus);
- for (i = 0; i < num_vcpus; i++)
- vcpus[i].vcpuid = i;
- }
-
- r = xc_sched_rtds_vcpu_get(CTX->xch, domid, vcpus, num_vcpus);
- if (r != 0) {
- LOGED(ERROR, domid, "Getting vcpu sched rtds");
- rc = ERROR_FAIL;
- goto out;
- }
- scinfo->sched = LIBXL_SCHEDULER_RTDS;
- scinfo->num_vcpus = num_vcpus;
- scinfo->vcpus = libxl__calloc(NOGC, num_vcpus,
- sizeof(libxl_sched_params));
-
- for (i = 0; i < num_vcpus; i++) {
- scinfo->vcpus[i].period = vcpus[i].u.rtds.period;
- scinfo->vcpus[i].budget = vcpus[i].u.rtds.budget;
- scinfo->vcpus[i].vcpuid = vcpus[i].vcpuid;
- }
- rc = 0;
-out:
- return rc;
-}
-
-/* Set the RTDS scheduling parameters of vcpu(s) */
-static int sched_rtds_vcpu_set(libxl__gc *gc, uint32_t domid,
- const libxl_vcpu_sched_params *scinfo)
-{
- int r, rc;
- int i;
- uint16_t max_vcpuid;
- xc_dominfo_t info;
- struct xen_domctl_schedparam_vcpu *vcpus;
-
- r = xc_domain_getinfo(CTX->xch, domid, 1, &info);
- if (r < 0) {
- LOGED(ERROR, domid, "Getting domain info");
- rc = ERROR_FAIL;
- goto out;
- }
- max_vcpuid = info.max_vcpu_id;
-
- if (scinfo->num_vcpus <= 0) {
- rc = ERROR_INVAL;
- goto out;
- }
- for (i = 0; i < scinfo->num_vcpus; i++) {
- if (scinfo->vcpus[i].vcpuid < 0 ||
- scinfo->vcpus[i].vcpuid > max_vcpuid) {
- LOGD(ERROR, domid, "Invalid VCPU %d: valid range is [0, %d]",
- scinfo->vcpus[i].vcpuid, max_vcpuid);
- rc = ERROR_INVAL;
- goto out;
- }
- rc = sched_rtds_validate_params(gc, scinfo->vcpus[i].period,
- scinfo->vcpus[i].budget);
- if (rc) {
- rc = ERROR_INVAL;
- goto out;
- }
- }
- GCNEW_ARRAY(vcpus, scinfo->num_vcpus);
- for (i = 0; i < scinfo->num_vcpus; i++) {
- vcpus[i].vcpuid = scinfo->vcpus[i].vcpuid;
- vcpus[i].u.rtds.period = scinfo->vcpus[i].period;
- vcpus[i].u.rtds.budget = scinfo->vcpus[i].budget;
- }
-
- r = xc_sched_rtds_vcpu_set(CTX->xch, domid,
- vcpus, scinfo->num_vcpus);
- if (r != 0) {
- LOGED(ERROR, domid, "Setting vcpu sched rtds");
- rc = ERROR_FAIL;
- goto out;
- }
- rc = 0;
-out:
- return rc;
-}
-
-/* Set the RTDS scheduling parameters of all vcpus of a domain */
-static int sched_rtds_vcpu_set_all(libxl__gc *gc, uint32_t domid,
- const libxl_vcpu_sched_params *scinfo)
-{
- int r, rc;
- int i;
- uint16_t max_vcpuid;
- xc_dominfo_t info;
- struct xen_domctl_schedparam_vcpu *vcpus;
- uint32_t num_vcpus;
-
- r = xc_domain_getinfo(CTX->xch, domid, 1, &info);
- if (r < 0) {
- LOGED(ERROR, domid, "Getting domain info");
- rc = ERROR_FAIL;
- goto out;
- }
- max_vcpuid = info.max_vcpu_id;
-
- if (scinfo->num_vcpus != 1) {
- rc = ERROR_INVAL;
- goto out;
- }
- if (sched_rtds_validate_params(gc, scinfo->vcpus[0].period,
- scinfo->vcpus[0].budget)) {
- rc = ERROR_INVAL;
- goto out;
- }
- num_vcpus = max_vcpuid + 1;
- GCNEW_ARRAY(vcpus, num_vcpus);
- for (i = 0; i < num_vcpus; i++) {
- vcpus[i].vcpuid = i;
- vcpus[i].u.rtds.period = scinfo->vcpus[0].period;
- vcpus[i].u.rtds.budget = scinfo->vcpus[0].budget;
- }
-
- r = xc_sched_rtds_vcpu_set(CTX->xch, domid,
- vcpus, num_vcpus);
- if (r != 0) {
- LOGED(ERROR, domid, "Setting vcpu sched rtds");
- rc = ERROR_FAIL;
- goto out;
- }
- rc = 0;
-out:
- return rc;
-}
-
-static int sched_rtds_domain_get(libxl__gc *gc, uint32_t domid,
- libxl_domain_sched_params *scinfo)
-{
- struct xen_domctl_sched_rtds sdom;
- int rc;
-
- rc = xc_sched_rtds_domain_get(CTX->xch, domid, &sdom);
- if (rc != 0) {
- LOGED(ERROR, domid, "Getting domain sched rtds");
- return ERROR_FAIL;
- }
-
- libxl_domain_sched_params_init(scinfo);
-
- scinfo->sched = LIBXL_SCHEDULER_RTDS;
- scinfo->period = sdom.period;
- scinfo->budget = sdom.budget;
-
- return 0;
-}
-
-static int sched_rtds_domain_set(libxl__gc *gc, uint32_t domid,
- const libxl_domain_sched_params *scinfo)
-{
- struct xen_domctl_sched_rtds sdom;
- int rc;
-
- rc = xc_sched_rtds_domain_get(CTX->xch, domid, &sdom);
- if (rc != 0) {
- LOGED(ERROR, domid, "Getting domain sched rtds");
- return ERROR_FAIL;
- }
- if (scinfo->period != LIBXL_DOMAIN_SCHED_PARAM_PERIOD_DEFAULT)
- sdom.period = scinfo->period;
- if (scinfo->budget != LIBXL_DOMAIN_SCHED_PARAM_BUDGET_DEFAULT)
- sdom.budget = scinfo->budget;
- if (sched_rtds_validate_params(gc, sdom.period, sdom.budget))
- return ERROR_INVAL;
-
- rc = xc_sched_rtds_domain_set(CTX->xch, domid, &sdom);
- if (rc < 0) {
- LOGED(ERROR, domid, "Setting domain sched rtds");
- return ERROR_FAIL;
- }
-
- return 0;
-}
-
-int libxl_domain_sched_params_set(libxl_ctx *ctx, uint32_t domid,
- const libxl_domain_sched_params *scinfo)
-{
- GC_INIT(ctx);
- libxl_scheduler sched = scinfo->sched;
- int ret;
-
- if (sched == LIBXL_SCHEDULER_UNKNOWN)
- sched = libxl__domain_scheduler(gc, domid);
-
- switch (sched) {
- case LIBXL_SCHEDULER_SEDF:
- LOGD(ERROR, domid, "SEDF scheduler no longer available");
- ret=ERROR_FEATURE_REMOVED;
- break;
- case LIBXL_SCHEDULER_CREDIT:
- ret=sched_credit_domain_set(gc, domid, scinfo);
- break;
- case LIBXL_SCHEDULER_CREDIT2:
- ret=sched_credit2_domain_set(gc, domid, scinfo);
- break;
- case LIBXL_SCHEDULER_ARINC653:
- ret=sched_arinc653_domain_set(gc, domid, scinfo);
- break;
- case LIBXL_SCHEDULER_RTDS:
- ret=sched_rtds_domain_set(gc, domid, scinfo);
- break;
- default:
- LOGD(ERROR, domid, "Unknown scheduler");
- ret=ERROR_INVAL;
- break;
- }
-
- GC_FREE;
- return ret;
-}
-
-int libxl_vcpu_sched_params_set(libxl_ctx *ctx, uint32_t domid,
- const libxl_vcpu_sched_params *scinfo)
-{
- GC_INIT(ctx);
- libxl_scheduler sched = scinfo->sched;
- int rc;
-
- if (sched == LIBXL_SCHEDULER_UNKNOWN)
- sched = libxl__domain_scheduler(gc, domid);
-
- switch (sched) {
- case LIBXL_SCHEDULER_SEDF:
- LOGD(ERROR, domid, "SEDF scheduler no longer available");
- rc = ERROR_FEATURE_REMOVED;
- break;
- case LIBXL_SCHEDULER_CREDIT:
- case LIBXL_SCHEDULER_CREDIT2:
- case LIBXL_SCHEDULER_ARINC653:
- LOGD(ERROR, domid, "per-VCPU parameter setting not supported for this scheduler");
- rc = ERROR_INVAL;
- break;
- case LIBXL_SCHEDULER_RTDS:
- rc = sched_rtds_vcpu_set(gc, domid, scinfo);
- break;
- default:
- LOGD(ERROR, domid, "Unknown scheduler");
- rc = ERROR_INVAL;
- break;
- }
-
- GC_FREE;
- return rc;
-}
-
-int libxl_vcpu_sched_params_set_all(libxl_ctx *ctx, uint32_t domid,
- const libxl_vcpu_sched_params *scinfo)
-{
- GC_INIT(ctx);
- libxl_scheduler sched = scinfo->sched;
- int rc;
-
- if (sched == LIBXL_SCHEDULER_UNKNOWN)
- sched = libxl__domain_scheduler(gc, domid);
-
- switch (sched) {
- case LIBXL_SCHEDULER_SEDF:
- LOGD(ERROR, domid, "SEDF scheduler no longer available");
- rc = ERROR_FEATURE_REMOVED;
- break;
- case LIBXL_SCHEDULER_CREDIT:
- case LIBXL_SCHEDULER_CREDIT2:
- case LIBXL_SCHEDULER_ARINC653:
- LOGD(ERROR, domid, "per-VCPU parameter setting not supported for this scheduler");
- rc = ERROR_INVAL;
- break;
- case LIBXL_SCHEDULER_RTDS:
- rc = sched_rtds_vcpu_set_all(gc, domid, scinfo);
- break;
- default:
- LOGD(ERROR, domid, "Unknown scheduler");
- rc = ERROR_INVAL;
- break;
- }
-
- GC_FREE;
- return rc;
-}
-
-int libxl_domain_sched_params_get(libxl_ctx *ctx, uint32_t domid,
- libxl_domain_sched_params *scinfo)
-{
- GC_INIT(ctx);
- int ret;
-
- libxl_domain_sched_params_init(scinfo);
-
- scinfo->sched = libxl__domain_scheduler(gc, domid);
-
- switch (scinfo->sched) {
- case LIBXL_SCHEDULER_SEDF:
- LOGD(ERROR, domid, "SEDF scheduler no longer available");
- ret=ERROR_FEATURE_REMOVED;
- break;
- case LIBXL_SCHEDULER_CREDIT:
- ret=sched_credit_domain_get(gc, domid, scinfo);
- break;
- case LIBXL_SCHEDULER_CREDIT2:
- ret=sched_credit2_domain_get(gc, domid, scinfo);
- break;
- case LIBXL_SCHEDULER_RTDS:
- ret=sched_rtds_domain_get(gc, domid, scinfo);
- break;
- default:
- LOGD(ERROR, domid, "Unknown scheduler");
- ret=ERROR_INVAL;
- break;
- }
-
- GC_FREE;
- return ret;
-}
-
-int libxl_vcpu_sched_params_get(libxl_ctx *ctx, uint32_t domid,
- libxl_vcpu_sched_params *scinfo)
-{
- GC_INIT(ctx);
- int rc;
-
- scinfo->sched = libxl__domain_scheduler(gc, domid);
-
- switch (scinfo->sched) {
- case LIBXL_SCHEDULER_SEDF:
- LOGD(ERROR, domid, "SEDF scheduler is no longer available");
- rc = ERROR_FEATURE_REMOVED;
- break;
- case LIBXL_SCHEDULER_CREDIT:
- case LIBXL_SCHEDULER_CREDIT2:
- case LIBXL_SCHEDULER_ARINC653:
- LOGD(ERROR, domid, "per-VCPU parameter getting not supported for this scheduler");
- rc = ERROR_INVAL;
- break;
- case LIBXL_SCHEDULER_RTDS:
- rc = sched_rtds_vcpu_get(gc, domid, scinfo);
- break;
- default:
- LOGD(ERROR, domid, "Unknown scheduler");
- rc = ERROR_INVAL;
- break;
- }
-
- GC_FREE;
- return rc;
-}
-
-int libxl_vcpu_sched_params_get_all(libxl_ctx *ctx, uint32_t domid,
- libxl_vcpu_sched_params *scinfo)
-{
- GC_INIT(ctx);
- int rc;
-
- scinfo->sched = libxl__domain_scheduler(gc, domid);
-
- switch (scinfo->sched) {
- case LIBXL_SCHEDULER_SEDF:
- LOGD(ERROR, domid, "SEDF scheduler is no longer available");
- rc = ERROR_FEATURE_REMOVED;
- break;
- case LIBXL_SCHEDULER_CREDIT:
- case LIBXL_SCHEDULER_CREDIT2:
- case LIBXL_SCHEDULER_ARINC653:
- LOGD(ERROR, domid, "per-VCPU parameter getting not supported for this scheduler");
- rc = ERROR_INVAL;
- break;
- case LIBXL_SCHEDULER_RTDS:
- rc = sched_rtds_vcpu_get_all(gc, domid, scinfo);
- break;
- default:
- LOGD(ERROR, domid, "Unknown scheduler");
- rc = ERROR_INVAL;
- break;
- }
-
- GC_FREE;
- return rc;
-}
-
static int libxl__domain_s3_resume(libxl__gc *gc, int domid)
{
int rc = 0;
diff --git a/tools/libxl/libxl_sched.c b/tools/libxl/libxl_sched.c
new file mode 100644
index 0000000..84d3837
--- /dev/null
+++ b/tools/libxl/libxl_sched.c
@@ -0,0 +1,915 @@
+/*
+ * 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"
+
+static int libxl__set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid,
+ uint32_t vcpuid,
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft,
+ unsigned flags)
+{
+ GC_INIT(ctx);
+ libxl_bitmap hard, soft;
+ int rc;
+
+ libxl_bitmap_init(&hard);
+ libxl_bitmap_init(&soft);
+
+ if (!cpumap_hard && !cpumap_soft && !flags) {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ /*
+ * Xen wants writable hard and/or soft cpumaps, to put back in them
+ * the effective hard and/or soft affinity that will be used.
+ */
+ if (cpumap_hard) {
+ rc = libxl_cpu_bitmap_alloc(ctx, &hard, 0);
+ if (rc)
+ goto out;
+
+ libxl__bitmap_copy_best_effort(gc, &hard, cpumap_hard);
+ flags |= XEN_VCPUAFFINITY_HARD;
+ }
+ if (cpumap_soft) {
+ rc = libxl_cpu_bitmap_alloc(ctx, &soft, 0);
+ if (rc)
+ goto out;
+
+ libxl__bitmap_copy_best_effort(gc, &soft, cpumap_soft);
+ flags |= XEN_VCPUAFFINITY_SOFT;
+ }
+
+ if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid,
+ cpumap_hard ? hard.map : NULL,
+ cpumap_soft ? soft.map : NULL,
+ flags)) {
+ LOGED(ERROR, domid, "Setting vcpu affinity");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /*
+ * Let's check the results. Hard affinity will never be empty, but it
+ * is possible that Xen will use something different from what we asked
+ * for various reasons. If that's the case, report it.
+ */
+ if (cpumap_hard &&
+ !libxl_bitmap_equal(cpumap_hard, &hard, 0))
+ LOGD(DEBUG, domid, "New hard affinity for vcpu %d has unreachable cpus", vcpuid);
+ /*
+ * Soft affinity can both be different from what asked and empty. Check
+ * for (and report) both.
+ */
+ if (cpumap_soft) {
+ if (!libxl_bitmap_equal(cpumap_soft, &soft, 0))
+ LOGD(DEBUG, domid, "New soft affinity for vcpu %d has unreachable cpus",
+ vcpuid);
+ if (libxl_bitmap_is_empty(&soft))
+ LOGD(WARN, domid, "All cpus in soft affinity of vcpu %d are unreachable."
+ " Only hard affinity will be considered for scheduling",
+ vcpuid);
+ }
+
+ rc = 0;
+ out:
+ libxl_bitmap_dispose(&hard);
+ libxl_bitmap_dispose(&soft);
+ GC_FREE;
+ return rc;
+}
+
+int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft)
+{
+ return libxl__set_vcpuaffinity(ctx, domid, vcpuid, cpumap_hard,
+ cpumap_soft, 0);
+}
+
+int libxl_set_vcpuaffinity_force(libxl_ctx *ctx, uint32_t domid,
+ uint32_t vcpuid,
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft)
+{
+ return libxl__set_vcpuaffinity(ctx, domid, vcpuid, cpumap_hard,
+ cpumap_soft, XEN_VCPUAFFINITY_FORCE);
+}
+
+int libxl_set_vcpuaffinity_all(libxl_ctx *ctx, uint32_t domid,
+ unsigned int max_vcpus,
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft)
+{
+ GC_INIT(ctx);
+ int i, rc = 0;
+
+ for (i = 0; i < max_vcpus; i++) {
+ if (libxl_set_vcpuaffinity(ctx, domid, i, cpumap_hard, cpumap_soft)) {
+ LOGD(WARN, domid, "Failed to set affinity for %d", i);
+ rc = ERROR_FAIL;
+ }
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+int libxl_domain_set_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
+ libxl_bitmap *nodemap)
+{
+ GC_INIT(ctx);
+ if (xc_domain_node_setaffinity(ctx->xch, domid, nodemap->map)) {
+ LOGED(ERROR, domid, "Setting node affinity");
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+ GC_FREE;
+ return 0;
+}
+
+int libxl_domain_get_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
+ libxl_bitmap *nodemap)
+{
+ GC_INIT(ctx);
+ if (xc_domain_node_getaffinity(ctx->xch, domid, nodemap->map)) {
+ LOGED(ERROR, domid, "Getting node affinity");
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+ GC_FREE;
+ return 0;
+}
+
+int libxl_get_scheduler(libxl_ctx *ctx)
+{
+ int r, sched;
+
+ GC_INIT(ctx);
+ r = xc_sched_id(ctx->xch, &sched);
+ if (r != 0) {
+ LOGE(ERROR, "getting current scheduler id");
+ sched = ERROR_FAIL;
+ }
+ GC_FREE;
+ return sched;
+}
+
+static int sched_arinc653_domain_set(libxl__gc *gc, uint32_t domid,
+ const libxl_domain_sched_params *scinfo)
+{
+ /* Currently, the ARINC 653 scheduler does not take any domain-specific
+ configuration, so we simply return success. */
+ return 0;
+}
+
+static int sched_credit_domain_get(libxl__gc *gc, uint32_t domid,
+ libxl_domain_sched_params *scinfo)
+{
+ struct xen_domctl_sched_credit sdom;
+ int rc;
+
+ rc = xc_sched_credit_domain_get(CTX->xch, domid, &sdom);
+ if (rc != 0) {
+ LOGED(ERROR, domid, "Getting domain sched credit");
+ return ERROR_FAIL;
+ }
+
+ libxl_domain_sched_params_init(scinfo);
+ scinfo->sched = LIBXL_SCHEDULER_CREDIT;
+ scinfo->weight = sdom.weight;
+ scinfo->cap = sdom.cap;
+
+ return 0;
+}
+
+static int sched_credit_domain_set(libxl__gc *gc, uint32_t domid,
+ const libxl_domain_sched_params *scinfo)
+{
+ struct xen_domctl_sched_credit sdom;
+ xc_domaininfo_t domaininfo;
+ int rc;
+
+ rc = xc_domain_getinfolist(CTX->xch, domid, 1, &domaininfo);
+ if (rc < 0) {
+ LOGED(ERROR, domid, "Getting domain info list");
+ return ERROR_FAIL;
+ }
+ if (rc != 1 || domaininfo.domain != domid)
+ return ERROR_INVAL;
+
+ rc = xc_sched_credit_domain_get(CTX->xch, domid, &sdom);
+ if (rc != 0) {
+ LOGED(ERROR, domid, "Getting domain sched credit");
+ return ERROR_FAIL;
+ }
+
+ if (scinfo->weight != LIBXL_DOMAIN_SCHED_PARAM_WEIGHT_DEFAULT) {
+ if (scinfo->weight < 1 || scinfo->weight > 65535) {
+ LOGD(ERROR, domid, "Cpu weight out of range, "
+ "valid values are within range from 1 to 65535");
+ return ERROR_INVAL;
+ }
+ sdom.weight = scinfo->weight;
+ }
+
+ if (scinfo->cap != LIBXL_DOMAIN_SCHED_PARAM_CAP_DEFAULT) {
+ if (scinfo->cap < 0
+ || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
+ LOGD(ERROR, domid, "Cpu cap out of range, "
+ "valid range is from 0 to %d for specified number of vcpus",
+ ((domaininfo.max_vcpu_id + 1) * 100));
+ return ERROR_INVAL;
+ }
+ sdom.cap = scinfo->cap;
+ }
+
+ rc = xc_sched_credit_domain_set(CTX->xch, domid, &sdom);
+ if ( rc < 0 ) {
+ LOGED(ERROR, domid, "Setting domain sched credit");
+ return ERROR_FAIL;
+ }
+
+ return 0;
+}
+
+static int sched_ratelimit_check(libxl__gc *gc, int ratelimit)
+{
+ if (ratelimit != 0 &&
+ (ratelimit < XEN_SYSCTL_SCHED_RATELIMIT_MIN ||
+ ratelimit > XEN_SYSCTL_SCHED_RATELIMIT_MAX)) {
+ LOG(ERROR, "Ratelimit out of range, valid range is from %d to %d",
+ XEN_SYSCTL_SCHED_RATELIMIT_MIN, XEN_SYSCTL_SCHED_RATELIMIT_MAX);
+ return ERROR_INVAL;
+ }
+
+ return 0;
+}
+
+int libxl_sched_credit_params_get(libxl_ctx *ctx, uint32_t poolid,
+ libxl_sched_credit_params *scinfo)
+{
+ struct xen_sysctl_credit_schedule sparam;
+ int r, rc;
+ GC_INIT(ctx);
+
+ r = xc_sched_credit_params_get(ctx->xch, poolid, &sparam);
+ if (r < 0) {
+ LOGE(ERROR, "getting Credit scheduler parameters");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ scinfo->tslice_ms = sparam.tslice_ms;
+ scinfo->ratelimit_us = sparam.ratelimit_us;
+
+ rc = 0;
+ out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl_sched_credit_params_set(libxl_ctx *ctx, uint32_t poolid,
+ libxl_sched_credit_params *scinfo)
+{
+ struct xen_sysctl_credit_schedule sparam;
+ int r, rc;
+ GC_INIT(ctx);
+
+ if (scinfo->tslice_ms < XEN_SYSCTL_CSCHED_TSLICE_MIN
+ || scinfo->tslice_ms > XEN_SYSCTL_CSCHED_TSLICE_MAX) {
+ LOG(ERROR, "Time slice out of range, valid range is from %d to %d",
+ XEN_SYSCTL_CSCHED_TSLICE_MIN, XEN_SYSCTL_CSCHED_TSLICE_MAX);
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ rc = sched_ratelimit_check(gc, scinfo->ratelimit_us);
+ if (rc) {
+ goto out;
+ }
+ if (scinfo->ratelimit_us > scinfo->tslice_ms*1000) {
+ LOG(ERROR, "Ratelimit cannot be greater than timeslice");
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ sparam.tslice_ms = scinfo->tslice_ms;
+ sparam.ratelimit_us = scinfo->ratelimit_us;
+
+ r = xc_sched_credit_params_set(ctx->xch, poolid, &sparam);
+ if ( r < 0 ) {
+ LOGE(ERROR, "Setting Credit scheduler parameters");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ scinfo->tslice_ms = sparam.tslice_ms;
+ scinfo->ratelimit_us = sparam.ratelimit_us;
+
+ rc = 0;
+ out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl_sched_credit2_params_get(libxl_ctx *ctx, uint32_t poolid,
+ libxl_sched_credit2_params *scinfo)
+{
+ struct xen_sysctl_credit2_schedule sparam;
+ int r, rc;
+ GC_INIT(ctx);
+
+ r = xc_sched_credit2_params_get(ctx->xch, poolid, &sparam);
+ if (r < 0) {
+ LOGE(ERROR, "getting Credit2 scheduler parameters");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ scinfo->ratelimit_us = sparam.ratelimit_us;
+
+ rc = 0;
+ out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl_sched_credit2_params_set(libxl_ctx *ctx, uint32_t poolid,
+ libxl_sched_credit2_params *scinfo)
+{
+ struct xen_sysctl_credit2_schedule sparam;
+ int r, rc;
+ GC_INIT(ctx);
+
+ rc = sched_ratelimit_check(gc, scinfo->ratelimit_us);
+ if (rc) goto out;
+
+ sparam.ratelimit_us = scinfo->ratelimit_us;
+
+ r = xc_sched_credit2_params_set(ctx->xch, poolid, &sparam);
+ if (r < 0) {
+ LOGE(ERROR, "Setting Credit2 scheduler parameters");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ scinfo->ratelimit_us = sparam.ratelimit_us;
+
+ rc = 0;
+ out:
+ GC_FREE;
+ return rc;
+}
+
+static int sched_credit2_domain_get(libxl__gc *gc, uint32_t domid,
+ libxl_domain_sched_params *scinfo)
+{
+ struct xen_domctl_sched_credit2 sdom;
+ int rc;
+
+ rc = xc_sched_credit2_domain_get(CTX->xch, domid, &sdom);
+ if (rc != 0) {
+ LOGED(ERROR, domid, "Getting domain sched credit2");
+ return ERROR_FAIL;
+ }
+
+ libxl_domain_sched_params_init(scinfo);
+ scinfo->sched = LIBXL_SCHEDULER_CREDIT2;
+ scinfo->weight = sdom.weight;
+
+ return 0;
+}
+
+static int sched_credit2_domain_set(libxl__gc *gc, uint32_t domid,
+ const libxl_domain_sched_params *scinfo)
+{
+ struct xen_domctl_sched_credit2 sdom;
+ int rc;
+
+ rc = xc_sched_credit2_domain_get(CTX->xch, domid, &sdom);
+ if (rc != 0) {
+ LOGED(ERROR, domid, "Getting domain sched credit2");
+ return ERROR_FAIL;
+ }
+
+ if (scinfo->weight != LIBXL_DOMAIN_SCHED_PARAM_WEIGHT_DEFAULT) {
+ if (scinfo->weight < 1 || scinfo->weight > 65535) {
+ LOGD(ERROR, domid, "Cpu weight out of range, "
+ "valid values are within range from 1 to 65535");
+ return ERROR_INVAL;
+ }
+ sdom.weight = scinfo->weight;
+ }
+
+ rc = xc_sched_credit2_domain_set(CTX->xch, domid, &sdom);
+ if ( rc < 0 ) {
+ LOGED(ERROR, domid, "Setting domain sched credit2");
+ return ERROR_FAIL;
+ }
+
+ return 0;
+}
+
+static int sched_rtds_validate_params(libxl__gc *gc, int period, int budget)
+{
+ int rc;
+
+ if (period < 1) {
+ LOG(ERROR, "Invalid VCPU period of %d (it should be >= 1)", period);
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ if (budget < 1) {
+ LOG(ERROR, "Invalid VCPU budget of %d (it should be >= 1)", budget);
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ if (budget > period) {
+ LOG(ERROR, "VCPU budget must be smaller than or equal to period, "
+ "but %d > %d", budget, period);
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ rc = 0;
+out:
+ return rc;
+}
+
+/* Get the RTDS scheduling parameters of vcpu(s) */
+static int sched_rtds_vcpu_get(libxl__gc *gc, uint32_t domid,
+ libxl_vcpu_sched_params *scinfo)
+{
+ uint32_t num_vcpus;
+ int i, r, rc;
+ xc_dominfo_t info;
+ struct xen_domctl_schedparam_vcpu *vcpus;
+
+ r = xc_domain_getinfo(CTX->xch, domid, 1, &info);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Getting domain info");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (scinfo->num_vcpus <= 0) {
+ rc = ERROR_INVAL;
+ goto out;
+ } else {
+ num_vcpus = scinfo->num_vcpus;
+ GCNEW_ARRAY(vcpus, num_vcpus);
+ for (i = 0; i < num_vcpus; i++) {
+ if (scinfo->vcpus[i].vcpuid < 0 ||
+ scinfo->vcpus[i].vcpuid > info.max_vcpu_id) {
+ LOGD(ERROR, domid, "VCPU index is out of range, "
+ "valid values are within range from 0 to %d",
+ info.max_vcpu_id);
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ vcpus[i].vcpuid = scinfo->vcpus[i].vcpuid;
+ }
+ }
+
+ r = xc_sched_rtds_vcpu_get(CTX->xch, domid, vcpus, num_vcpus);
+ if (r != 0) {
+ LOGED(ERROR, domid, "Getting vcpu sched rtds");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ scinfo->sched = LIBXL_SCHEDULER_RTDS;
+ for (i = 0; i < num_vcpus; i++) {
+ scinfo->vcpus[i].period = vcpus[i].u.rtds.period;
+ scinfo->vcpus[i].budget = vcpus[i].u.rtds.budget;
+ scinfo->vcpus[i].vcpuid = vcpus[i].vcpuid;
+ }
+ rc = 0;
+out:
+ return rc;
+}
+
+/* Get the RTDS scheduling parameters of all vcpus of a domain */
+static int sched_rtds_vcpu_get_all(libxl__gc *gc, uint32_t domid,
+ libxl_vcpu_sched_params *scinfo)
+{
+ uint32_t num_vcpus;
+ int i, r, rc;
+ xc_dominfo_t info;
+ struct xen_domctl_schedparam_vcpu *vcpus;
+
+ r = xc_domain_getinfo(CTX->xch, domid, 1, &info);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Getting domain info");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (scinfo->num_vcpus > 0) {
+ rc = ERROR_INVAL;
+ goto out;
+ } else {
+ num_vcpus = info.max_vcpu_id + 1;
+ GCNEW_ARRAY(vcpus, num_vcpus);
+ for (i = 0; i < num_vcpus; i++)
+ vcpus[i].vcpuid = i;
+ }
+
+ r = xc_sched_rtds_vcpu_get(CTX->xch, domid, vcpus, num_vcpus);
+ if (r != 0) {
+ LOGED(ERROR, domid, "Getting vcpu sched rtds");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ scinfo->sched = LIBXL_SCHEDULER_RTDS;
+ scinfo->num_vcpus = num_vcpus;
+ scinfo->vcpus = libxl__calloc(NOGC, num_vcpus,
+ sizeof(libxl_sched_params));
+
+ for (i = 0; i < num_vcpus; i++) {
+ scinfo->vcpus[i].period = vcpus[i].u.rtds.period;
+ scinfo->vcpus[i].budget = vcpus[i].u.rtds.budget;
+ scinfo->vcpus[i].vcpuid = vcpus[i].vcpuid;
+ }
+ rc = 0;
+out:
+ return rc;
+}
+
+/* Set the RTDS scheduling parameters of vcpu(s) */
+static int sched_rtds_vcpu_set(libxl__gc *gc, uint32_t domid,
+ const libxl_vcpu_sched_params *scinfo)
+{
+ int r, rc;
+ int i;
+ uint16_t max_vcpuid;
+ xc_dominfo_t info;
+ struct xen_domctl_schedparam_vcpu *vcpus;
+
+ r = xc_domain_getinfo(CTX->xch, domid, 1, &info);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Getting domain info");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ max_vcpuid = info.max_vcpu_id;
+
+ if (scinfo->num_vcpus <= 0) {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ for (i = 0; i < scinfo->num_vcpus; i++) {
+ if (scinfo->vcpus[i].vcpuid < 0 ||
+ scinfo->vcpus[i].vcpuid > max_vcpuid) {
+ LOGD(ERROR, domid, "Invalid VCPU %d: valid range is [0, %d]",
+ scinfo->vcpus[i].vcpuid, max_vcpuid);
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ rc = sched_rtds_validate_params(gc, scinfo->vcpus[i].period,
+ scinfo->vcpus[i].budget);
+ if (rc) {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ }
+ GCNEW_ARRAY(vcpus, scinfo->num_vcpus);
+ for (i = 0; i < scinfo->num_vcpus; i++) {
+ vcpus[i].vcpuid = scinfo->vcpus[i].vcpuid;
+ vcpus[i].u.rtds.period = scinfo->vcpus[i].period;
+ vcpus[i].u.rtds.budget = scinfo->vcpus[i].budget;
+ }
+
+ r = xc_sched_rtds_vcpu_set(CTX->xch, domid,
+ vcpus, scinfo->num_vcpus);
+ if (r != 0) {
+ LOGED(ERROR, domid, "Setting vcpu sched rtds");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ rc = 0;
+out:
+ return rc;
+}
+
+/* Set the RTDS scheduling parameters of all vcpus of a domain */
+static int sched_rtds_vcpu_set_all(libxl__gc *gc, uint32_t domid,
+ const libxl_vcpu_sched_params *scinfo)
+{
+ int r, rc;
+ int i;
+ uint16_t max_vcpuid;
+ xc_dominfo_t info;
+ struct xen_domctl_schedparam_vcpu *vcpus;
+ uint32_t num_vcpus;
+
+ r = xc_domain_getinfo(CTX->xch, domid, 1, &info);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Getting domain info");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ max_vcpuid = info.max_vcpu_id;
+
+ if (scinfo->num_vcpus != 1) {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ if (sched_rtds_validate_params(gc, scinfo->vcpus[0].period,
+ scinfo->vcpus[0].budget)) {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ num_vcpus = max_vcpuid + 1;
+ GCNEW_ARRAY(vcpus, num_vcpus);
+ for (i = 0; i < num_vcpus; i++) {
+ vcpus[i].vcpuid = i;
+ vcpus[i].u.rtds.period = scinfo->vcpus[0].period;
+ vcpus[i].u.rtds.budget = scinfo->vcpus[0].budget;
+ }
+
+ r = xc_sched_rtds_vcpu_set(CTX->xch, domid,
+ vcpus, num_vcpus);
+ if (r != 0) {
+ LOGED(ERROR, domid, "Setting vcpu sched rtds");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ rc = 0;
+out:
+ return rc;
+}
+
+static int sched_rtds_domain_get(libxl__gc *gc, uint32_t domid,
+ libxl_domain_sched_params *scinfo)
+{
+ struct xen_domctl_sched_rtds sdom;
+ int rc;
+
+ rc = xc_sched_rtds_domain_get(CTX->xch, domid, &sdom);
+ if (rc != 0) {
+ LOGED(ERROR, domid, "Getting domain sched rtds");
+ return ERROR_FAIL;
+ }
+
+ libxl_domain_sched_params_init(scinfo);
+
+ scinfo->sched = LIBXL_SCHEDULER_RTDS;
+ scinfo->period = sdom.period;
+ scinfo->budget = sdom.budget;
+
+ return 0;
+}
+
+static int sched_rtds_domain_set(libxl__gc *gc, uint32_t domid,
+ const libxl_domain_sched_params *scinfo)
+{
+ struct xen_domctl_sched_rtds sdom;
+ int rc;
+
+ rc = xc_sched_rtds_domain_get(CTX->xch, domid, &sdom);
+ if (rc != 0) {
+ LOGED(ERROR, domid, "Getting domain sched rtds");
+ return ERROR_FAIL;
+ }
+ if (scinfo->period != LIBXL_DOMAIN_SCHED_PARAM_PERIOD_DEFAULT)
+ sdom.period = scinfo->period;
+ if (scinfo->budget != LIBXL_DOMAIN_SCHED_PARAM_BUDGET_DEFAULT)
+ sdom.budget = scinfo->budget;
+ if (sched_rtds_validate_params(gc, sdom.period, sdom.budget))
+ return ERROR_INVAL;
+
+ rc = xc_sched_rtds_domain_set(CTX->xch, domid, &sdom);
+ if (rc < 0) {
+ LOGED(ERROR, domid, "Setting domain sched rtds");
+ return ERROR_FAIL;
+ }
+
+ return 0;
+}
+
+int libxl_domain_sched_params_set(libxl_ctx *ctx, uint32_t domid,
+ const libxl_domain_sched_params *scinfo)
+{
+ GC_INIT(ctx);
+ libxl_scheduler sched = scinfo->sched;
+ int ret;
+
+ if (sched == LIBXL_SCHEDULER_UNKNOWN)
+ sched = libxl__domain_scheduler(gc, domid);
+
+ switch (sched) {
+ case LIBXL_SCHEDULER_SEDF:
+ LOGD(ERROR, domid, "SEDF scheduler no longer available");
+ ret=ERROR_FEATURE_REMOVED;
+ break;
+ case LIBXL_SCHEDULER_CREDIT:
+ ret=sched_credit_domain_set(gc, domid, scinfo);
+ break;
+ case LIBXL_SCHEDULER_CREDIT2:
+ ret=sched_credit2_domain_set(gc, domid, scinfo);
+ break;
+ case LIBXL_SCHEDULER_ARINC653:
+ ret=sched_arinc653_domain_set(gc, domid, scinfo);
+ break;
+ case LIBXL_SCHEDULER_RTDS:
+ ret=sched_rtds_domain_set(gc, domid, scinfo);
+ break;
+ default:
+ LOGD(ERROR, domid, "Unknown scheduler");
+ ret=ERROR_INVAL;
+ break;
+ }
+
+ GC_FREE;
+ return ret;
+}
+
+int libxl_vcpu_sched_params_set(libxl_ctx *ctx, uint32_t domid,
+ const libxl_vcpu_sched_params *scinfo)
+{
+ GC_INIT(ctx);
+ libxl_scheduler sched = scinfo->sched;
+ int rc;
+
+ if (sched == LIBXL_SCHEDULER_UNKNOWN)
+ sched = libxl__domain_scheduler(gc, domid);
+
+ switch (sched) {
+ case LIBXL_SCHEDULER_SEDF:
+ LOGD(ERROR, domid, "SEDF scheduler no longer available");
+ rc = ERROR_FEATURE_REMOVED;
+ break;
+ case LIBXL_SCHEDULER_CREDIT:
+ case LIBXL_SCHEDULER_CREDIT2:
+ case LIBXL_SCHEDULER_ARINC653:
+ LOGD(ERROR, domid, "per-VCPU parameter setting not supported for this scheduler");
+ rc = ERROR_INVAL;
+ break;
+ case LIBXL_SCHEDULER_RTDS:
+ rc = sched_rtds_vcpu_set(gc, domid, scinfo);
+ break;
+ default:
+ LOGD(ERROR, domid, "Unknown scheduler");
+ rc = ERROR_INVAL;
+ break;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+int libxl_vcpu_sched_params_set_all(libxl_ctx *ctx, uint32_t domid,
+ const libxl_vcpu_sched_params *scinfo)
+{
+ GC_INIT(ctx);
+ libxl_scheduler sched = scinfo->sched;
+ int rc;
+
+ if (sched == LIBXL_SCHEDULER_UNKNOWN)
+ sched = libxl__domain_scheduler(gc, domid);
+
+ switch (sched) {
+ case LIBXL_SCHEDULER_SEDF:
+ LOGD(ERROR, domid, "SEDF scheduler no longer available");
+ rc = ERROR_FEATURE_REMOVED;
+ break;
+ case LIBXL_SCHEDULER_CREDIT:
+ case LIBXL_SCHEDULER_CREDIT2:
+ case LIBXL_SCHEDULER_ARINC653:
+ LOGD(ERROR, domid, "per-VCPU parameter setting not supported for this scheduler");
+ rc = ERROR_INVAL;
+ break;
+ case LIBXL_SCHEDULER_RTDS:
+ rc = sched_rtds_vcpu_set_all(gc, domid, scinfo);
+ break;
+ default:
+ LOGD(ERROR, domid, "Unknown scheduler");
+ rc = ERROR_INVAL;
+ break;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+int libxl_domain_sched_params_get(libxl_ctx *ctx, uint32_t domid,
+ libxl_domain_sched_params *scinfo)
+{
+ GC_INIT(ctx);
+ int ret;
+
+ libxl_domain_sched_params_init(scinfo);
+
+ scinfo->sched = libxl__domain_scheduler(gc, domid);
+
+ switch (scinfo->sched) {
+ case LIBXL_SCHEDULER_SEDF:
+ LOGD(ERROR, domid, "SEDF scheduler no longer available");
+ ret=ERROR_FEATURE_REMOVED;
+ break;
+ case LIBXL_SCHEDULER_CREDIT:
+ ret=sched_credit_domain_get(gc, domid, scinfo);
+ break;
+ case LIBXL_SCHEDULER_CREDIT2:
+ ret=sched_credit2_domain_get(gc, domid, scinfo);
+ break;
+ case LIBXL_SCHEDULER_RTDS:
+ ret=sched_rtds_domain_get(gc, domid, scinfo);
+ break;
+ default:
+ LOGD(ERROR, domid, "Unknown scheduler");
+ ret=ERROR_INVAL;
+ break;
+ }
+
+ GC_FREE;
+ return ret;
+}
+
+int libxl_vcpu_sched_params_get(libxl_ctx *ctx, uint32_t domid,
+ libxl_vcpu_sched_params *scinfo)
+{
+ GC_INIT(ctx);
+ int rc;
+
+ scinfo->sched = libxl__domain_scheduler(gc, domid);
+
+ switch (scinfo->sched) {
+ case LIBXL_SCHEDULER_SEDF:
+ LOGD(ERROR, domid, "SEDF scheduler is no longer available");
+ rc = ERROR_FEATURE_REMOVED;
+ break;
+ case LIBXL_SCHEDULER_CREDIT:
+ case LIBXL_SCHEDULER_CREDIT2:
+ case LIBXL_SCHEDULER_ARINC653:
+ LOGD(ERROR, domid, "per-VCPU parameter getting not supported for this scheduler");
+ rc = ERROR_INVAL;
+ break;
+ case LIBXL_SCHEDULER_RTDS:
+ rc = sched_rtds_vcpu_get(gc, domid, scinfo);
+ break;
+ default:
+ LOGD(ERROR, domid, "Unknown scheduler");
+ rc = ERROR_INVAL;
+ break;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+int libxl_vcpu_sched_params_get_all(libxl_ctx *ctx, uint32_t domid,
+ libxl_vcpu_sched_params *scinfo)
+{
+ GC_INIT(ctx);
+ int rc;
+
+ scinfo->sched = libxl__domain_scheduler(gc, domid);
+
+ switch (scinfo->sched) {
+ case LIBXL_SCHEDULER_SEDF:
+ LOGD(ERROR, domid, "SEDF scheduler is no longer available");
+ rc = ERROR_FEATURE_REMOVED;
+ break;
+ case LIBXL_SCHEDULER_CREDIT:
+ case LIBXL_SCHEDULER_CREDIT2:
+ case LIBXL_SCHEDULER_ARINC653:
+ LOGD(ERROR, domid, "per-VCPU parameter getting not supported for this scheduler");
+ rc = ERROR_INVAL;
+ break;
+ case LIBXL_SCHEDULER_RTDS:
+ rc = sched_rtds_vcpu_get_all(gc, domid, scinfo);
+ break;
+ default:
+ LOGD(ERROR, domid, "Unknown scheduler");
+ rc = ERROR_INVAL;
+ break;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 06/12] libxl: carve out disk specific functions from libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (4 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 05/12] libxl: carve out scheduler " Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 9:30 ` [PATCH v2 07/12] libxl: carve out console " Juergen Gross
` (7 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
libxl.c has grown to an uncomfortable size. Carve out the disk
related functions to libxl_disk.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/Makefile | 2 +-
tools/libxl/libxl.c | 1233 ---------------------------------------------
tools/libxl/libxl_disk.c | 1258 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1259 insertions(+), 1234 deletions(-)
create mode 100644 tools/libxl/libxl_disk.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 7514cc2..baf591d 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -136,7 +136,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_save_callout.o _libxl_save_msgs_callout.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_vtpm.o libxl_nic.o libxl_disk.o \
libxl_cpupool.o libxl_sched.o \
$(LIBXL_OBJS-y)
LIBXL_OBJS += libxl_genid.o
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index ae6c7d4..3f8f16e 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -18,7 +18,6 @@
#include "libxl_arch.h"
#define PAGE_TO_MEMKB(pages) ((pages) * 4)
-#define BACKEND_STRING_SIZE 5
int libxl_ctx_alloc(libxl_ctx **pctx, int version,
unsigned flags, xentoollog_logger * lg)
@@ -1197,140 +1196,6 @@ void libxl_evdisable_domain_death(libxl_ctx *ctx,
GC_FREE;
}
-static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
- const char *wpath, const char *epath) {
- EGC_GC;
- libxl_evgen_disk_eject *evg = (void*)w;
- const char *backend;
- char *value;
- char backend_type[BACKEND_STRING_SIZE+1];
- int rc;
-
- value = libxl__xs_read(gc, XBT_NULL, wpath);
-
- if (!value || strcmp(value, "eject"))
- return;
-
- if (libxl__xs_printf(gc, XBT_NULL, wpath, "")) {
- LIBXL__EVENT_DISASTER(egc, "xs_write failed acknowledging eject",
- errno, LIBXL_EVENT_TYPE_DISK_EJECT);
- return;
- }
-
- libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
- libxl_device_disk *disk = &ev->u.disk_eject.disk;
-
- rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
- if (rc) {
- LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
- errno, LIBXL_EVENT_TYPE_DISK_EJECT);
- return;
- }
- if (!backend) {
- /* device has been removed, not simply ejected */
- return;
- }
-
- sscanf(backend,
- "/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
- "[a-z]/%*d/%*d",
- &disk->backend_domid, backend_type);
- if (!strcmp(backend_type, "tap") || !strcmp(backend_type, "vbd")) {
- disk->backend = LIBXL_DISK_BACKEND_TAP;
- } else if (!strcmp(backend_type, "qdisk")) {
- disk->backend = LIBXL_DISK_BACKEND_QDISK;
- } else {
- disk->backend = LIBXL_DISK_BACKEND_UNKNOWN;
- }
-
- disk->pdev_path = strdup(""); /* xxx fixme malloc failure */
- disk->format = LIBXL_DISK_FORMAT_EMPTY;
- /* this value is returned to the user: do not free right away */
- disk->vdev = libxl__strdup(NOGC, evg->vdev);
- disk->removable = 1;
- disk->readwrite = 0;
- disk->is_cdrom = 1;
-
- libxl__event_occurred(egc, ev);
-}
-
-int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
- const char *vdev, libxl_ev_user user,
- libxl_evgen_disk_eject **evgen_out) {
- GC_INIT(ctx);
- CTX_LOCK;
- int rc;
- char *path;
- libxl_evgen_disk_eject *evg = NULL;
-
- evg = malloc(sizeof(*evg)); if (!evg) { rc = ERROR_NOMEM; goto out; }
- memset(evg, 0, sizeof(*evg));
- evg->user = user;
- evg->domid = guest_domid;
- LIBXL_LIST_INSERT_HEAD(&CTX->disk_eject_evgens, evg, entry);
-
- uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
-
- if (!domid)
- domid = guest_domid;
-
- int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
-
- path = GCSPRINTF("%s/device/vbd/%d/eject",
- libxl__xs_get_dompath(gc, domid),
- devid);
- if (!path) { rc = ERROR_NOMEM; goto out; }
-
- const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
- libxl__xs_libxl_path(gc, domid),
- devid);
- evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
-
- const char *configured_vdev;
- rc = libxl__xs_read_checked(gc, XBT_NULL,
- GCSPRINTF("%s/dev", libxl_path), &configured_vdev);
- if (rc) goto out;
-
- evg->vdev = libxl__strdup(NOGC, configured_vdev);
-
- rc = libxl__ev_xswatch_register(gc, &evg->watch,
- disk_eject_xswatch_callback, path);
- if (rc) goto out;
-
- *evgen_out = evg;
- CTX_UNLOCK;
- GC_FREE;
- return 0;
-
- out:
- if (evg)
- libxl__evdisable_disk_eject(gc, evg);
- CTX_UNLOCK;
- GC_FREE;
- return rc;
-}
-
-void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
- CTX_LOCK;
-
- LIBXL_LIST_REMOVE(evg, entry);
-
- if (libxl__ev_xswatch_isregistered(&evg->watch))
- libxl__ev_xswatch_deregister(gc, &evg->watch);
-
- free(evg->vdev);
- free(evg->be_ptr_path);
- free(evg);
-
- CTX_UNLOCK;
-}
-
-void libxl_evdisable_disk_eject(libxl_ctx *ctx, libxl_evgen_disk_eject *evg) {
- GC_INIT(ctx);
- libxl__evdisable_disk_eject(gc, evg);
- GC_FREE;
-}
-
/* Callbacks for libxl_domain_destroy */
static void domain_destroy_cb(libxl__egc *egc, libxl__domain_destroy_state *dds,
@@ -1948,1044 +1813,6 @@ int libxl__resolve_domid(libxl__gc *gc, const char *name, uint32_t *domid)
}
/******************************************************************************/
-
-int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk,
- uint32_t domid)
-{
- int rc;
-
- libxl_defbool_setdefault(&disk->discard_enable, !!disk->readwrite);
- libxl_defbool_setdefault(&disk->colo_enable, false);
- libxl_defbool_setdefault(&disk->colo_restore_enable, false);
-
- rc = libxl__resolve_domid(gc, disk->backend_domname, &disk->backend_domid);
- if (rc < 0) return rc;
-
- /* Force Qdisk backend for CDROM devices of guests with a device model. */
- if (disk->is_cdrom != 0 &&
- libxl__domain_type(gc, domid) == LIBXL_DOMAIN_TYPE_HVM &&
- libxl__device_model_version_running(gc, domid) !=
- LIBXL_DEVICE_MODEL_VERSION_NONE) {
- if (!(disk->backend == LIBXL_DISK_BACKEND_QDISK ||
- disk->backend == LIBXL_DISK_BACKEND_UNKNOWN)) {
- LOGD(ERROR, domid, "Backend for CD devices on HVM guests must be Qdisk");
- return ERROR_FAIL;
- }
- disk->backend = LIBXL_DISK_BACKEND_QDISK;
- }
-
- rc = libxl__device_disk_set_backend(gc, disk);
- return rc;
-}
-
-int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
- const libxl_device_disk *disk,
- libxl__device *device)
-{
- int devid;
-
- devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
- if (devid==-1) {
- LOGD(ERROR, domid, "Invalid or unsupported"" virtual disk identifier %s",
- disk->vdev);
- return ERROR_INVAL;
- }
-
- device->backend_domid = disk->backend_domid;
- device->backend_devid = devid;
-
- switch (disk->backend) {
- case LIBXL_DISK_BACKEND_PHY:
- device->backend_kind = LIBXL__DEVICE_KIND_VBD;
- break;
- case LIBXL_DISK_BACKEND_TAP:
- device->backend_kind = LIBXL__DEVICE_KIND_VBD;
- break;
- case LIBXL_DISK_BACKEND_QDISK:
- device->backend_kind = LIBXL__DEVICE_KIND_QDISK;
- break;
- default:
- LOGD(ERROR, domid, "Unrecognized disk backend type: %d",
- disk->backend);
- return ERROR_INVAL;
- }
-
- device->domid = domid;
- device->devid = devid;
- device->kind = LIBXL__DEVICE_KIND_VBD;
-
- return 0;
-}
-
-/* Specific function called directly only by local disk attach,
- * all other users should instead use the regular
- * libxl__device_disk_add wrapper
- *
- * The (optionally) passed function get_vdev will be used to
- * set the vdev the disk should be attached to. When it is set the caller
- * must also pass get_vdev_user, which will be passed to get_vdev.
- *
- * The passed get_vdev function is also in charge of printing
- * the corresponding error message when appropiate.
- */
-static void device_disk_add(libxl__egc *egc, uint32_t domid,
- libxl_device_disk *disk,
- libxl__ao_device *aodev,
- char *get_vdev(libxl__gc *, void *,
- xs_transaction_t),
- void *get_vdev_user)
-{
- STATE_AO_GC(aodev->ao);
- flexarray_t *front = NULL;
- flexarray_t *back = NULL;
- char *dev = NULL, *script;
- libxl__device *device;
- int rc;
- libxl_ctx *ctx = gc->owner;
- xs_transaction_t t = XBT_NULL;
- libxl_domain_config d_config;
- libxl_device_disk disk_saved;
- libxl__domain_userdata_lock *lock = NULL;
-
- libxl_domain_config_init(&d_config);
- libxl_device_disk_init(&disk_saved);
- libxl_device_disk_copy(ctx, &disk_saved, disk);
-
- libxl_domain_type type = libxl__domain_type(gc, domid);
- if (type == LIBXL_DOMAIN_TYPE_INVALID) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- /*
- * get_vdev != NULL -> local attach
- * get_vdev == NULL -> block attach
- *
- * We don't care about local attach state because it's only
- * intermediate state.
- */
- if (!get_vdev && aodev->update_json) {
- lock = libxl__lock_domain_userdata(gc, domid);
- if (!lock) {
- rc = ERROR_LOCK_FAIL;
- goto out;
- }
-
- rc = libxl__get_domain_configuration(gc, domid, &d_config);
- if (rc) goto out;
-
- DEVICE_ADD(disk, disks, domid, &disk_saved, COMPARE_DISK, &d_config);
-
- rc = libxl__dm_check_start(gc, &d_config, domid);
- if (rc) goto out;
- }
-
- for (;;) {
- rc = libxl__xs_transaction_start(gc, &t);
- if (rc) goto out;
-
- if (get_vdev) {
- assert(get_vdev_user);
- disk->vdev = get_vdev(gc, get_vdev_user, t);
- if (disk->vdev == NULL) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
-
- rc = libxl__device_disk_setdefault(gc, disk, domid);
- if (rc) goto out;
-
- front = flexarray_make(gc, 16, 1);
- back = flexarray_make(gc, 16, 1);
-
- GCNEW(device);
- rc = libxl__device_from_disk(gc, domid, disk, device);
- if (rc != 0) {
- LOGD(ERROR, domid, "Invalid or unsupported"" virtual disk identifier %s",
- disk->vdev);
- goto out;
- }
-
- rc = libxl__device_exists(gc, t, device);
- if (rc < 0) goto out;
- if (rc == 1) { /* already exists in xenstore */
- LOGD(ERROR, domid, "device already exists in xenstore");
- aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
- rc = ERROR_DEVICE_EXISTS;
- goto out;
- }
-
- switch (disk->backend) {
- case LIBXL_DISK_BACKEND_PHY:
- dev = disk->pdev_path;
-
- do_backend_phy:
- flexarray_append(back, "params");
- flexarray_append(back, dev);
-
- script = libxl__abs_path(gc, disk->script?: "block",
- libxl__xen_script_dir_path());
- flexarray_append_pair(back, "script", script);
-
- assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD);
- break;
-
- case LIBXL_DISK_BACKEND_TAP:
- if (dev == NULL) {
- dev = libxl__blktap_devpath(gc, disk->pdev_path,
- disk->format);
- if (!dev) {
- LOGD(ERROR, domid, "Failed to get blktap devpath for %p",
- disk->pdev_path);
- rc = ERROR_FAIL;
- goto out;
- }
- }
- flexarray_append(back, "tapdisk-params");
- flexarray_append(back, GCSPRINTF("%s:%s",
- libxl__device_disk_string_of_format(disk->format),
- disk->pdev_path));
-
- /* tap backends with scripts are rejected by
- * libxl__device_disk_set_backend */
- assert(!disk->script);
-
- /* now create a phy device to export the device to the guest */
- goto do_backend_phy;
- case LIBXL_DISK_BACKEND_QDISK:
- flexarray_append(back, "params");
- flexarray_append(back, GCSPRINTF("%s:%s",
- libxl__device_disk_string_of_format(disk->format), disk->pdev_path));
- if (libxl_defbool_val(disk->colo_enable)) {
- flexarray_append(back, "colo-host");
- flexarray_append(back, libxl__sprintf(gc, "%s", disk->colo_host));
- flexarray_append(back, "colo-port");
- flexarray_append(back, libxl__sprintf(gc, "%d", disk->colo_port));
- flexarray_append(back, "colo-export");
- flexarray_append(back, libxl__sprintf(gc, "%s", disk->colo_export));
- flexarray_append(back, "active-disk");
- flexarray_append(back, libxl__sprintf(gc, "%s", disk->active_disk));
- flexarray_append(back, "hidden-disk");
- flexarray_append(back, libxl__sprintf(gc, "%s", disk->hidden_disk));
- }
- assert(device->backend_kind == LIBXL__DEVICE_KIND_QDISK);
- break;
- default:
- LOGD(ERROR, domid, "Unrecognized disk backend type: %d",
- disk->backend);
- rc = ERROR_INVAL;
- goto out;
- }
-
- flexarray_append(back, "frontend-id");
- flexarray_append(back, GCSPRINTF("%d", domid));
- flexarray_append(back, "online");
- flexarray_append(back, "1");
- flexarray_append(back, "removable");
- flexarray_append(back, GCSPRINTF("%d", (disk->removable) ? 1 : 0));
- flexarray_append(back, "bootable");
- flexarray_append(back, GCSPRINTF("%d", 1));
- flexarray_append(back, "state");
- flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
- flexarray_append(back, "dev");
- flexarray_append(back, disk->vdev);
- flexarray_append(back, "type");
- flexarray_append(back, libxl__device_disk_string_of_backend(disk->backend));
- flexarray_append(back, "mode");
- flexarray_append(back, disk->readwrite ? "w" : "r");
- flexarray_append(back, "device-type");
- flexarray_append(back, disk->is_cdrom ? "cdrom" : "disk");
- if (disk->direct_io_safe) {
- flexarray_append(back, "direct-io-safe");
- flexarray_append(back, "1");
- }
- flexarray_append_pair(back, "discard-enable",
- libxl_defbool_val(disk->discard_enable) ?
- "1" : "0");
-
- flexarray_append(front, "backend-id");
- flexarray_append(front, GCSPRINTF("%d", disk->backend_domid));
- flexarray_append(front, "state");
- flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
- flexarray_append(front, "virtual-device");
- flexarray_append(front, GCSPRINTF("%d", device->devid));
- flexarray_append(front, "device-type");
- flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
-
- /*
- * Old PV kernel disk frontends before 2.6.26 rely on tool stack to
- * write disk native protocol to frontend node. Xend does this, port
- * this behaviour to xl.
- *
- * New kernels write this node themselves. In that case it just
- * overwrites an existing node which is OK.
- */
- if (type == LIBXL_DOMAIN_TYPE_PV) {
- const char *protocol =
- xc_domain_get_native_protocol(ctx->xch, domid);
- if (protocol) {
- flexarray_append(front, "protocol");
- flexarray_append(front, libxl__strdup(gc, protocol));
- }
- }
-
- if (!get_vdev && aodev->update_json) {
- rc = libxl__set_domain_configuration(gc, domid, &d_config);
- if (rc) goto out;
- }
-
- libxl__device_generic_add(gc, t, device,
- libxl__xs_kvs_of_flexarray(gc, back),
- libxl__xs_kvs_of_flexarray(gc, front),
- NULL);
-
- rc = libxl__xs_transaction_commit(gc, &t);
- if (!rc) break;
- if (rc < 0) goto out;
- }
-
- aodev->dev = device;
- aodev->action = LIBXL__DEVICE_ACTION_ADD;
- libxl__wait_device_connection(egc, aodev);
-
- rc = 0;
-
-out:
- libxl__xs_transaction_abort(gc, &t);
- if (lock) libxl__unlock_domain_userdata(lock);
- libxl_device_disk_dispose(&disk_saved);
- libxl_domain_config_dispose(&d_config);
- aodev->rc = rc;
- if (rc) aodev->callback(egc, aodev);
- return;
-}
-
-static void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
- libxl_device_disk *disk,
- libxl__ao_device *aodev)
-{
- device_disk_add(egc, domid, disk, aodev, NULL, NULL);
-}
-
-static int libxl__device_disk_from_xenstore(libxl__gc *gc,
- const char *libxl_path,
- libxl_device_disk *disk)
-{
- libxl_ctx *ctx = libxl__gc_owner(gc);
- unsigned int len;
- char *tmp;
- int rc;
-
- libxl_device_disk_init(disk);
-
- const char *backend_path;
- rc = libxl__xs_read_checked(gc, XBT_NULL,
- GCSPRINTF("%s/backend", libxl_path),
- &backend_path);
- if (rc) goto out;
-
- if (!backend_path) {
- LOG(ERROR, "disk %s does not exist (no backend path", libxl_path);
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = libxl__backendpath_parse_domid(gc, backend_path, &disk->backend_domid);
- if (rc) {
- LOG(ERROR, "Unable to fetch device backend domid from %s", backend_path);
- goto out;
- }
-
- /*
- * "params" may not be present; but everything else must be.
- * colo releated entries(colo-host, colo-port, colo-export,
- * active-disk and hidden-disk) are present only if colo is
- * enabled.
- */
- tmp = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/params", libxl_path), &len);
- if (tmp && strchr(tmp, ':')) {
- disk->pdev_path = strdup(strchr(tmp, ':') + 1);
- free(tmp);
- } else {
- disk->pdev_path = tmp;
- }
-
- tmp = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/colo-host", libxl_path), &len);
- if (tmp) {
- libxl_defbool_set(&disk->colo_enable, true);
- disk->colo_host = tmp;
-
- tmp = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/colo-port", libxl_path), &len);
- if (!tmp) {
- LOG(ERROR, "Missing xenstore node %s/colo-port", libxl_path);
- goto cleanup;
- }
- disk->colo_port = atoi(tmp);
-
-#define XS_READ_COLO(param, item) do { \
- tmp = xs_read(ctx->xsh, XBT_NULL, \
- GCSPRINTF("%s/"#param"", libxl_path), &len); \
- if (!tmp) { \
- LOG(ERROR, "Missing xenstore node %s/"#param"", libxl_path); \
- goto cleanup; \
- } \
- disk->item = tmp; \
-} while (0)
- XS_READ_COLO(colo-export, colo_export);
- XS_READ_COLO(active-disk, active_disk);
- XS_READ_COLO(hidden-disk, hidden_disk);
-#undef XS_READ_COLO
- } else {
- libxl_defbool_set(&disk->colo_enable, false);
- }
-
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/type", libxl_path));
- if (!tmp) {
- LOG(ERROR, "Missing xenstore node %s/type", libxl_path);
- goto cleanup;
- }
- libxl_string_to_backend(ctx, tmp, &(disk->backend));
-
- disk->vdev = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/dev", libxl_path), &len);
- if (!disk->vdev) {
- LOG(ERROR, "Missing xenstore node %s/dev", libxl_path);
- goto cleanup;
- }
-
- tmp = libxl__xs_read(gc, XBT_NULL, libxl__sprintf
- (gc, "%s/removable", libxl_path));
- if (!tmp) {
- LOG(ERROR, "Missing xenstore node %s/removable", libxl_path);
- goto cleanup;
- }
- disk->removable = atoi(tmp);
-
- tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/mode", libxl_path));
- if (!tmp) {
- LOG(ERROR, "Missing xenstore node %s/mode", libxl_path);
- goto cleanup;
- }
- if (!strcmp(tmp, "w"))
- disk->readwrite = 1;
- else
- disk->readwrite = 0;
-
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/device-type", libxl_path));
- if (!tmp) {
- LOG(ERROR, "Missing xenstore node %s/device-type", libxl_path);
- goto cleanup;
- }
- disk->is_cdrom = !strcmp(tmp, "cdrom");
-
- disk->format = LIBXL_DISK_FORMAT_UNKNOWN;
-
- return 0;
-cleanup:
- rc = ERROR_FAIL;
- out:
- libxl_device_disk_dispose(disk);
- return rc;
-}
-
-int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid,
- const char *vdev, libxl_device_disk *disk)
-{
- GC_INIT(ctx);
- char *dom_xl_path, *libxl_path;
- int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
- int rc = ERROR_FAIL;
-
- if (devid < 0)
- return ERROR_INVAL;
-
- libxl_device_disk_init(disk);
-
- dom_xl_path = libxl__xs_libxl_path(gc, domid);
- if (!dom_xl_path) {
- goto out;
- }
- libxl_path = GCSPRINTF("%s/device/vbd/%d", dom_xl_path, devid);
-
- rc = libxl__device_disk_from_xenstore(gc, libxl_path, disk);
-out:
- GC_FREE;
- return rc;
-}
-
-static int libxl__append_disk_list(libxl__gc *gc,
- uint32_t domid,
- libxl_device_disk **disks,
- int *ndisks)
-{
- char *libxl_dir_path = NULL;
- char **dir = NULL;
- unsigned int n = 0;
- libxl_device_disk *pdisk = NULL, *pdisk_end = NULL;
- int rc=0;
- int initial_disks = *ndisks;
-
- libxl_dir_path = GCSPRINTF("%s/device/vbd",
- libxl__xs_libxl_path(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n);
- if (dir && n) {
- libxl_device_disk *tmp;
- tmp = realloc(*disks, sizeof (libxl_device_disk) * (*ndisks + n));
- if (tmp == NULL)
- return ERROR_NOMEM;
- *disks = tmp;
- pdisk = *disks + initial_disks;
- pdisk_end = *disks + initial_disks + n;
- for (; pdisk < pdisk_end; pdisk++, dir++) {
- const char *p;
- p = GCSPRINTF("%s/%s", libxl_dir_path, *dir);
- if ((rc=libxl__device_disk_from_xenstore(gc, p, pdisk)))
- goto out;
- *ndisks += 1;
- }
- }
-out:
- return rc;
-}
-
-libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num)
-{
- GC_INIT(ctx);
- libxl_device_disk *disks = NULL;
- int rc;
-
- *num = 0;
-
- rc = libxl__append_disk_list(gc, domid, &disks, num);
- if (rc) goto out_err;
-
- GC_FREE;
- return disks;
-
-out_err:
- LOG(ERROR, "Unable to list disks");
- while (disks && *num) {
- (*num)--;
- libxl_device_disk_dispose(&disks[*num]);
- }
- free(disks);
- return NULL;
-}
-
-int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
- libxl_device_disk *disk, libxl_diskinfo *diskinfo)
-{
- GC_INIT(ctx);
- char *dompath, *fe_path, *libxl_path;
- char *val;
- int rc;
-
- diskinfo->backend = NULL;
-
- dompath = libxl__xs_get_dompath(gc, domid);
- diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
-
- /* tap devices entries in xenstore are written as vbd devices. */
- fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
- libxl_path = GCSPRINTF("%s/device/vbd/%d",
- libxl__xs_libxl_path(gc, domid), diskinfo->devid);
- diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", libxl_path), NULL);
- if (!diskinfo->backend) {
- GC_FREE;
- return ERROR_FAIL;
- }
- rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
- &diskinfo->backend_id);
- if (rc) goto out;
-
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
- diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
- diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
- diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
- diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/frontend", libxl_path), NULL);
- diskinfo->frontend_id = domid;
-
- GC_FREE;
- return 0;
-
- out:
- free(diskinfo->backend);
- return rc;
-}
-
-int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
- const libxl_asyncop_how *ao_how)
-{
- AO_CREATE(ctx, domid, ao_how);
- int num = 0, i;
- libxl_device_disk *disks = NULL, disk_saved, disk_empty;
- libxl_domain_config d_config;
- int rc, dm_ver;
- libxl__device device;
- const char *be_path, *libxl_path;
- char * tmp;
- libxl__domain_userdata_lock *lock = NULL;
- xs_transaction_t t = XBT_NULL;
- flexarray_t *insert = NULL, *empty = NULL;
-
- libxl_domain_config_init(&d_config);
- libxl_device_disk_init(&disk_empty);
- libxl_device_disk_init(&disk_saved);
- libxl_device_disk_copy(ctx, &disk_saved, disk);
-
- disk_empty.format = LIBXL_DISK_FORMAT_EMPTY;
- disk_empty.vdev = libxl__strdup(NOGC, disk->vdev);
- disk_empty.pdev_path = libxl__strdup(NOGC, "");
- disk_empty.is_cdrom = 1;
- libxl__device_disk_setdefault(gc, &disk_empty, domid);
-
- libxl_domain_type type = libxl__domain_type(gc, domid);
- if (type == LIBXL_DOMAIN_TYPE_INVALID) {
- rc = ERROR_FAIL;
- goto out;
- }
- if (type != LIBXL_DOMAIN_TYPE_HVM) {
- LOGD(ERROR, domid, "cdrom-insert requires an HVM domain");
- rc = ERROR_INVAL;
- goto out;
- }
-
- if (libxl_get_stubdom_id(ctx, domid) != 0) {
- LOGD(ERROR, domid, "cdrom-insert doesn't work for stub domains");
- rc = ERROR_INVAL;
- goto out;
- }
-
- dm_ver = libxl__device_model_version_running(gc, domid);
- if (dm_ver == -1) {
- LOGD(ERROR, domid, "Cannot determine device model version");
- rc = ERROR_FAIL;
- goto out;
- }
-
- if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_NONE) {
- LOGD(ERROR, domid, "Guests without a device model cannot use cd-insert");
- rc = ERROR_FAIL;
- goto out;
- }
-
- disks = libxl_device_disk_list(ctx, domid, &num);
- for (i = 0; i < num; i++) {
- if (disks[i].is_cdrom && !strcmp(disk->vdev, disks[i].vdev))
- {
- /* Found. Set backend type appropriately. */
- disk->backend=disks[i].backend;
- break;
- }
- }
- if (i == num) {
- LOGD(ERROR, domid, "Virtual device not found");
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = libxl__device_disk_setdefault(gc, disk, domid);
- if (rc) goto out;
-
- if (!disk->pdev_path) {
- disk->pdev_path = libxl__strdup(NOGC, "");
- disk->format = LIBXL_DISK_FORMAT_EMPTY;
- }
-
- rc = libxl__device_from_disk(gc, domid, disk, &device);
- if (rc) goto out;
-
- be_path = libxl__device_backend_path(gc, &device);
- libxl_path = libxl__device_libxl_path(gc, &device);
-
- insert = flexarray_make(gc, 4, 1);
-
- flexarray_append_pair(insert, "type",
- libxl__device_disk_string_of_backend(disk->backend));
- if (disk->format != LIBXL_DISK_FORMAT_EMPTY)
- flexarray_append_pair(insert, "params",
- GCSPRINTF("%s:%s",
- libxl__device_disk_string_of_format(disk->format),
- disk->pdev_path));
- else
- flexarray_append_pair(insert, "params", "");
-
- empty = flexarray_make(gc, 4, 1);
- flexarray_append_pair(empty, "type",
- libxl__device_disk_string_of_backend(disk->backend));
- flexarray_append_pair(empty, "params", "");
-
- /* Note: CTX lock is already held at this point so lock hierarchy
- * is maintained.
- */
- lock = libxl__lock_domain_userdata(gc, domid);
- if (!lock) {
- rc = ERROR_LOCK_FAIL;
- goto out;
- }
-
- /* We need to eject the original image first. This is implemented
- * by inserting empty media. JSON is not updated.
- */
- if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
- rc = libxl__qmp_insert_cdrom(gc, domid, &disk_empty);
- if (rc) goto out;
- }
-
- for (;;) {
- rc = libxl__xs_transaction_start(gc, &t);
- if (rc) goto out;
- /* Sanity check: make sure the device exists before writing here */
- tmp = libxl__xs_read(gc, t, GCSPRINTF("%s/frontend", libxl_path));
- if (!tmp)
- {
- LOGD(ERROR, domid, "Internal error: %s does not exist",
- GCSPRINTF("%s/frontend", libxl_path));
- rc = ERROR_FAIL;
- goto out;
- }
-
- char **kvs = libxl__xs_kvs_of_flexarray(gc, empty);
-
- rc = libxl__xs_writev(gc, t, be_path, kvs);
- if (rc) goto out;
-
- rc = libxl__xs_writev(gc, t, libxl_path, kvs);
- if (rc) goto out;
-
- rc = libxl__xs_transaction_commit(gc, &t);
- if (!rc) break;
- if (rc < 0) goto out;
- }
-
- rc = libxl__get_domain_configuration(gc, domid, &d_config);
- if (rc) goto out;
-
- DEVICE_ADD(disk, disks, domid, &disk_saved, COMPARE_DISK, &d_config);
-
- rc = libxl__dm_check_start(gc, &d_config, domid);
- if (rc) goto out;
-
- if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
- rc = libxl__qmp_insert_cdrom(gc, domid, disk);
- if (rc) goto out;
- }
-
- for (;;) {
- rc = libxl__xs_transaction_start(gc, &t);
- if (rc) goto out;
- /* Sanity check: make sure the device exists before writing here */
- tmp = libxl__xs_read(gc, t, GCSPRINTF("%s/frontend", libxl_path));
- if (!tmp)
- {
- LOGD(ERROR, domid, "Internal error: %s does not exist",
- GCSPRINTF("%s/frontend", libxl_path));
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = libxl__set_domain_configuration(gc, domid, &d_config);
- if (rc) goto out;
-
- char **kvs = libxl__xs_kvs_of_flexarray(gc, insert);
-
- rc = libxl__xs_writev(gc, t, be_path, kvs);
- if (rc) goto out;
-
- rc = libxl__xs_writev(gc, t, libxl_path, kvs);
- if (rc) goto out;
-
- rc = libxl__xs_transaction_commit(gc, &t);
- if (!rc) break;
- if (rc < 0) goto out;
- }
-
- /* success, no actual async */
- libxl__ao_complete(egc, ao, 0);
-
- rc = 0;
-
-out:
- libxl__xs_transaction_abort(gc, &t);
- for (i = 0; i < num; i++)
- libxl_device_disk_dispose(&disks[i]);
- free(disks);
- libxl_device_disk_dispose(&disk_empty);
- libxl_device_disk_dispose(&disk_saved);
- libxl_domain_config_dispose(&d_config);
-
- if (lock) libxl__unlock_domain_userdata(lock);
-
- if (rc) return AO_CREATE_FAIL(rc);
- return AO_INPROGRESS;
-}
-
-/* libxl__alloc_vdev only works on the local domain, that is the domain
- * where the toolstack is running */
-static char * libxl__alloc_vdev(libxl__gc *gc, void *get_vdev_user,
- xs_transaction_t t)
-{
- const char *blkdev_start = (const char *) get_vdev_user;
- int devid = 0, disk = 0, part = 0;
- char *libxl_dom_path = libxl__xs_libxl_path(gc, LIBXL_TOOLSTACK_DOMID);
-
- libxl__device_disk_dev_number(blkdev_start, &disk, &part);
- if (part != 0) {
- LOG(ERROR, "blkdev_start is invalid");
- return NULL;
- }
-
- do {
- devid = libxl__device_disk_dev_number(GCSPRINTF("d%dp0", disk),
- NULL, NULL);
- if (devid < 0)
- return NULL;
- if (libxl__xs_read(gc, t,
- GCSPRINTF("%s/device/vbd/%d/backend",
- libxl_dom_path, devid)) == NULL) {
- if (errno == ENOENT)
- return libxl__devid_to_vdev(gc, devid);
- else
- return NULL;
- }
- disk++;
- } while (1);
- return NULL;
-}
-
-/* Callbacks */
-
-char *libxl__device_disk_find_local_path(libxl__gc *gc,
- libxl_domid guest_domid,
- const libxl_device_disk *disk,
- bool qdisk_direct)
-{
- char *path = NULL;
-
- /* No local paths for driver domains */
- if (disk->backend_domname != NULL) {
- LOG(DEBUG, "Non-local backend, can't access locally.\n");
- goto out;
- }
-
- /*
- * If this is in raw format, and we're not using a script or a
- * driver domain, we can access the target path directly.
- */
- if (disk->format == LIBXL_DISK_FORMAT_RAW
- && disk->script == NULL) {
- path = libxl__strdup(gc, disk->pdev_path);
- LOG(DEBUG, "Directly accessing local RAW disk %s", path);
- goto out;
- }
-
- /*
- * If we're being called for a qemu path, we can pass the target
- * string directly as well
- */
- if (qdisk_direct && disk->backend == LIBXL_DISK_BACKEND_QDISK) {
- path = libxl__strdup(gc, disk->pdev_path);
- LOG(DEBUG, "Directly accessing local QDISK target %s", path);
- goto out;
- }
-
- /*
- * If the format isn't raw and / or we're using a script, then see
- * if the script has written a path to the "cooked" node
- */
- if (disk->script && guest_domid != INVALID_DOMID) {
- libxl__device device;
- char *be_path, *pdpath;
- int rc;
-
- LOGD(DEBUG, guest_domid,
- "Run from a script; checking for physical-device-path (vdev %s)",
- disk->vdev);
-
- rc = libxl__device_from_disk(gc, guest_domid, disk, &device);
- if (rc < 0)
- goto out;
-
- be_path = libxl__device_backend_path(gc, &device);
-
- pdpath = libxl__sprintf(gc, "%s/physical-device-path", be_path);
-
- LOGD(DEBUG, guest_domid, "Attempting to read node %s", pdpath);
- path = libxl__xs_read(gc, XBT_NULL, pdpath);
-
- if (path)
- LOGD(DEBUG, guest_domid, "Accessing cooked block device %s", path);
- else
- LOGD(DEBUG, guest_domid, "No physical-device-path, can't access locally.");
-
- goto out;
- }
-
- out:
- return path;
-}
-
-static void local_device_attach_cb(libxl__egc *egc, libxl__ao_device *aodev);
-
-void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
- libxl__disk_local_state *dls)
-{
- STATE_AO_GC(dls->ao);
- int rc;
- const libxl_device_disk *in_disk = dls->in_disk;
- libxl_device_disk *disk = &dls->disk;
- const char *blkdev_start = dls->blkdev_start;
-
- assert(in_disk->pdev_path);
-
- disk->vdev = NULL;
-
- if (dls->diskpath)
- LOG(DEBUG, "Strange, dls->diskpath already set: %s", dls->diskpath);
-
- LOG(DEBUG, "Trying to find local path");
-
- dls->diskpath = libxl__device_disk_find_local_path(gc, INVALID_DOMID,
- in_disk, false);
- if (dls->diskpath) {
- LOG(DEBUG, "Local path found, executing callback.");
- dls->callback(egc, dls, 0);
- } else {
- LOG(DEBUG, "Local path not found, initiating attach.");
-
- memcpy(disk, in_disk, sizeof(libxl_device_disk));
- disk->pdev_path = libxl__strdup(gc, in_disk->pdev_path);
- if (in_disk->script != NULL)
- disk->script = libxl__strdup(gc, in_disk->script);
- disk->vdev = NULL;
-
- rc = libxl__device_disk_setdefault(gc, disk, LIBXL_TOOLSTACK_DOMID);
- if (rc) goto out;
-
- libxl__prepare_ao_device(ao, &dls->aodev);
- dls->aodev.callback = local_device_attach_cb;
- device_disk_add(egc, LIBXL_TOOLSTACK_DOMID, disk, &dls->aodev,
- libxl__alloc_vdev, (void *) blkdev_start);
- }
-
- return;
-
- out:
- assert(rc);
- dls->rc = rc;
- libxl__device_disk_local_initiate_detach(egc, dls);
- dls->callback(egc, dls, rc);
-}
-
-static void local_device_attach_cb(libxl__egc *egc, libxl__ao_device *aodev)
-{
- STATE_AO_GC(aodev->ao);
- libxl__disk_local_state *dls = CONTAINER_OF(aodev, *dls, aodev);
- char *be_path = NULL;
- int rc;
- libxl__device device;
- libxl_device_disk *disk = &dls->disk;
-
- rc = aodev->rc;
- if (rc) {
- LOGE(ERROR, "unable locally attach device: %s", disk->pdev_path);
- goto out;
- }
-
- rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID, disk, &device);
- if (rc < 0)
- goto out;
- be_path = libxl__device_backend_path(gc, &device);
- rc = libxl__wait_for_backend(gc, be_path, GCSPRINTF("%d", XenbusStateConnected));
- if (rc < 0)
- goto out;
-
- dls->diskpath = GCSPRINTF("/dev/%s",
- libxl__devid_to_localdev(gc, device.devid));
- LOG(DEBUG, "locally attached disk %s", dls->diskpath);
-
- dls->callback(egc, dls, 0);
- return;
-
- out:
- assert(rc);
- dls->rc = rc;
- libxl__device_disk_local_initiate_detach(egc, dls);
- return;
-}
-
-/* Callbacks for local detach */
-
-static void local_device_detach_cb(libxl__egc *egc, libxl__ao_device *aodev);
-
-void libxl__device_disk_local_initiate_detach(libxl__egc *egc,
- libxl__disk_local_state *dls)
-{
- STATE_AO_GC(dls->ao);
- int rc = 0;
- libxl_device_disk *disk = &dls->disk;
- libxl__device *device;
- libxl__ao_device *aodev = &dls->aodev;
- libxl__prepare_ao_device(ao, aodev);
-
- if (!dls->diskpath) goto out;
-
- if (disk->vdev != NULL) {
- GCNEW(device);
- rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID,
- disk, device);
- if (rc != 0) goto out;
-
- aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
- aodev->dev = device;
- aodev->callback = local_device_detach_cb;
- aodev->force = 0;
- libxl__initiate_device_generic_remove(egc, aodev);
- return;
- }
-
-out:
- aodev->rc = rc;
- local_device_detach_cb(egc, aodev);
- return;
-}
-
-static void local_device_detach_cb(libxl__egc *egc, libxl__ao_device *aodev)
-{
- STATE_AO_GC(aodev->ao);
- libxl__disk_local_state *dls = CONTAINER_OF(aodev, *dls, aodev);
- int rc;
-
- if (aodev->rc) {
- LOGED(ERROR, aodev->dev->domid, "Unable to %s %s with id %u",
- libxl__device_action_to_string(aodev->action),
- libxl__device_kind_to_string(aodev->dev->kind),
- aodev->dev->devid);
- goto out;
- }
-
-out:
- /*
- * If there was an error in dls->rc, it means we have been called from
- * a failed execution of libxl__device_disk_local_initiate_attach,
- * so return the original error.
- */
- rc = dls->rc ? dls->rc : aodev->rc;
- dls->callback(egc, dls, rc);
- return;
-}
-
-/******************************************************************************/
int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
libxl__device_console *console,
libxl__domain_build_state *state,
@@ -3520,10 +2347,6 @@ out:
/******************************************************************************/
/* The following functions are defined:
- * libxl_device_disk_add
- * libxl__add_disks
- * libxl_device_disk_remove
- * libxl_device_disk_destroy
* libxl_device_vkb_remove
* libxl_device_vkb_destroy
* libxl_device_vfb_remove
@@ -3534,11 +2357,6 @@ out:
* 1. add support for secondary consoles to xenconsoled
* 2. dynamically add/remove qemu chardevs via qmp messages. */
-/* disk */
-LIBXL_DEFINE_DEVICE_ADD(disk)
-LIBXL_DEFINE_DEVICES_ADD(disk)
-LIBXL_DEFINE_DEVICE_REMOVE(disk)
-
/* vkb */
LIBXL_DEFINE_DEVICE_REMOVE(vkb)
@@ -5644,57 +4462,6 @@ out:
return rc;
}
-static int libxl_device_disk_compare(libxl_device_disk *d1,
- libxl_device_disk *d2)
-{
- return COMPARE_DISK(d1, d2);
-}
-
-/* Take care of removable device. We maintain invariant in the
- * insert / remove operation so that:
- * 1. if xenstore is "empty" while JSON is not, the result
- * is "empty"
- * 2. if xenstore has a different media than JSON, use the
- * one in JSON
- * 3. if xenstore and JSON have the same media, well, you
- * know the answer :-)
- *
- * Currently there is only one removable device -- CDROM.
- * Look for libxl_cdrom_insert for reference.
- */
-static void libxl_device_disk_merge(libxl_ctx *ctx, void *d1, void *d2)
-{
- GC_INIT(ctx);
- libxl_device_disk *src = d1;
- libxl_device_disk *dst = d2;
-
- if (src->removable) {
- if (!src->pdev_path || *src->pdev_path == '\0') {
- /* 1, no media in drive */
- free(dst->pdev_path);
- dst->pdev_path = libxl__strdup(NOGC, "");
- dst->format = LIBXL_DISK_FORMAT_EMPTY;
- } else {
- /* 2 and 3, use JSON, no need to touch anything */
- ;
- }
- }
-}
-
-static int libxl_device_disk_dm_needed(void *e, unsigned domid)
-{
- libxl_device_disk *elem = e;
-
- return elem->backend == LIBXL_DISK_BACKEND_QDISK &&
- elem->backend_domid == domid;
-}
-
-DEFINE_DEVICE_TYPE_STRUCT(disk,
- .merge = libxl_device_disk_merge,
- .dm_needed = libxl_device_disk_dm_needed,
- .skip_attach = 1
-);
-
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl_disk.c b/tools/libxl/libxl_disk.c
new file mode 100644
index 0000000..ac49df2
--- /dev/null
+++ b/tools/libxl/libxl_disk.c
@@ -0,0 +1,1258 @@
+/*
+ * 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"
+
+#define BACKEND_STRING_SIZE 5
+
+static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
+ const char *wpath, const char *epath) {
+ EGC_GC;
+ libxl_evgen_disk_eject *evg = (void*)w;
+ const char *backend;
+ char *value;
+ char backend_type[BACKEND_STRING_SIZE+1];
+ int rc;
+
+ value = libxl__xs_read(gc, XBT_NULL, wpath);
+
+ if (!value || strcmp(value, "eject"))
+ return;
+
+ if (libxl__xs_printf(gc, XBT_NULL, wpath, "")) {
+ LIBXL__EVENT_DISASTER(egc, "xs_write failed acknowledging eject",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+
+ libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
+ libxl_device_disk *disk = &ev->u.disk_eject.disk;
+
+ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
+ if (rc) {
+ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+ if (!backend) {
+ /* device has been removed, not simply ejected */
+ return;
+ }
+
+ sscanf(backend,
+ "/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
+ "[a-z]/%*d/%*d",
+ &disk->backend_domid, backend_type);
+ if (!strcmp(backend_type, "tap") || !strcmp(backend_type, "vbd")) {
+ disk->backend = LIBXL_DISK_BACKEND_TAP;
+ } else if (!strcmp(backend_type, "qdisk")) {
+ disk->backend = LIBXL_DISK_BACKEND_QDISK;
+ } else {
+ disk->backend = LIBXL_DISK_BACKEND_UNKNOWN;
+ }
+
+ disk->pdev_path = strdup(""); /* xxx fixme malloc failure */
+ disk->format = LIBXL_DISK_FORMAT_EMPTY;
+ /* this value is returned to the user: do not free right away */
+ disk->vdev = libxl__strdup(NOGC, evg->vdev);
+ disk->removable = 1;
+ disk->readwrite = 0;
+ disk->is_cdrom = 1;
+
+ libxl__event_occurred(egc, ev);
+}
+
+int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
+ const char *vdev, libxl_ev_user user,
+ libxl_evgen_disk_eject **evgen_out) {
+ GC_INIT(ctx);
+ CTX_LOCK;
+ int rc;
+ char *path;
+ libxl_evgen_disk_eject *evg = NULL;
+
+ evg = malloc(sizeof(*evg)); if (!evg) { rc = ERROR_NOMEM; goto out; }
+ memset(evg, 0, sizeof(*evg));
+ evg->user = user;
+ evg->domid = guest_domid;
+ LIBXL_LIST_INSERT_HEAD(&CTX->disk_eject_evgens, evg, entry);
+
+ uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
+
+ if (!domid)
+ domid = guest_domid;
+
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+
+ path = GCSPRINTF("%s/device/vbd/%d/eject",
+ libxl__xs_get_dompath(gc, domid),
+ devid);
+ if (!path) { rc = ERROR_NOMEM; goto out; }
+
+ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid),
+ devid);
+ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
+
+ const char *configured_vdev;
+ rc = libxl__xs_read_checked(gc, XBT_NULL,
+ GCSPRINTF("%s/dev", libxl_path), &configured_vdev);
+ if (rc) goto out;
+
+ evg->vdev = libxl__strdup(NOGC, configured_vdev);
+
+ rc = libxl__ev_xswatch_register(gc, &evg->watch,
+ disk_eject_xswatch_callback, path);
+ if (rc) goto out;
+
+ *evgen_out = evg;
+ CTX_UNLOCK;
+ GC_FREE;
+ return 0;
+
+ out:
+ if (evg)
+ libxl__evdisable_disk_eject(gc, evg);
+ CTX_UNLOCK;
+ GC_FREE;
+ return rc;
+}
+
+void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
+ CTX_LOCK;
+
+ LIBXL_LIST_REMOVE(evg, entry);
+
+ if (libxl__ev_xswatch_isregistered(&evg->watch))
+ libxl__ev_xswatch_deregister(gc, &evg->watch);
+
+ free(evg->vdev);
+ free(evg->be_ptr_path);
+ free(evg);
+
+ CTX_UNLOCK;
+}
+
+void libxl_evdisable_disk_eject(libxl_ctx *ctx, libxl_evgen_disk_eject *evg) {
+ GC_INIT(ctx);
+ libxl__evdisable_disk_eject(gc, evg);
+ GC_FREE;
+}
+
+int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk,
+ uint32_t domid)
+{
+ int rc;
+
+ libxl_defbool_setdefault(&disk->discard_enable, !!disk->readwrite);
+ libxl_defbool_setdefault(&disk->colo_enable, false);
+ libxl_defbool_setdefault(&disk->colo_restore_enable, false);
+
+ rc = libxl__resolve_domid(gc, disk->backend_domname, &disk->backend_domid);
+ if (rc < 0) return rc;
+
+ /* Force Qdisk backend for CDROM devices of guests with a device model. */
+ if (disk->is_cdrom != 0 &&
+ libxl__domain_type(gc, domid) == LIBXL_DOMAIN_TYPE_HVM &&
+ libxl__device_model_version_running(gc, domid) !=
+ LIBXL_DEVICE_MODEL_VERSION_NONE) {
+ if (!(disk->backend == LIBXL_DISK_BACKEND_QDISK ||
+ disk->backend == LIBXL_DISK_BACKEND_UNKNOWN)) {
+ LOGD(ERROR, domid, "Backend for CD devices on HVM guests must be Qdisk");
+ return ERROR_FAIL;
+ }
+ disk->backend = LIBXL_DISK_BACKEND_QDISK;
+ }
+
+ rc = libxl__device_disk_set_backend(gc, disk);
+ return rc;
+}
+
+int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
+ const libxl_device_disk *disk,
+ libxl__device *device)
+{
+ int devid;
+
+ devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
+ if (devid==-1) {
+ LOGD(ERROR, domid, "Invalid or unsupported"" virtual disk identifier %s",
+ disk->vdev);
+ return ERROR_INVAL;
+ }
+
+ device->backend_domid = disk->backend_domid;
+ device->backend_devid = devid;
+
+ switch (disk->backend) {
+ case LIBXL_DISK_BACKEND_PHY:
+ device->backend_kind = LIBXL__DEVICE_KIND_VBD;
+ break;
+ case LIBXL_DISK_BACKEND_TAP:
+ device->backend_kind = LIBXL__DEVICE_KIND_VBD;
+ break;
+ case LIBXL_DISK_BACKEND_QDISK:
+ device->backend_kind = LIBXL__DEVICE_KIND_QDISK;
+ break;
+ default:
+ LOGD(ERROR, domid, "Unrecognized disk backend type: %d",
+ disk->backend);
+ return ERROR_INVAL;
+ }
+
+ device->domid = domid;
+ device->devid = devid;
+ device->kind = LIBXL__DEVICE_KIND_VBD;
+
+ return 0;
+}
+
+/* Specific function called directly only by local disk attach,
+ * all other users should instead use the regular
+ * libxl__device_disk_add wrapper
+ *
+ * The (optionally) passed function get_vdev will be used to
+ * set the vdev the disk should be attached to. When it is set the caller
+ * must also pass get_vdev_user, which will be passed to get_vdev.
+ *
+ * The passed get_vdev function is also in charge of printing
+ * the corresponding error message when appropiate.
+ */
+static void device_disk_add(libxl__egc *egc, uint32_t domid,
+ libxl_device_disk *disk,
+ libxl__ao_device *aodev,
+ char *get_vdev(libxl__gc *, void *,
+ xs_transaction_t),
+ void *get_vdev_user)
+{
+ STATE_AO_GC(aodev->ao);
+ flexarray_t *front = NULL;
+ flexarray_t *back = NULL;
+ char *dev = NULL, *script;
+ libxl__device *device;
+ int rc;
+ libxl_ctx *ctx = gc->owner;
+ xs_transaction_t t = XBT_NULL;
+ libxl_domain_config d_config;
+ libxl_device_disk disk_saved;
+ libxl__domain_userdata_lock *lock = NULL;
+
+ libxl_domain_config_init(&d_config);
+ libxl_device_disk_init(&disk_saved);
+ libxl_device_disk_copy(ctx, &disk_saved, disk);
+
+ libxl_domain_type type = libxl__domain_type(gc, domid);
+ if (type == LIBXL_DOMAIN_TYPE_INVALID) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /*
+ * get_vdev != NULL -> local attach
+ * get_vdev == NULL -> block attach
+ *
+ * We don't care about local attach state because it's only
+ * intermediate state.
+ */
+ if (!get_vdev && aodev->update_json) {
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ DEVICE_ADD(disk, disks, domid, &disk_saved, COMPARE_DISK, &d_config);
+
+ rc = libxl__dm_check_start(gc, &d_config, domid);
+ if (rc) goto out;
+ }
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+
+ if (get_vdev) {
+ assert(get_vdev_user);
+ disk->vdev = get_vdev(gc, get_vdev_user, t);
+ if (disk->vdev == NULL) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ }
+
+ rc = libxl__device_disk_setdefault(gc, disk, domid);
+ if (rc) goto out;
+
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
+
+ GCNEW(device);
+ rc = libxl__device_from_disk(gc, domid, disk, device);
+ if (rc != 0) {
+ LOGD(ERROR, domid, "Invalid or unsupported"" virtual disk identifier %s",
+ disk->vdev);
+ goto out;
+ }
+
+ rc = libxl__device_exists(gc, t, device);
+ if (rc < 0) goto out;
+ if (rc == 1) { /* already exists in xenstore */
+ LOGD(ERROR, domid, "device already exists in xenstore");
+ aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+ rc = ERROR_DEVICE_EXISTS;
+ goto out;
+ }
+
+ switch (disk->backend) {
+ case LIBXL_DISK_BACKEND_PHY:
+ dev = disk->pdev_path;
+
+ do_backend_phy:
+ flexarray_append(back, "params");
+ flexarray_append(back, dev);
+
+ script = libxl__abs_path(gc, disk->script?: "block",
+ libxl__xen_script_dir_path());
+ flexarray_append_pair(back, "script", script);
+
+ assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD);
+ break;
+
+ case LIBXL_DISK_BACKEND_TAP:
+ if (dev == NULL) {
+ dev = libxl__blktap_devpath(gc, disk->pdev_path,
+ disk->format);
+ if (!dev) {
+ LOGD(ERROR, domid, "Failed to get blktap devpath for %p",
+ disk->pdev_path);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ }
+ flexarray_append(back, "tapdisk-params");
+ flexarray_append(back, GCSPRINTF("%s:%s",
+ libxl__device_disk_string_of_format(disk->format),
+ disk->pdev_path));
+
+ /* tap backends with scripts are rejected by
+ * libxl__device_disk_set_backend */
+ assert(!disk->script);
+
+ /* now create a phy device to export the device to the guest */
+ goto do_backend_phy;
+ case LIBXL_DISK_BACKEND_QDISK:
+ flexarray_append(back, "params");
+ flexarray_append(back, GCSPRINTF("%s:%s",
+ libxl__device_disk_string_of_format(disk->format), disk->pdev_path));
+ if (libxl_defbool_val(disk->colo_enable)) {
+ flexarray_append(back, "colo-host");
+ flexarray_append(back, libxl__sprintf(gc, "%s", disk->colo_host));
+ flexarray_append(back, "colo-port");
+ flexarray_append(back, libxl__sprintf(gc, "%d", disk->colo_port));
+ flexarray_append(back, "colo-export");
+ flexarray_append(back, libxl__sprintf(gc, "%s", disk->colo_export));
+ flexarray_append(back, "active-disk");
+ flexarray_append(back, libxl__sprintf(gc, "%s", disk->active_disk));
+ flexarray_append(back, "hidden-disk");
+ flexarray_append(back, libxl__sprintf(gc, "%s", disk->hidden_disk));
+ }
+ assert(device->backend_kind == LIBXL__DEVICE_KIND_QDISK);
+ break;
+ default:
+ LOGD(ERROR, domid, "Unrecognized disk backend type: %d",
+ disk->backend);
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ flexarray_append(back, "frontend-id");
+ flexarray_append(back, GCSPRINTF("%d", domid));
+ flexarray_append(back, "online");
+ flexarray_append(back, "1");
+ flexarray_append(back, "removable");
+ flexarray_append(back, GCSPRINTF("%d", (disk->removable) ? 1 : 0));
+ flexarray_append(back, "bootable");
+ flexarray_append(back, GCSPRINTF("%d", 1));
+ flexarray_append(back, "state");
+ flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
+ flexarray_append(back, "dev");
+ flexarray_append(back, disk->vdev);
+ flexarray_append(back, "type");
+ flexarray_append(back, libxl__device_disk_string_of_backend(disk->backend));
+ flexarray_append(back, "mode");
+ flexarray_append(back, disk->readwrite ? "w" : "r");
+ flexarray_append(back, "device-type");
+ flexarray_append(back, disk->is_cdrom ? "cdrom" : "disk");
+ if (disk->direct_io_safe) {
+ flexarray_append(back, "direct-io-safe");
+ flexarray_append(back, "1");
+ }
+ flexarray_append_pair(back, "discard-enable",
+ libxl_defbool_val(disk->discard_enable) ?
+ "1" : "0");
+
+ flexarray_append(front, "backend-id");
+ flexarray_append(front, GCSPRINTF("%d", disk->backend_domid));
+ flexarray_append(front, "state");
+ flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
+ flexarray_append(front, "virtual-device");
+ flexarray_append(front, GCSPRINTF("%d", device->devid));
+ flexarray_append(front, "device-type");
+ flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
+
+ /*
+ * Old PV kernel disk frontends before 2.6.26 rely on tool stack to
+ * write disk native protocol to frontend node. Xend does this, port
+ * this behaviour to xl.
+ *
+ * New kernels write this node themselves. In that case it just
+ * overwrites an existing node which is OK.
+ */
+ if (type == LIBXL_DOMAIN_TYPE_PV) {
+ const char *protocol =
+ xc_domain_get_native_protocol(ctx->xch, domid);
+ if (protocol) {
+ flexarray_append(front, "protocol");
+ flexarray_append(front, libxl__strdup(gc, protocol));
+ }
+ }
+
+ if (!get_vdev && aodev->update_json) {
+ rc = libxl__set_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+ }
+
+ libxl__device_generic_add(gc, t, device,
+ libxl__xs_kvs_of_flexarray(gc, back),
+ libxl__xs_kvs_of_flexarray(gc, front),
+ NULL);
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
+
+ aodev->dev = device;
+ aodev->action = LIBXL__DEVICE_ACTION_ADD;
+ libxl__wait_device_connection(egc, aodev);
+
+ rc = 0;
+
+out:
+ libxl__xs_transaction_abort(gc, &t);
+ if (lock) libxl__unlock_domain_userdata(lock);
+ libxl_device_disk_dispose(&disk_saved);
+ libxl_domain_config_dispose(&d_config);
+ aodev->rc = rc;
+ if (rc) aodev->callback(egc, aodev);
+ return;
+}
+
+static void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
+ libxl_device_disk *disk,
+ libxl__ao_device *aodev)
+{
+ device_disk_add(egc, domid, disk, aodev, NULL, NULL);
+}
+
+static int libxl__device_disk_from_xenstore(libxl__gc *gc,
+ const char *libxl_path,
+ libxl_device_disk *disk)
+{
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ unsigned int len;
+ char *tmp;
+ int rc;
+
+ libxl_device_disk_init(disk);
+
+ const char *backend_path;
+ rc = libxl__xs_read_checked(gc, XBT_NULL,
+ GCSPRINTF("%s/backend", libxl_path),
+ &backend_path);
+ if (rc) goto out;
+
+ if (!backend_path) {
+ LOG(ERROR, "disk %s does not exist (no backend path", libxl_path);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = libxl__backendpath_parse_domid(gc, backend_path, &disk->backend_domid);
+ if (rc) {
+ LOG(ERROR, "Unable to fetch device backend domid from %s", backend_path);
+ goto out;
+ }
+
+ /*
+ * "params" may not be present; but everything else must be.
+ * colo releated entries(colo-host, colo-port, colo-export,
+ * active-disk and hidden-disk) are present only if colo is
+ * enabled.
+ */
+ tmp = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/params", libxl_path), &len);
+ if (tmp && strchr(tmp, ':')) {
+ disk->pdev_path = strdup(strchr(tmp, ':') + 1);
+ free(tmp);
+ } else {
+ disk->pdev_path = tmp;
+ }
+
+ tmp = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/colo-host", libxl_path), &len);
+ if (tmp) {
+ libxl_defbool_set(&disk->colo_enable, true);
+ disk->colo_host = tmp;
+
+ tmp = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/colo-port", libxl_path), &len);
+ if (!tmp) {
+ LOG(ERROR, "Missing xenstore node %s/colo-port", libxl_path);
+ goto cleanup;
+ }
+ disk->colo_port = atoi(tmp);
+
+#define XS_READ_COLO(param, item) do { \
+ tmp = xs_read(ctx->xsh, XBT_NULL, \
+ GCSPRINTF("%s/"#param"", libxl_path), &len); \
+ if (!tmp) { \
+ LOG(ERROR, "Missing xenstore node %s/"#param"", libxl_path); \
+ goto cleanup; \
+ } \
+ disk->item = tmp; \
+} while (0)
+ XS_READ_COLO(colo-export, colo_export);
+ XS_READ_COLO(active-disk, active_disk);
+ XS_READ_COLO(hidden-disk, hidden_disk);
+#undef XS_READ_COLO
+ } else {
+ libxl_defbool_set(&disk->colo_enable, false);
+ }
+
+ tmp = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF("%s/type", libxl_path));
+ if (!tmp) {
+ LOG(ERROR, "Missing xenstore node %s/type", libxl_path);
+ goto cleanup;
+ }
+ libxl_string_to_backend(ctx, tmp, &(disk->backend));
+
+ disk->vdev = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/dev", libxl_path), &len);
+ if (!disk->vdev) {
+ LOG(ERROR, "Missing xenstore node %s/dev", libxl_path);
+ goto cleanup;
+ }
+
+ tmp = libxl__xs_read(gc, XBT_NULL, libxl__sprintf
+ (gc, "%s/removable", libxl_path));
+ if (!tmp) {
+ LOG(ERROR, "Missing xenstore node %s/removable", libxl_path);
+ goto cleanup;
+ }
+ disk->removable = atoi(tmp);
+
+ tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/mode", libxl_path));
+ if (!tmp) {
+ LOG(ERROR, "Missing xenstore node %s/mode", libxl_path);
+ goto cleanup;
+ }
+ if (!strcmp(tmp, "w"))
+ disk->readwrite = 1;
+ else
+ disk->readwrite = 0;
+
+ tmp = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF("%s/device-type", libxl_path));
+ if (!tmp) {
+ LOG(ERROR, "Missing xenstore node %s/device-type", libxl_path);
+ goto cleanup;
+ }
+ disk->is_cdrom = !strcmp(tmp, "cdrom");
+
+ disk->format = LIBXL_DISK_FORMAT_UNKNOWN;
+
+ return 0;
+cleanup:
+ rc = ERROR_FAIL;
+ out:
+ libxl_device_disk_dispose(disk);
+ return rc;
+}
+
+int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid,
+ const char *vdev, libxl_device_disk *disk)
+{
+ GC_INIT(ctx);
+ char *dom_xl_path, *libxl_path;
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+ int rc = ERROR_FAIL;
+
+ if (devid < 0)
+ return ERROR_INVAL;
+
+ libxl_device_disk_init(disk);
+
+ dom_xl_path = libxl__xs_libxl_path(gc, domid);
+ if (!dom_xl_path) {
+ goto out;
+ }
+ libxl_path = GCSPRINTF("%s/device/vbd/%d", dom_xl_path, devid);
+
+ rc = libxl__device_disk_from_xenstore(gc, libxl_path, disk);
+out:
+ GC_FREE;
+ return rc;
+}
+
+static int libxl__append_disk_list(libxl__gc *gc,
+ uint32_t domid,
+ libxl_device_disk **disks,
+ int *ndisks)
+{
+ char *libxl_dir_path = NULL;
+ char **dir = NULL;
+ unsigned int n = 0;
+ libxl_device_disk *pdisk = NULL, *pdisk_end = NULL;
+ int rc=0;
+ int initial_disks = *ndisks;
+
+ libxl_dir_path = GCSPRINTF("%s/device/vbd",
+ libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n);
+ if (dir && n) {
+ libxl_device_disk *tmp;
+ tmp = realloc(*disks, sizeof (libxl_device_disk) * (*ndisks + n));
+ if (tmp == NULL)
+ return ERROR_NOMEM;
+ *disks = tmp;
+ pdisk = *disks + initial_disks;
+ pdisk_end = *disks + initial_disks + n;
+ for (; pdisk < pdisk_end; pdisk++, dir++) {
+ const char *p;
+ p = GCSPRINTF("%s/%s", libxl_dir_path, *dir);
+ if ((rc=libxl__device_disk_from_xenstore(gc, p, pdisk)))
+ goto out;
+ *ndisks += 1;
+ }
+ }
+out:
+ return rc;
+}
+
+libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+ GC_INIT(ctx);
+ libxl_device_disk *disks = NULL;
+ int rc;
+
+ *num = 0;
+
+ rc = libxl__append_disk_list(gc, domid, &disks, num);
+ if (rc) goto out_err;
+
+ GC_FREE;
+ return disks;
+
+out_err:
+ LOG(ERROR, "Unable to list disks");
+ while (disks && *num) {
+ (*num)--;
+ libxl_device_disk_dispose(&disks[*num]);
+ }
+ free(disks);
+ return NULL;
+}
+
+int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_disk *disk, libxl_diskinfo *diskinfo)
+{
+ GC_INIT(ctx);
+ char *dompath, *fe_path, *libxl_path;
+ char *val;
+ int rc;
+
+ diskinfo->backend = NULL;
+
+ dompath = libxl__xs_get_dompath(gc, domid);
+ diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
+
+ /* tap devices entries in xenstore are written as vbd devices. */
+ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid), diskinfo->devid);
+ diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/backend", libxl_path), NULL);
+ if (!diskinfo->backend) {
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
+ &diskinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
+ diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
+ diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
+ diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
+ diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/frontend", libxl_path), NULL);
+ diskinfo->frontend_id = domid;
+
+ GC_FREE;
+ return 0;
+
+ out:
+ free(diskinfo->backend);
+ return rc;
+}
+
+int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ int num = 0, i;
+ libxl_device_disk *disks = NULL, disk_saved, disk_empty;
+ libxl_domain_config d_config;
+ int rc, dm_ver;
+ libxl__device device;
+ const char *be_path, *libxl_path;
+ char * tmp;
+ libxl__domain_userdata_lock *lock = NULL;
+ xs_transaction_t t = XBT_NULL;
+ flexarray_t *insert = NULL, *empty = NULL;
+
+ libxl_domain_config_init(&d_config);
+ libxl_device_disk_init(&disk_empty);
+ libxl_device_disk_init(&disk_saved);
+ libxl_device_disk_copy(ctx, &disk_saved, disk);
+
+ disk_empty.format = LIBXL_DISK_FORMAT_EMPTY;
+ disk_empty.vdev = libxl__strdup(NOGC, disk->vdev);
+ disk_empty.pdev_path = libxl__strdup(NOGC, "");
+ disk_empty.is_cdrom = 1;
+ libxl__device_disk_setdefault(gc, &disk_empty, domid);
+
+ libxl_domain_type type = libxl__domain_type(gc, domid);
+ if (type == LIBXL_DOMAIN_TYPE_INVALID) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ if (type != LIBXL_DOMAIN_TYPE_HVM) {
+ LOGD(ERROR, domid, "cdrom-insert requires an HVM domain");
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ if (libxl_get_stubdom_id(ctx, domid) != 0) {
+ LOGD(ERROR, domid, "cdrom-insert doesn't work for stub domains");
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ dm_ver = libxl__device_model_version_running(gc, domid);
+ if (dm_ver == -1) {
+ LOGD(ERROR, domid, "Cannot determine device model version");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_NONE) {
+ LOGD(ERROR, domid, "Guests without a device model cannot use cd-insert");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ disks = libxl_device_disk_list(ctx, domid, &num);
+ for (i = 0; i < num; i++) {
+ if (disks[i].is_cdrom && !strcmp(disk->vdev, disks[i].vdev))
+ {
+ /* Found. Set backend type appropriately. */
+ disk->backend=disks[i].backend;
+ break;
+ }
+ }
+ if (i == num) {
+ LOGD(ERROR, domid, "Virtual device not found");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = libxl__device_disk_setdefault(gc, disk, domid);
+ if (rc) goto out;
+
+ if (!disk->pdev_path) {
+ disk->pdev_path = libxl__strdup(NOGC, "");
+ disk->format = LIBXL_DISK_FORMAT_EMPTY;
+ }
+
+ rc = libxl__device_from_disk(gc, domid, disk, &device);
+ if (rc) goto out;
+
+ be_path = libxl__device_backend_path(gc, &device);
+ libxl_path = libxl__device_libxl_path(gc, &device);
+
+ insert = flexarray_make(gc, 4, 1);
+
+ flexarray_append_pair(insert, "type",
+ libxl__device_disk_string_of_backend(disk->backend));
+ if (disk->format != LIBXL_DISK_FORMAT_EMPTY)
+ flexarray_append_pair(insert, "params",
+ GCSPRINTF("%s:%s",
+ libxl__device_disk_string_of_format(disk->format),
+ disk->pdev_path));
+ else
+ flexarray_append_pair(insert, "params", "");
+
+ empty = flexarray_make(gc, 4, 1);
+ flexarray_append_pair(empty, "type",
+ libxl__device_disk_string_of_backend(disk->backend));
+ flexarray_append_pair(empty, "params", "");
+
+ /* Note: CTX lock is already held at this point so lock hierarchy
+ * is maintained.
+ */
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ /* We need to eject the original image first. This is implemented
+ * by inserting empty media. JSON is not updated.
+ */
+ if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+ rc = libxl__qmp_insert_cdrom(gc, domid, &disk_empty);
+ if (rc) goto out;
+ }
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+ /* Sanity check: make sure the device exists before writing here */
+ tmp = libxl__xs_read(gc, t, GCSPRINTF("%s/frontend", libxl_path));
+ if (!tmp)
+ {
+ LOGD(ERROR, domid, "Internal error: %s does not exist",
+ GCSPRINTF("%s/frontend", libxl_path));
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ char **kvs = libxl__xs_kvs_of_flexarray(gc, empty);
+
+ rc = libxl__xs_writev(gc, t, be_path, kvs);
+ if (rc) goto out;
+
+ rc = libxl__xs_writev(gc, t, libxl_path, kvs);
+ if (rc) goto out;
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ DEVICE_ADD(disk, disks, domid, &disk_saved, COMPARE_DISK, &d_config);
+
+ rc = libxl__dm_check_start(gc, &d_config, domid);
+ if (rc) goto out;
+
+ if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+ rc = libxl__qmp_insert_cdrom(gc, domid, disk);
+ if (rc) goto out;
+ }
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+ /* Sanity check: make sure the device exists before writing here */
+ tmp = libxl__xs_read(gc, t, GCSPRINTF("%s/frontend", libxl_path));
+ if (!tmp)
+ {
+ LOGD(ERROR, domid, "Internal error: %s does not exist",
+ GCSPRINTF("%s/frontend", libxl_path));
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = libxl__set_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ char **kvs = libxl__xs_kvs_of_flexarray(gc, insert);
+
+ rc = libxl__xs_writev(gc, t, be_path, kvs);
+ if (rc) goto out;
+
+ rc = libxl__xs_writev(gc, t, libxl_path, kvs);
+ if (rc) goto out;
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
+
+ /* success, no actual async */
+ libxl__ao_complete(egc, ao, 0);
+
+ rc = 0;
+
+out:
+ libxl__xs_transaction_abort(gc, &t);
+ for (i = 0; i < num; i++)
+ libxl_device_disk_dispose(&disks[i]);
+ free(disks);
+ libxl_device_disk_dispose(&disk_empty);
+ libxl_device_disk_dispose(&disk_saved);
+ libxl_domain_config_dispose(&d_config);
+
+ if (lock) libxl__unlock_domain_userdata(lock);
+
+ if (rc) return AO_CREATE_FAIL(rc);
+ return AO_INPROGRESS;
+}
+
+/* libxl__alloc_vdev only works on the local domain, that is the domain
+ * where the toolstack is running */
+static char * libxl__alloc_vdev(libxl__gc *gc, void *get_vdev_user,
+ xs_transaction_t t)
+{
+ const char *blkdev_start = (const char *) get_vdev_user;
+ int devid = 0, disk = 0, part = 0;
+ char *libxl_dom_path = libxl__xs_libxl_path(gc, LIBXL_TOOLSTACK_DOMID);
+
+ libxl__device_disk_dev_number(blkdev_start, &disk, &part);
+ if (part != 0) {
+ LOG(ERROR, "blkdev_start is invalid");
+ return NULL;
+ }
+
+ do {
+ devid = libxl__device_disk_dev_number(GCSPRINTF("d%dp0", disk),
+ NULL, NULL);
+ if (devid < 0)
+ return NULL;
+ if (libxl__xs_read(gc, t,
+ GCSPRINTF("%s/device/vbd/%d/backend",
+ libxl_dom_path, devid)) == NULL) {
+ if (errno == ENOENT)
+ return libxl__devid_to_vdev(gc, devid);
+ else
+ return NULL;
+ }
+ disk++;
+ } while (1);
+ return NULL;
+}
+
+/* Callbacks */
+
+char *libxl__device_disk_find_local_path(libxl__gc *gc,
+ libxl_domid guest_domid,
+ const libxl_device_disk *disk,
+ bool qdisk_direct)
+{
+ char *path = NULL;
+
+ /* No local paths for driver domains */
+ if (disk->backend_domname != NULL) {
+ LOG(DEBUG, "Non-local backend, can't access locally.\n");
+ goto out;
+ }
+
+ /*
+ * If this is in raw format, and we're not using a script or a
+ * driver domain, we can access the target path directly.
+ */
+ if (disk->format == LIBXL_DISK_FORMAT_RAW
+ && disk->script == NULL) {
+ path = libxl__strdup(gc, disk->pdev_path);
+ LOG(DEBUG, "Directly accessing local RAW disk %s", path);
+ goto out;
+ }
+
+ /*
+ * If we're being called for a qemu path, we can pass the target
+ * string directly as well
+ */
+ if (qdisk_direct && disk->backend == LIBXL_DISK_BACKEND_QDISK) {
+ path = libxl__strdup(gc, disk->pdev_path);
+ LOG(DEBUG, "Directly accessing local QDISK target %s", path);
+ goto out;
+ }
+
+ /*
+ * If the format isn't raw and / or we're using a script, then see
+ * if the script has written a path to the "cooked" node
+ */
+ if (disk->script && guest_domid != INVALID_DOMID) {
+ libxl__device device;
+ char *be_path, *pdpath;
+ int rc;
+
+ LOGD(DEBUG, guest_domid,
+ "Run from a script; checking for physical-device-path (vdev %s)",
+ disk->vdev);
+
+ rc = libxl__device_from_disk(gc, guest_domid, disk, &device);
+ if (rc < 0)
+ goto out;
+
+ be_path = libxl__device_backend_path(gc, &device);
+
+ pdpath = libxl__sprintf(gc, "%s/physical-device-path", be_path);
+
+ LOGD(DEBUG, guest_domid, "Attempting to read node %s", pdpath);
+ path = libxl__xs_read(gc, XBT_NULL, pdpath);
+
+ if (path)
+ LOGD(DEBUG, guest_domid, "Accessing cooked block device %s", path);
+ else
+ LOGD(DEBUG, guest_domid, "No physical-device-path, can't access locally.");
+
+ goto out;
+ }
+
+ out:
+ return path;
+}
+
+static void local_device_attach_cb(libxl__egc *egc, libxl__ao_device *aodev);
+
+void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
+ libxl__disk_local_state *dls)
+{
+ STATE_AO_GC(dls->ao);
+ int rc;
+ const libxl_device_disk *in_disk = dls->in_disk;
+ libxl_device_disk *disk = &dls->disk;
+ const char *blkdev_start = dls->blkdev_start;
+
+ assert(in_disk->pdev_path);
+
+ disk->vdev = NULL;
+
+ if (dls->diskpath)
+ LOG(DEBUG, "Strange, dls->diskpath already set: %s", dls->diskpath);
+
+ LOG(DEBUG, "Trying to find local path");
+
+ dls->diskpath = libxl__device_disk_find_local_path(gc, INVALID_DOMID,
+ in_disk, false);
+ if (dls->diskpath) {
+ LOG(DEBUG, "Local path found, executing callback.");
+ dls->callback(egc, dls, 0);
+ } else {
+ LOG(DEBUG, "Local path not found, initiating attach.");
+
+ memcpy(disk, in_disk, sizeof(libxl_device_disk));
+ disk->pdev_path = libxl__strdup(gc, in_disk->pdev_path);
+ if (in_disk->script != NULL)
+ disk->script = libxl__strdup(gc, in_disk->script);
+ disk->vdev = NULL;
+
+ rc = libxl__device_disk_setdefault(gc, disk, LIBXL_TOOLSTACK_DOMID);
+ if (rc) goto out;
+
+ libxl__prepare_ao_device(ao, &dls->aodev);
+ dls->aodev.callback = local_device_attach_cb;
+ device_disk_add(egc, LIBXL_TOOLSTACK_DOMID, disk, &dls->aodev,
+ libxl__alloc_vdev, (void *) blkdev_start);
+ }
+
+ return;
+
+ out:
+ assert(rc);
+ dls->rc = rc;
+ libxl__device_disk_local_initiate_detach(egc, dls);
+ dls->callback(egc, dls, rc);
+}
+
+static void local_device_attach_cb(libxl__egc *egc, libxl__ao_device *aodev)
+{
+ STATE_AO_GC(aodev->ao);
+ libxl__disk_local_state *dls = CONTAINER_OF(aodev, *dls, aodev);
+ char *be_path = NULL;
+ int rc;
+ libxl__device device;
+ libxl_device_disk *disk = &dls->disk;
+
+ rc = aodev->rc;
+ if (rc) {
+ LOGE(ERROR, "unable locally attach device: %s", disk->pdev_path);
+ goto out;
+ }
+
+ rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID, disk, &device);
+ if (rc < 0)
+ goto out;
+ be_path = libxl__device_backend_path(gc, &device);
+ rc = libxl__wait_for_backend(gc, be_path, GCSPRINTF("%d", XenbusStateConnected));
+ if (rc < 0)
+ goto out;
+
+ dls->diskpath = GCSPRINTF("/dev/%s",
+ libxl__devid_to_localdev(gc, device.devid));
+ LOG(DEBUG, "locally attached disk %s", dls->diskpath);
+
+ dls->callback(egc, dls, 0);
+ return;
+
+ out:
+ assert(rc);
+ dls->rc = rc;
+ libxl__device_disk_local_initiate_detach(egc, dls);
+ return;
+}
+
+/* Callbacks for local detach */
+
+static void local_device_detach_cb(libxl__egc *egc, libxl__ao_device *aodev);
+
+void libxl__device_disk_local_initiate_detach(libxl__egc *egc,
+ libxl__disk_local_state *dls)
+{
+ STATE_AO_GC(dls->ao);
+ int rc = 0;
+ libxl_device_disk *disk = &dls->disk;
+ libxl__device *device;
+ libxl__ao_device *aodev = &dls->aodev;
+ libxl__prepare_ao_device(ao, aodev);
+
+ if (!dls->diskpath) goto out;
+
+ if (disk->vdev != NULL) {
+ GCNEW(device);
+ rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID,
+ disk, device);
+ if (rc != 0) goto out;
+
+ aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
+ aodev->dev = device;
+ aodev->callback = local_device_detach_cb;
+ aodev->force = 0;
+ libxl__initiate_device_generic_remove(egc, aodev);
+ return;
+ }
+
+out:
+ aodev->rc = rc;
+ local_device_detach_cb(egc, aodev);
+ return;
+}
+
+static void local_device_detach_cb(libxl__egc *egc, libxl__ao_device *aodev)
+{
+ STATE_AO_GC(aodev->ao);
+ libxl__disk_local_state *dls = CONTAINER_OF(aodev, *dls, aodev);
+ int rc;
+
+ if (aodev->rc) {
+ LOGED(ERROR, aodev->dev->domid, "Unable to %s %s with id %u",
+ libxl__device_action_to_string(aodev->action),
+ libxl__device_kind_to_string(aodev->dev->kind),
+ aodev->dev->devid);
+ goto out;
+ }
+
+out:
+ /*
+ * If there was an error in dls->rc, it means we have been called from
+ * a failed execution of libxl__device_disk_local_initiate_attach,
+ * so return the original error.
+ */
+ rc = dls->rc ? dls->rc : aodev->rc;
+ dls->callback(egc, dls, rc);
+ return;
+}
+
+/* The following functions are defined:
+ * libxl_device_disk_add
+ * libxl__add_disks
+ * libxl_device_disk_remove
+ * libxl_device_disk_destroy
+ */
+LIBXL_DEFINE_DEVICE_ADD(disk)
+LIBXL_DEFINE_DEVICES_ADD(disk)
+LIBXL_DEFINE_DEVICE_REMOVE(disk)
+
+static int libxl_device_disk_compare(libxl_device_disk *d1,
+ libxl_device_disk *d2)
+{
+ return COMPARE_DISK(d1, d2);
+}
+
+/* Take care of removable device. We maintain invariant in the
+ * insert / remove operation so that:
+ * 1. if xenstore is "empty" while JSON is not, the result
+ * is "empty"
+ * 2. if xenstore has a different media than JSON, use the
+ * one in JSON
+ * 3. if xenstore and JSON have the same media, well, you
+ * know the answer :-)
+ *
+ * Currently there is only one removable device -- CDROM.
+ * Look for libxl_cdrom_insert for reference.
+ */
+static void libxl_device_disk_merge(libxl_ctx *ctx, void *d1, void *d2)
+{
+ GC_INIT(ctx);
+ libxl_device_disk *src = d1;
+ libxl_device_disk *dst = d2;
+
+ if (src->removable) {
+ if (!src->pdev_path || *src->pdev_path == '\0') {
+ /* 1, no media in drive */
+ free(dst->pdev_path);
+ dst->pdev_path = libxl__strdup(NOGC, "");
+ dst->format = LIBXL_DISK_FORMAT_EMPTY;
+ } else {
+ /* 2 and 3, use JSON, no need to touch anything */
+ ;
+ }
+ }
+}
+
+static int libxl_device_disk_dm_needed(void *e, unsigned domid)
+{
+ libxl_device_disk *elem = e;
+
+ return elem->backend == LIBXL_DISK_BACKEND_QDISK &&
+ elem->backend_domid == domid;
+}
+
+DEFINE_DEVICE_TYPE_STRUCT(disk,
+ .merge = libxl_device_disk_merge,
+ .dm_needed = libxl_device_disk_dm_needed,
+ .skip_attach = 1
+);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 07/12] libxl: carve out console specific functions from libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (5 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 06/12] libxl: carve out disk " Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 9:30 ` [PATCH v2 08/12] libxl: carve out memory " Juergen Gross
` (6 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
libxl.c has grown to an uncomfortable size. Carve out the console
related functions (including channels, keyboard and frame buffer)
to libxl_console.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/Makefile | 2 +-
tools/libxl/libxl.c | 846 -------------------------------------------
tools/libxl/libxl_console.c | 862 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 863 insertions(+), 847 deletions(-)
create mode 100644 tools/libxl/libxl_console.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index baf591d..dd7aa41 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -136,7 +136,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_save_callout.o _libxl_save_msgs_callout.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_vtpm.o libxl_nic.o libxl_disk.o libxl_console.o \
libxl_cpupool.o libxl_sched.o \
$(LIBXL_OBJS-y)
LIBXL_OBJS += libxl_genid.o
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 3f8f16e..20ae61a 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1507,239 +1507,6 @@ static void domain_destroy_domid_cb(libxl__egc *egc,
dis->callback(egc, dis, rc);
}
-static int libxl__console_tty_path(libxl__gc *gc, uint32_t domid, int cons_num,
- libxl_console_type type, char **tty_path)
-{
- int rc;
- char *dom_path;
-
- dom_path = libxl__xs_get_dompath(gc, domid);
- if (!dom_path) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- switch (type) {
- case LIBXL_CONSOLE_TYPE_SERIAL:
- *tty_path = GCSPRINTF("%s/serial/%d/tty", dom_path, cons_num);
- rc = 0;
- break;
- case LIBXL_CONSOLE_TYPE_PV:
- if (cons_num == 0)
- *tty_path = GCSPRINTF("%s/console/tty", dom_path);
- else
- *tty_path = GCSPRINTF("%s/device/console/%d/tty", dom_path,
- cons_num);
- rc = 0;
- break;
- default:
- rc = ERROR_INVAL;
- goto out;
- }
-
-out:
- return rc;
-}
-
-int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num,
- libxl_console_type type, int notify_fd)
-{
- GC_INIT(ctx);
- char *p = GCSPRINTF("%s/xenconsole", libxl__private_bindir_path());
- char *domid_s = GCSPRINTF("%d", domid);
- char *cons_num_s = GCSPRINTF("%d", cons_num);
- char *notify_fd_s;
- char *cons_type_s;
-
- switch (type) {
- case LIBXL_CONSOLE_TYPE_PV:
- cons_type_s = "pv";
- break;
- case LIBXL_CONSOLE_TYPE_SERIAL:
- cons_type_s = "serial";
- break;
- default:
- goto out;
- }
-
- if (notify_fd != -1) {
- notify_fd_s = GCSPRINTF("%d", notify_fd);
- execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s,
- "--start-notify-fd", notify_fd_s, (void *)NULL);
- } else {
- execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s,
- (void *)NULL);
- }
-
-out:
- GC_FREE;
- return ERROR_FAIL;
-}
-
-int libxl_console_get_tty(libxl_ctx *ctx, uint32_t domid, int cons_num,
- libxl_console_type type, char **path)
-{
- GC_INIT(ctx);
- char *tty_path;
- char *tty;
- int rc;
-
- rc = libxl__console_tty_path(gc, domid, cons_num, type, &tty_path);
- if (rc) {
- LOGD(ERROR, domid, "Failed to get tty path\n");
- goto out;
- }
-
- tty = libxl__xs_read(gc, XBT_NULL, tty_path);
- if (!tty || tty[0] == '\0') {
- LOGED(ERROR, domid, "Unable to read console tty path `%s'",
- tty_path);
- rc = ERROR_FAIL;
- goto out;
- }
-
- *path = libxl__strdup(NOGC, tty);
- rc = 0;
-out:
- GC_FREE;
- return rc;
-}
-
-static int libxl__primary_console_find(libxl_ctx *ctx, uint32_t domid_vm,
- uint32_t *domid, int *cons_num,
- libxl_console_type *type)
-{
- GC_INIT(ctx);
- uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm);
- int rc;
-
- if (stubdomid) {
- *domid = stubdomid;
- *cons_num = STUBDOM_CONSOLE_SERIAL;
- *type = LIBXL_CONSOLE_TYPE_PV;
- } else {
- switch (libxl__domain_type(gc, domid_vm)) {
- case LIBXL_DOMAIN_TYPE_HVM:
- *domid = domid_vm;
- *cons_num = 0;
- *type = LIBXL_CONSOLE_TYPE_SERIAL;
- break;
- case LIBXL_DOMAIN_TYPE_PV:
- *domid = domid_vm;
- *cons_num = 0;
- *type = LIBXL_CONSOLE_TYPE_PV;
- break;
- case LIBXL_DOMAIN_TYPE_INVALID:
- rc = ERROR_INVAL;
- goto out;
- default: abort();
- }
- }
-
- rc = 0;
-out:
- GC_FREE;
- return rc;
-}
-
-int libxl_primary_console_exec(libxl_ctx *ctx, uint32_t domid_vm, int notify_fd)
-{
- uint32_t domid;
- int cons_num;
- libxl_console_type type;
- int rc;
-
- rc = libxl__primary_console_find(ctx, domid_vm, &domid, &cons_num, &type);
- if ( rc ) return rc;
- return libxl_console_exec(ctx, domid, cons_num, type, notify_fd);
-}
-
-int libxl_primary_console_get_tty(libxl_ctx *ctx, uint32_t domid_vm,
- char **path)
-{
- uint32_t domid;
- int cons_num;
- libxl_console_type type;
- int rc;
-
- rc = libxl__primary_console_find(ctx, domid_vm, &domid, &cons_num, &type);
- if ( rc ) return rc;
- return libxl_console_get_tty(ctx, domid, cons_num, type, path);
-}
-
-int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass)
-{
- GC_INIT(ctx);
- const char *vnc_port;
- const char *vnc_listen = NULL, *vnc_pass = NULL;
- int port = 0, autopass_fd = -1;
- char *vnc_bin, *args[] = {
- "vncviewer",
- NULL, /* hostname:display */
- NULL, /* -autopass */
- NULL,
- };
-
- vnc_port = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF(
- "/local/domain/%d/console/vnc-port", domid));
- if (!vnc_port) {
- LOGD(ERROR, domid, "Cannot get vnc-port");
- goto x_fail;
- }
-
- port = atoi(vnc_port) - 5900;
-
- vnc_listen = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("/local/domain/%d/console/vnc-listen",
- domid));
-
- if ( autopass )
- vnc_pass = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("/local/domain/%d/console/vnc-pass",
- domid));
-
- if ( NULL == vnc_listen )
- vnc_listen = "localhost";
-
- if ( (vnc_bin = getenv("VNCVIEWER")) )
- args[0] = vnc_bin;
-
- args[1] = GCSPRINTF("%s:%d", vnc_listen, port);
-
- if ( vnc_pass ) {
- char tmpname[] = "/tmp/vncautopass.XXXXXX";
- autopass_fd = mkstemp(tmpname);
- if ( autopass_fd < 0 ) {
- LOGED(ERROR, domid, "mkstemp %s failed", tmpname);
- goto x_fail;
- }
-
- if ( unlink(tmpname) ) {
- /* should never happen */
- LOGED(ERROR, domid, "unlink %s failed", tmpname);
- goto x_fail;
- }
-
- if ( libxl_write_exactly(ctx, autopass_fd, vnc_pass, strlen(vnc_pass),
- tmpname, "vnc password") )
- goto x_fail;
-
- if ( lseek(autopass_fd, SEEK_SET, 0) ) {
- LOGED(ERROR, domid, "rewind %s (autopass) failed", tmpname);
- goto x_fail;
- }
-
- args[2] = "-autopass";
- }
-
- libxl__exec(gc, autopass_fd, -1, -1, args[0], args, NULL);
-
- x_fail:
- GC_FREE;
- return ERROR_FAIL;
-}
-
int libxl__get_domid(libxl__gc *gc, uint32_t *domid)
{
int rc;
@@ -1813,557 +1580,6 @@ int libxl__resolve_domid(libxl__gc *gc, const char *name, uint32_t *domid)
}
/******************************************************************************/
-int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
- libxl__device_console *console,
- libxl__domain_build_state *state,
- libxl__device *device)
-{
- flexarray_t *front, *ro_front;
- flexarray_t *back;
- int rc;
-
- if (console->devid && state) {
- rc = ERROR_INVAL;
- goto out;
- }
- if (!console->devid && (console->name || console->path)) {
- LOGD(ERROR, domid, "Primary console has invalid configuration");
- rc = ERROR_INVAL;
- goto out;
- }
-
- front = flexarray_make(gc, 16, 1);
- ro_front = flexarray_make(gc, 16, 1);
- back = flexarray_make(gc, 16, 1);
-
- device->backend_devid = console->devid;
- device->backend_domid = console->backend_domid;
- device->backend_kind = LIBXL__DEVICE_KIND_CONSOLE;
- device->devid = console->devid;
- device->domid = domid;
- device->kind = LIBXL__DEVICE_KIND_CONSOLE;
-
- flexarray_append(back, "frontend-id");
- flexarray_append(back, GCSPRINTF("%d", domid));
- flexarray_append(back, "online");
- flexarray_append(back, "1");
- flexarray_append(back, "state");
- flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
- flexarray_append(back, "protocol");
- flexarray_append(back, LIBXL_XENCONSOLE_PROTOCOL);
-
- if (console->name) {
- flexarray_append(ro_front, "name");
- flexarray_append(ro_front, console->name);
- flexarray_append(back, "name");
- flexarray_append(back, console->name);
- }
- if (console->connection) {
- flexarray_append(back, "connection");
- flexarray_append(back, console->connection);
- }
- if (console->path) {
- flexarray_append(back, "path");
- flexarray_append(back, console->path);
- }
-
- flexarray_append(front, "backend-id");
- flexarray_append(front, GCSPRINTF("%d", console->backend_domid));
-
- flexarray_append(ro_front, "limit");
- flexarray_append(ro_front, GCSPRINTF("%d", LIBXL_XENCONSOLE_LIMIT));
- flexarray_append(ro_front, "type");
- if (console->consback == LIBXL__CONSOLE_BACKEND_XENCONSOLED)
- flexarray_append(ro_front, "xenconsoled");
- else
- flexarray_append(ro_front, "ioemu");
- flexarray_append(ro_front, "output");
- flexarray_append(ro_front, console->output);
- flexarray_append(ro_front, "tty");
- flexarray_append(ro_front, "");
-
- if (state) {
- flexarray_append(ro_front, "port");
- flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->console_port));
- flexarray_append(ro_front, "ring-ref");
- flexarray_append(ro_front, GCSPRINTF("%lu", state->console_mfn));
- } else {
- flexarray_append(front, "state");
- flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
- flexarray_append(front, "protocol");
- flexarray_append(front, LIBXL_XENCONSOLE_PROTOCOL);
- }
- libxl__device_generic_add(gc, XBT_NULL, device,
- libxl__xs_kvs_of_flexarray(gc, back),
- libxl__xs_kvs_of_flexarray(gc, front),
- libxl__xs_kvs_of_flexarray(gc, ro_front));
- rc = 0;
-out:
- return rc;
-}
-
-/******************************************************************************/
-
-int libxl__init_console_from_channel(libxl__gc *gc,
- libxl__device_console *console,
- int dev_num,
- libxl_device_channel *channel)
-{
- int rc;
-
- libxl__device_console_init(console);
-
- /* Perform validation first, allocate second. */
-
- if (!channel->name) {
- LOG(ERROR, "channel %d has no name", channel->devid);
- return ERROR_INVAL;
- }
-
- if (channel->backend_domname) {
- rc = libxl_domain_qualifier_to_domid(CTX, channel->backend_domname,
- &channel->backend_domid);
- if (rc < 0) return rc;
- }
-
- /* The xenstore 'output' node tells the backend what to connect the console
- to. If the channel has "connection = pty" then the "output" node will be
- set to "pty". If the channel has "connection = socket" then the "output"
- node will be set to "chardev:libxl-channel%d". This tells the qemu
- backend to proxy data between the console ring and the character device
- with id "libxl-channel%d". These character devices are currently defined
- on the qemu command-line via "-chardev" options in libxl_dm.c */
-
- switch (channel->connection) {
- case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
- LOG(ERROR, "channel %d has no defined connection; "
- "to where should it be connected?", channel->devid);
- return ERROR_INVAL;
- case LIBXL_CHANNEL_CONNECTION_PTY:
- console->connection = libxl__strdup(NOGC, "pty");
- console->output = libxl__sprintf(NOGC, "pty");
- break;
- case LIBXL_CHANNEL_CONNECTION_SOCKET:
- if (!channel->u.socket.path) {
- LOG(ERROR, "channel %d has no path", channel->devid);
- return ERROR_INVAL;
- }
- console->connection = libxl__strdup(NOGC, "socket");
- console->path = libxl__strdup(NOGC, channel->u.socket.path);
- console->output = libxl__sprintf(NOGC, "chardev:libxl-channel%d",
- channel->devid);
- break;
- default:
- /* We've forgotten to add the clause */
- LOG(ERROR, "%s: missing implementation for channel connection %d",
- __func__, channel->connection);
- abort();
- }
-
- console->devid = dev_num;
- console->consback = LIBXL__CONSOLE_BACKEND_IOEMU;
- console->backend_domid = channel->backend_domid;
- console->name = libxl__strdup(NOGC, channel->name);
-
- return 0;
-}
-
-static int libxl__device_channel_from_xenstore(libxl__gc *gc,
- const char *libxl_path,
- libxl_device_channel *channel)
-{
- const char *tmp;
- int rc;
-
- libxl_device_channel_init(channel);
-
- rc = libxl__xs_read_checked(NOGC, XBT_NULL,
- GCSPRINTF("%s/name", libxl_path),
- (const char **)(&channel->name));
- if (rc) goto out;
- rc = libxl__xs_read_checked(gc, XBT_NULL,
- GCSPRINTF("%s/connection", libxl_path), &tmp);
- if (rc) goto out;
- if (!strcmp(tmp, "pty")) {
- channel->connection = LIBXL_CHANNEL_CONNECTION_PTY;
- } else if (!strcmp(tmp, "socket")) {
- channel->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
- rc = libxl__xs_read_checked(NOGC, XBT_NULL,
- GCSPRINTF("%s/path", libxl_path),
- (const char **)(&channel->u.socket.path));
- if (rc) goto out;
- } else {
- rc = ERROR_INVAL;
- goto out;
- }
-
- rc = 0;
- out:
- return rc;
-}
-
-static int libxl__append_channel_list(libxl__gc *gc,
- uint32_t domid,
- libxl_device_channel **channels,
- int *nchannels)
-{
- char *libxl_dir_path = NULL;
- char **dir = NULL;
- unsigned int n = 0, devid = 0;
- libxl_device_channel *next = NULL;
- int rc = 0, i;
-
- libxl_dir_path = GCSPRINTF("%s/device/console",
- libxl__xs_libxl_path(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n);
- if (!dir || !n)
- goto out;
-
- for (i = 0; i < n; i++) {
- const char *libxl_path, *name;
- libxl_device_channel *tmp;
-
- libxl_path = GCSPRINTF("%s/%s", libxl_dir_path, dir[i]);
- name = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/name", libxl_path));
- /* 'channels' are consoles with names, so ignore all consoles
- without names */
- if (!name) continue;
- tmp = realloc(*channels,
- sizeof(libxl_device_channel) * (*nchannels + devid + 1));
- if (!tmp) {
- rc = ERROR_NOMEM;
- goto out;
- }
- *channels = tmp;
- next = *channels + *nchannels + devid;
- rc = libxl__device_channel_from_xenstore(gc, libxl_path, next);
- if (rc) goto out;
- next->devid = devid;
- devid++;
- }
- *nchannels += devid;
- return 0;
-
- out:
- return rc;
-}
-
-libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
- uint32_t domid,
- int *num)
-{
- GC_INIT(ctx);
- libxl_device_channel *channels = NULL;
- int rc;
-
- *num = 0;
-
- rc = libxl__append_channel_list(gc, domid, &channels, num);
- if (rc) goto out_err;
-
- GC_FREE;
- return channels;
-
-out_err:
- LOGD(ERROR, domid, "Unable to list channels");
- while (*num) {
- (*num)--;
- libxl_device_channel_dispose(&channels[*num]);
- }
- free(channels);
- return NULL;
-}
-
-int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
- libxl_device_channel *channel,
- libxl_channelinfo *channelinfo)
-{
- GC_INIT(ctx);
- char *dompath, *fe_path, *libxl_path;
- char *val;
- int rc;
-
- dompath = libxl__xs_get_dompath(gc, domid);
- channelinfo->devid = channel->devid;
-
- fe_path = GCSPRINTF("%s/device/console/%d", dompath,
- channelinfo->devid + 1);
- libxl_path = GCSPRINTF("%s/device/console/%d",
- libxl__xs_libxl_path(gc, domid),
- channelinfo->devid + 1);
- channelinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", libxl_path), NULL);
- if (!channelinfo->backend) {
- GC_FREE;
- return ERROR_FAIL;
- }
- rc = libxl__backendpath_parse_domid(gc, channelinfo->backend,
- &channelinfo->backend_id);
- if (rc) goto out;
-
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
- channelinfo->state = val ? strtoul(val, NULL, 10) : -1;
- channelinfo->frontend = libxl__strdup(NOGC, fe_path);
- channelinfo->frontend_id = domid;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
- channelinfo->rref = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/port", fe_path));
- channelinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
-
- channelinfo->connection = channel->connection;
- switch (channel->connection) {
- case LIBXL_CHANNEL_CONNECTION_PTY:
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path));
- /*
- * It is obviously very wrong for this value to be in the
- * frontend. But in XSA-175 we don't want to re-engineer
- * this because other xenconsole code elsewhere (some
- * even out of tree, perhaps) expects this node to be
- * here.
- *
- * FE/pty is readonly for the guest. It always exists if
- * FE does because libxl__device_console_add
- * unconditionally creates it and nothing deletes it.
- *
- * The guest can delete the whole FE (which it has write
- * privilege on) but the containing directories
- * /local/GUEST[/device[/console]] are also RO for the
- * guest. So if the guest deletes FE it cannot recreate
- * it.
- *
- * Therefore the guest cannot cause FE/pty to contain bad
- * data, although it can cause it to not exist.
- */
- if (!val) val = "/NO-SUCH-PATH";
- channelinfo->u.pty.path = strdup(val);
- break;
- default:
- break;
- }
- rc = 0;
- out:
- GC_FREE;
- return rc;
-}
-
-/******************************************************************************/
-
-int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb)
-{
- int rc;
- rc = libxl__resolve_domid(gc, vkb->backend_domname, &vkb->backend_domid);
- return rc;
-}
-
-static int libxl__device_from_vkb(libxl__gc *gc, uint32_t domid,
- libxl_device_vkb *vkb,
- libxl__device *device)
-{
- device->backend_devid = vkb->devid;
- device->backend_domid = vkb->backend_domid;
- device->backend_kind = LIBXL__DEVICE_KIND_VKBD;
- device->devid = vkb->devid;
- device->domid = domid;
- device->kind = LIBXL__DEVICE_KIND_VKBD;
-
- return 0;
-}
-
-int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb,
- const libxl_asyncop_how *ao_how)
-{
- AO_CREATE(ctx, domid, ao_how);
- int rc;
-
- rc = libxl__device_vkb_add(gc, domid, vkb);
- if (rc) {
- LOGD(ERROR, domid, "Unable to add vkb device");
- goto out;
- }
-
-out:
- libxl__ao_complete(egc, ao, rc);
- return AO_INPROGRESS;
-}
-
-int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
- libxl_device_vkb *vkb)
-{
- flexarray_t *front;
- flexarray_t *back;
- libxl__device device;
- int rc;
-
- rc = libxl__device_vkb_setdefault(gc, vkb);
- if (rc) goto out;
-
- front = flexarray_make(gc, 16, 1);
- back = flexarray_make(gc, 16, 1);
-
- if (vkb->devid == -1) {
- if ((vkb->devid = libxl__device_nextid(gc, domid, "vkb")) < 0) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
-
- rc = libxl__device_from_vkb(gc, domid, vkb, &device);
- if (rc != 0) goto out;
-
- flexarray_append(back, "frontend-id");
- flexarray_append(back, GCSPRINTF("%d", domid));
- flexarray_append(back, "online");
- flexarray_append(back, "1");
- flexarray_append(back, "state");
- flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
-
- flexarray_append(front, "backend-id");
- flexarray_append(front, GCSPRINTF("%d", vkb->backend_domid));
- flexarray_append(front, "state");
- flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
-
- libxl__device_generic_add(gc, XBT_NULL, &device,
- libxl__xs_kvs_of_flexarray(gc, back),
- libxl__xs_kvs_of_flexarray(gc, front),
- NULL);
- rc = 0;
-out:
- return rc;
-}
-
-/******************************************************************************/
-
-int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb)
-{
- int rc;
-
- libxl_defbool_setdefault(&vfb->vnc.enable, true);
- if (libxl_defbool_val(vfb->vnc.enable)) {
- if (!vfb->vnc.listen) {
- vfb->vnc.listen = strdup("127.0.0.1");
- if (!vfb->vnc.listen) return ERROR_NOMEM;
- }
-
- libxl_defbool_setdefault(&vfb->vnc.findunused, true);
- } else {
- libxl_defbool_setdefault(&vfb->vnc.findunused, false);
- }
-
- libxl_defbool_setdefault(&vfb->sdl.enable, false);
- libxl_defbool_setdefault(&vfb->sdl.opengl, false);
-
- rc = libxl__resolve_domid(gc, vfb->backend_domname, &vfb->backend_domid);
- return rc;
-}
-
-static int libxl__device_from_vfb(libxl__gc *gc, uint32_t domid,
- libxl_device_vfb *vfb,
- libxl__device *device)
-{
- device->backend_devid = vfb->devid;
- device->backend_domid = vfb->backend_domid;
- device->backend_kind = LIBXL__DEVICE_KIND_VFB;
- device->devid = vfb->devid;
- device->domid = domid;
- device->kind = LIBXL__DEVICE_KIND_VFB;
- return 0;
-}
-
-int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb,
- const libxl_asyncop_how *ao_how)
-{
- AO_CREATE(ctx, domid, ao_how);
- int rc;
-
- rc = libxl__device_vfb_add(gc, domid, vfb);
- if (rc) {
- LOGD(ERROR, domid, "Unable to add vfb device");
- goto out;
- }
-
-out:
- libxl__ao_complete(egc, ao, rc);
- return AO_INPROGRESS;
-}
-
-int libxl__device_vfb_add(libxl__gc *gc, uint32_t domid, libxl_device_vfb *vfb)
-{
- flexarray_t *front;
- flexarray_t *back;
- libxl__device device;
- int rc;
-
- rc = libxl__device_vfb_setdefault(gc, vfb);
- if (rc) goto out;
-
- front = flexarray_make(gc, 16, 1);
- back = flexarray_make(gc, 16, 1);
-
- if (vfb->devid == -1) {
- if ((vfb->devid = libxl__device_nextid(gc, domid, "vfb")) < 0) {
- rc = ERROR_FAIL;
- goto out;
- }
- }
-
- rc = libxl__device_from_vfb(gc, domid, vfb, &device);
- if (rc != 0) goto out;
-
- flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid));
- flexarray_append_pair(back, "online", "1");
- flexarray_append_pair(back, "state", GCSPRINTF("%d", XenbusStateInitialising));
- flexarray_append_pair(back, "vnc",
- libxl_defbool_val(vfb->vnc.enable) ? "1" : "0");
- flexarray_append_pair(back, "vnclisten", vfb->vnc.listen);
- flexarray_append_pair(back, "vncpasswd", vfb->vnc.passwd);
- flexarray_append_pair(back, "vncdisplay",
- GCSPRINTF("%d", vfb->vnc.display));
- flexarray_append_pair(back, "vncunused",
- libxl_defbool_val(vfb->vnc.findunused) ? "1" : "0");
- flexarray_append_pair(back, "sdl",
- libxl_defbool_val(vfb->sdl.enable) ? "1" : "0");
- flexarray_append_pair(back, "opengl",
- libxl_defbool_val(vfb->sdl.opengl) ? "1" : "0");
- if (vfb->sdl.xauthority) {
- flexarray_append_pair(back, "xauthority", vfb->sdl.xauthority);
- }
- if (vfb->sdl.display) {
- flexarray_append_pair(back, "display", vfb->sdl.display);
- }
-
- flexarray_append_pair(front, "backend-id",
- GCSPRINTF("%d", vfb->backend_domid));
- flexarray_append_pair(front, "state", GCSPRINTF("%d", XenbusStateInitialising));
-
- libxl__device_generic_add(gc, XBT_NULL, &device,
- libxl__xs_kvs_of_flexarray(gc, back),
- libxl__xs_kvs_of_flexarray(gc, front),
- NULL);
- rc = 0;
-out:
- return rc;
-}
-
-/******************************************************************************/
-
-/* The following functions are defined:
- * libxl_device_vkb_remove
- * libxl_device_vkb_destroy
- * libxl_device_vfb_remove
- * libxl_device_vfb_destroy
- */
-
-/* channel/console hotunplug is not implemented. There are 2 possibilities:
- * 1. add support for secondary consoles to xenconsoled
- * 2. dynamically add/remove qemu chardevs via qmp messages. */
-
-/* vkb */
-LIBXL_DEFINE_DEVICE_REMOVE(vkb)
-
-/* vfb */
-LIBXL_DEFINE_DEVICE_REMOVE(vfb)
-
-/******************************************************************************/
/*
* Data structures used to track devices handled by driver domains
@@ -3861,68 +3077,6 @@ int libxl_send_debug_keys(libxl_ctx *ctx, char *keys)
return 0;
}
-libxl_xen_console_reader *
- libxl_xen_console_read_start(libxl_ctx *ctx, int clear)
-{
- GC_INIT(ctx);
- libxl_xen_console_reader *cr;
- unsigned int size = 16384;
-
- cr = libxl__zalloc(NOGC, sizeof(libxl_xen_console_reader));
- cr->buffer = libxl__zalloc(NOGC, size);
- cr->size = size;
- cr->count = size;
- cr->clear = clear;
- cr->incremental = 1;
-
- GC_FREE;
- return cr;
-}
-
-/* return values: *line_r
- * 1 success, whole line obtained from buffer non-0
- * 0 no more lines available right now 0
- * negative error code ERROR_* 0
- * On success *line_r is updated to point to a nul-terminated
- * string which is valid until the next call on the same console
- * reader. The libxl caller may overwrite parts of the string
- * if it wishes. */
-int libxl_xen_console_read_line(libxl_ctx *ctx,
- libxl_xen_console_reader *cr,
- char **line_r)
-{
- int ret;
- GC_INIT(ctx);
-
- memset(cr->buffer, 0, cr->size);
- ret = xc_readconsolering(ctx->xch, cr->buffer, &cr->count,
- cr->clear, cr->incremental, &cr->index);
- if (ret < 0) {
- LOGE(ERROR, "reading console ring buffer");
- GC_FREE;
- return ERROR_FAIL;
- }
- if (!ret) {
- if (cr->count) {
- *line_r = cr->buffer;
- ret = 1;
- } else {
- *line_r = NULL;
- ret = 0;
- }
- }
-
- GC_FREE;
- return ret;
-}
-
-void libxl_xen_console_read_finish(libxl_ctx *ctx,
- libxl_xen_console_reader *cr)
-{
- free(cr->buffer);
- free(cr);
-}
-
uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid)
{
GC_INIT(ctx);
diff --git a/tools/libxl/libxl_console.c b/tools/libxl/libxl_console.c
new file mode 100644
index 0000000..cbc70b7
--- /dev/null
+++ b/tools/libxl/libxl_console.c
@@ -0,0 +1,862 @@
+/*
+ * 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"
+
+static int libxl__console_tty_path(libxl__gc *gc, uint32_t domid, int cons_num,
+ libxl_console_type type, char **tty_path)
+{
+ int rc;
+ char *dom_path;
+
+ dom_path = libxl__xs_get_dompath(gc, domid);
+ if (!dom_path) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ switch (type) {
+ case LIBXL_CONSOLE_TYPE_SERIAL:
+ *tty_path = GCSPRINTF("%s/serial/%d/tty", dom_path, cons_num);
+ rc = 0;
+ break;
+ case LIBXL_CONSOLE_TYPE_PV:
+ if (cons_num == 0)
+ *tty_path = GCSPRINTF("%s/console/tty", dom_path);
+ else
+ *tty_path = GCSPRINTF("%s/device/console/%d/tty", dom_path,
+ cons_num);
+ rc = 0;
+ break;
+ default:
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+out:
+ return rc;
+}
+
+int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num,
+ libxl_console_type type, int notify_fd)
+{
+ GC_INIT(ctx);
+ char *p = GCSPRINTF("%s/xenconsole", libxl__private_bindir_path());
+ char *domid_s = GCSPRINTF("%d", domid);
+ char *cons_num_s = GCSPRINTF("%d", cons_num);
+ char *notify_fd_s;
+ char *cons_type_s;
+
+ switch (type) {
+ case LIBXL_CONSOLE_TYPE_PV:
+ cons_type_s = "pv";
+ break;
+ case LIBXL_CONSOLE_TYPE_SERIAL:
+ cons_type_s = "serial";
+ break;
+ default:
+ goto out;
+ }
+
+ if (notify_fd != -1) {
+ notify_fd_s = GCSPRINTF("%d", notify_fd);
+ execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s,
+ "--start-notify-fd", notify_fd_s, (void *)NULL);
+ } else {
+ execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s,
+ (void *)NULL);
+ }
+
+out:
+ GC_FREE;
+ return ERROR_FAIL;
+}
+
+int libxl_console_get_tty(libxl_ctx *ctx, uint32_t domid, int cons_num,
+ libxl_console_type type, char **path)
+{
+ GC_INIT(ctx);
+ char *tty_path;
+ char *tty;
+ int rc;
+
+ rc = libxl__console_tty_path(gc, domid, cons_num, type, &tty_path);
+ if (rc) {
+ LOGD(ERROR, domid, "Failed to get tty path\n");
+ goto out;
+ }
+
+ tty = libxl__xs_read(gc, XBT_NULL, tty_path);
+ if (!tty || tty[0] == '\0') {
+ LOGED(ERROR, domid, "Unable to read console tty path `%s'",
+ tty_path);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ *path = libxl__strdup(NOGC, tty);
+ rc = 0;
+out:
+ GC_FREE;
+ return rc;
+}
+
+static int libxl__primary_console_find(libxl_ctx *ctx, uint32_t domid_vm,
+ uint32_t *domid, int *cons_num,
+ libxl_console_type *type)
+{
+ GC_INIT(ctx);
+ uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm);
+ int rc;
+
+ if (stubdomid) {
+ *domid = stubdomid;
+ *cons_num = STUBDOM_CONSOLE_SERIAL;
+ *type = LIBXL_CONSOLE_TYPE_PV;
+ } else {
+ switch (libxl__domain_type(gc, domid_vm)) {
+ case LIBXL_DOMAIN_TYPE_HVM:
+ *domid = domid_vm;
+ *cons_num = 0;
+ *type = LIBXL_CONSOLE_TYPE_SERIAL;
+ break;
+ case LIBXL_DOMAIN_TYPE_PV:
+ *domid = domid_vm;
+ *cons_num = 0;
+ *type = LIBXL_CONSOLE_TYPE_PV;
+ break;
+ case LIBXL_DOMAIN_TYPE_INVALID:
+ rc = ERROR_INVAL;
+ goto out;
+ default: abort();
+ }
+ }
+
+ rc = 0;
+out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl_primary_console_exec(libxl_ctx *ctx, uint32_t domid_vm, int notify_fd)
+{
+ uint32_t domid;
+ int cons_num;
+ libxl_console_type type;
+ int rc;
+
+ rc = libxl__primary_console_find(ctx, domid_vm, &domid, &cons_num, &type);
+ if ( rc ) return rc;
+ return libxl_console_exec(ctx, domid, cons_num, type, notify_fd);
+}
+
+int libxl_primary_console_get_tty(libxl_ctx *ctx, uint32_t domid_vm,
+ char **path)
+{
+ uint32_t domid;
+ int cons_num;
+ libxl_console_type type;
+ int rc;
+
+ rc = libxl__primary_console_find(ctx, domid_vm, &domid, &cons_num, &type);
+ if ( rc ) return rc;
+ return libxl_console_get_tty(ctx, domid, cons_num, type, path);
+}
+
+int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass)
+{
+ GC_INIT(ctx);
+ const char *vnc_port;
+ const char *vnc_listen = NULL, *vnc_pass = NULL;
+ int port = 0, autopass_fd = -1;
+ char *vnc_bin, *args[] = {
+ "vncviewer",
+ NULL, /* hostname:display */
+ NULL, /* -autopass */
+ NULL,
+ };
+
+ vnc_port = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF(
+ "/local/domain/%d/console/vnc-port", domid));
+ if (!vnc_port) {
+ LOGD(ERROR, domid, "Cannot get vnc-port");
+ goto x_fail;
+ }
+
+ port = atoi(vnc_port) - 5900;
+
+ vnc_listen = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF("/local/domain/%d/console/vnc-listen",
+ domid));
+
+ if ( autopass )
+ vnc_pass = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF("/local/domain/%d/console/vnc-pass",
+ domid));
+
+ if ( NULL == vnc_listen )
+ vnc_listen = "localhost";
+
+ if ( (vnc_bin = getenv("VNCVIEWER")) )
+ args[0] = vnc_bin;
+
+ args[1] = GCSPRINTF("%s:%d", vnc_listen, port);
+
+ if ( vnc_pass ) {
+ char tmpname[] = "/tmp/vncautopass.XXXXXX";
+ autopass_fd = mkstemp(tmpname);
+ if ( autopass_fd < 0 ) {
+ LOGED(ERROR, domid, "mkstemp %s failed", tmpname);
+ goto x_fail;
+ }
+
+ if ( unlink(tmpname) ) {
+ /* should never happen */
+ LOGED(ERROR, domid, "unlink %s failed", tmpname);
+ goto x_fail;
+ }
+
+ if ( libxl_write_exactly(ctx, autopass_fd, vnc_pass, strlen(vnc_pass),
+ tmpname, "vnc password") )
+ goto x_fail;
+
+ if ( lseek(autopass_fd, SEEK_SET, 0) ) {
+ LOGED(ERROR, domid, "rewind %s (autopass) failed", tmpname);
+ goto x_fail;
+ }
+
+ args[2] = "-autopass";
+ }
+
+ libxl__exec(gc, autopass_fd, -1, -1, args[0], args, NULL);
+
+ x_fail:
+ GC_FREE;
+ return ERROR_FAIL;
+}
+
+int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
+ libxl__device_console *console,
+ libxl__domain_build_state *state,
+ libxl__device *device)
+{
+ flexarray_t *front, *ro_front;
+ flexarray_t *back;
+ int rc;
+
+ if (console->devid && state) {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ if (!console->devid && (console->name || console->path)) {
+ LOGD(ERROR, domid, "Primary console has invalid configuration");
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ front = flexarray_make(gc, 16, 1);
+ ro_front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
+
+ device->backend_devid = console->devid;
+ device->backend_domid = console->backend_domid;
+ device->backend_kind = LIBXL__DEVICE_KIND_CONSOLE;
+ device->devid = console->devid;
+ device->domid = domid;
+ device->kind = LIBXL__DEVICE_KIND_CONSOLE;
+
+ flexarray_append(back, "frontend-id");
+ flexarray_append(back, GCSPRINTF("%d", domid));
+ flexarray_append(back, "online");
+ flexarray_append(back, "1");
+ flexarray_append(back, "state");
+ flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
+ flexarray_append(back, "protocol");
+ flexarray_append(back, LIBXL_XENCONSOLE_PROTOCOL);
+
+ if (console->name) {
+ flexarray_append(ro_front, "name");
+ flexarray_append(ro_front, console->name);
+ flexarray_append(back, "name");
+ flexarray_append(back, console->name);
+ }
+ if (console->connection) {
+ flexarray_append(back, "connection");
+ flexarray_append(back, console->connection);
+ }
+ if (console->path) {
+ flexarray_append(back, "path");
+ flexarray_append(back, console->path);
+ }
+
+ flexarray_append(front, "backend-id");
+ flexarray_append(front, GCSPRINTF("%d", console->backend_domid));
+
+ flexarray_append(ro_front, "limit");
+ flexarray_append(ro_front, GCSPRINTF("%d", LIBXL_XENCONSOLE_LIMIT));
+ flexarray_append(ro_front, "type");
+ if (console->consback == LIBXL__CONSOLE_BACKEND_XENCONSOLED)
+ flexarray_append(ro_front, "xenconsoled");
+ else
+ flexarray_append(ro_front, "ioemu");
+ flexarray_append(ro_front, "output");
+ flexarray_append(ro_front, console->output);
+ flexarray_append(ro_front, "tty");
+ flexarray_append(ro_front, "");
+
+ if (state) {
+ flexarray_append(ro_front, "port");
+ flexarray_append(ro_front, GCSPRINTF("%"PRIu32, state->console_port));
+ flexarray_append(ro_front, "ring-ref");
+ flexarray_append(ro_front, GCSPRINTF("%lu", state->console_mfn));
+ } else {
+ flexarray_append(front, "state");
+ flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
+ flexarray_append(front, "protocol");
+ flexarray_append(front, LIBXL_XENCONSOLE_PROTOCOL);
+ }
+ libxl__device_generic_add(gc, XBT_NULL, device,
+ libxl__xs_kvs_of_flexarray(gc, back),
+ libxl__xs_kvs_of_flexarray(gc, front),
+ libxl__xs_kvs_of_flexarray(gc, ro_front));
+ rc = 0;
+out:
+ return rc;
+}
+
+int libxl__init_console_from_channel(libxl__gc *gc,
+ libxl__device_console *console,
+ int dev_num,
+ libxl_device_channel *channel)
+{
+ int rc;
+
+ libxl__device_console_init(console);
+
+ /* Perform validation first, allocate second. */
+
+ if (!channel->name) {
+ LOG(ERROR, "channel %d has no name", channel->devid);
+ return ERROR_INVAL;
+ }
+
+ if (channel->backend_domname) {
+ rc = libxl_domain_qualifier_to_domid(CTX, channel->backend_domname,
+ &channel->backend_domid);
+ if (rc < 0) return rc;
+ }
+
+ /* The xenstore 'output' node tells the backend what to connect the console
+ to. If the channel has "connection = pty" then the "output" node will be
+ set to "pty". If the channel has "connection = socket" then the "output"
+ node will be set to "chardev:libxl-channel%d". This tells the qemu
+ backend to proxy data between the console ring and the character device
+ with id "libxl-channel%d". These character devices are currently defined
+ on the qemu command-line via "-chardev" options in libxl_dm.c */
+
+ switch (channel->connection) {
+ case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
+ LOG(ERROR, "channel %d has no defined connection; "
+ "to where should it be connected?", channel->devid);
+ return ERROR_INVAL;
+ case LIBXL_CHANNEL_CONNECTION_PTY:
+ console->connection = libxl__strdup(NOGC, "pty");
+ console->output = libxl__sprintf(NOGC, "pty");
+ break;
+ case LIBXL_CHANNEL_CONNECTION_SOCKET:
+ if (!channel->u.socket.path) {
+ LOG(ERROR, "channel %d has no path", channel->devid);
+ return ERROR_INVAL;
+ }
+ console->connection = libxl__strdup(NOGC, "socket");
+ console->path = libxl__strdup(NOGC, channel->u.socket.path);
+ console->output = libxl__sprintf(NOGC, "chardev:libxl-channel%d",
+ channel->devid);
+ break;
+ default:
+ /* We've forgotten to add the clause */
+ LOG(ERROR, "%s: missing implementation for channel connection %d",
+ __func__, channel->connection);
+ abort();
+ }
+
+ console->devid = dev_num;
+ console->consback = LIBXL__CONSOLE_BACKEND_IOEMU;
+ console->backend_domid = channel->backend_domid;
+ console->name = libxl__strdup(NOGC, channel->name);
+
+ return 0;
+}
+
+static int libxl__device_channel_from_xenstore(libxl__gc *gc,
+ const char *libxl_path,
+ libxl_device_channel *channel)
+{
+ const char *tmp;
+ int rc;
+
+ libxl_device_channel_init(channel);
+
+ rc = libxl__xs_read_checked(NOGC, XBT_NULL,
+ GCSPRINTF("%s/name", libxl_path),
+ (const char **)(&channel->name));
+ if (rc) goto out;
+ rc = libxl__xs_read_checked(gc, XBT_NULL,
+ GCSPRINTF("%s/connection", libxl_path), &tmp);
+ if (rc) goto out;
+ if (!strcmp(tmp, "pty")) {
+ channel->connection = LIBXL_CHANNEL_CONNECTION_PTY;
+ } else if (!strcmp(tmp, "socket")) {
+ channel->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
+ rc = libxl__xs_read_checked(NOGC, XBT_NULL,
+ GCSPRINTF("%s/path", libxl_path),
+ (const char **)(&channel->u.socket.path));
+ if (rc) goto out;
+ } else {
+ rc = ERROR_INVAL;
+ goto out;
+ }
+
+ rc = 0;
+ out:
+ return rc;
+}
+
+static int libxl__append_channel_list(libxl__gc *gc,
+ uint32_t domid,
+ libxl_device_channel **channels,
+ int *nchannels)
+{
+ char *libxl_dir_path = NULL;
+ char **dir = NULL;
+ unsigned int n = 0, devid = 0;
+ libxl_device_channel *next = NULL;
+ int rc = 0, i;
+
+ libxl_dir_path = GCSPRINTF("%s/device/console",
+ libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n);
+ if (!dir || !n)
+ goto out;
+
+ for (i = 0; i < n; i++) {
+ const char *libxl_path, *name;
+ libxl_device_channel *tmp;
+
+ libxl_path = GCSPRINTF("%s/%s", libxl_dir_path, dir[i]);
+ name = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/name", libxl_path));
+ /* 'channels' are consoles with names, so ignore all consoles
+ without names */
+ if (!name) continue;
+ tmp = realloc(*channels,
+ sizeof(libxl_device_channel) * (*nchannels + devid + 1));
+ if (!tmp) {
+ rc = ERROR_NOMEM;
+ goto out;
+ }
+ *channels = tmp;
+ next = *channels + *nchannels + devid;
+ rc = libxl__device_channel_from_xenstore(gc, libxl_path, next);
+ if (rc) goto out;
+ next->devid = devid;
+ devid++;
+ }
+ *nchannels += devid;
+ return 0;
+
+ out:
+ return rc;
+}
+
+libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
+ uint32_t domid,
+ int *num)
+{
+ GC_INIT(ctx);
+ libxl_device_channel *channels = NULL;
+ int rc;
+
+ *num = 0;
+
+ rc = libxl__append_channel_list(gc, domid, &channels, num);
+ if (rc) goto out_err;
+
+ GC_FREE;
+ return channels;
+
+out_err:
+ LOGD(ERROR, domid, "Unable to list channels");
+ while (*num) {
+ (*num)--;
+ libxl_device_channel_dispose(&channels[*num]);
+ }
+ free(channels);
+ return NULL;
+}
+
+int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_channel *channel,
+ libxl_channelinfo *channelinfo)
+{
+ GC_INIT(ctx);
+ char *dompath, *fe_path, *libxl_path;
+ char *val;
+ int rc;
+
+ dompath = libxl__xs_get_dompath(gc, domid);
+ channelinfo->devid = channel->devid;
+
+ fe_path = GCSPRINTF("%s/device/console/%d", dompath,
+ channelinfo->devid + 1);
+ libxl_path = GCSPRINTF("%s/device/console/%d",
+ libxl__xs_libxl_path(gc, domid),
+ channelinfo->devid + 1);
+ channelinfo->backend = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/backend", libxl_path), NULL);
+ if (!channelinfo->backend) {
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+ rc = libxl__backendpath_parse_domid(gc, channelinfo->backend,
+ &channelinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
+ channelinfo->state = val ? strtoul(val, NULL, 10) : -1;
+ channelinfo->frontend = libxl__strdup(NOGC, fe_path);
+ channelinfo->frontend_id = domid;
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
+ channelinfo->rref = val ? strtoul(val, NULL, 10) : -1;
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/port", fe_path));
+ channelinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+ channelinfo->connection = channel->connection;
+ switch (channel->connection) {
+ case LIBXL_CHANNEL_CONNECTION_PTY:
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path));
+ /*
+ * It is obviously very wrong for this value to be in the
+ * frontend. But in XSA-175 we don't want to re-engineer
+ * this because other xenconsole code elsewhere (some
+ * even out of tree, perhaps) expects this node to be
+ * here.
+ *
+ * FE/pty is readonly for the guest. It always exists if
+ * FE does because libxl__device_console_add
+ * unconditionally creates it and nothing deletes it.
+ *
+ * The guest can delete the whole FE (which it has write
+ * privilege on) but the containing directories
+ * /local/GUEST[/device[/console]] are also RO for the
+ * guest. So if the guest deletes FE it cannot recreate
+ * it.
+ *
+ * Therefore the guest cannot cause FE/pty to contain bad
+ * data, although it can cause it to not exist.
+ */
+ if (!val) val = "/NO-SUCH-PATH";
+ channelinfo->u.pty.path = strdup(val);
+ break;
+ default:
+ break;
+ }
+ rc = 0;
+ out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb)
+{
+ int rc;
+ rc = libxl__resolve_domid(gc, vkb->backend_domname, &vkb->backend_domid);
+ return rc;
+}
+
+static int libxl__device_from_vkb(libxl__gc *gc, uint32_t domid,
+ libxl_device_vkb *vkb,
+ libxl__device *device)
+{
+ device->backend_devid = vkb->devid;
+ device->backend_domid = vkb->backend_domid;
+ device->backend_kind = LIBXL__DEVICE_KIND_VKBD;
+ device->devid = vkb->devid;
+ device->domid = domid;
+ device->kind = LIBXL__DEVICE_KIND_VKBD;
+
+ return 0;
+}
+
+int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ int rc;
+
+ rc = libxl__device_vkb_add(gc, domid, vkb);
+ if (rc) {
+ LOGD(ERROR, domid, "Unable to add vkb device");
+ goto out;
+ }
+
+out:
+ libxl__ao_complete(egc, ao, rc);
+ return AO_INPROGRESS;
+}
+
+int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
+ libxl_device_vkb *vkb)
+{
+ flexarray_t *front;
+ flexarray_t *back;
+ libxl__device device;
+ int rc;
+
+ rc = libxl__device_vkb_setdefault(gc, vkb);
+ if (rc) goto out;
+
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
+
+ if (vkb->devid == -1) {
+ if ((vkb->devid = libxl__device_nextid(gc, domid, "vkb")) < 0) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ }
+
+ rc = libxl__device_from_vkb(gc, domid, vkb, &device);
+ if (rc != 0) goto out;
+
+ flexarray_append(back, "frontend-id");
+ flexarray_append(back, GCSPRINTF("%d", domid));
+ flexarray_append(back, "online");
+ flexarray_append(back, "1");
+ flexarray_append(back, "state");
+ flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
+
+ flexarray_append(front, "backend-id");
+ flexarray_append(front, GCSPRINTF("%d", vkb->backend_domid));
+ flexarray_append(front, "state");
+ flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
+
+ libxl__device_generic_add(gc, XBT_NULL, &device,
+ libxl__xs_kvs_of_flexarray(gc, back),
+ libxl__xs_kvs_of_flexarray(gc, front),
+ NULL);
+ rc = 0;
+out:
+ return rc;
+}
+
+int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb)
+{
+ int rc;
+
+ libxl_defbool_setdefault(&vfb->vnc.enable, true);
+ if (libxl_defbool_val(vfb->vnc.enable)) {
+ if (!vfb->vnc.listen) {
+ vfb->vnc.listen = strdup("127.0.0.1");
+ if (!vfb->vnc.listen) return ERROR_NOMEM;
+ }
+
+ libxl_defbool_setdefault(&vfb->vnc.findunused, true);
+ } else {
+ libxl_defbool_setdefault(&vfb->vnc.findunused, false);
+ }
+
+ libxl_defbool_setdefault(&vfb->sdl.enable, false);
+ libxl_defbool_setdefault(&vfb->sdl.opengl, false);
+
+ rc = libxl__resolve_domid(gc, vfb->backend_domname, &vfb->backend_domid);
+ return rc;
+}
+
+static int libxl__device_from_vfb(libxl__gc *gc, uint32_t domid,
+ libxl_device_vfb *vfb,
+ libxl__device *device)
+{
+ device->backend_devid = vfb->devid;
+ device->backend_domid = vfb->backend_domid;
+ device->backend_kind = LIBXL__DEVICE_KIND_VFB;
+ device->devid = vfb->devid;
+ device->domid = domid;
+ device->kind = LIBXL__DEVICE_KIND_VFB;
+ return 0;
+}
+
+int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ int rc;
+
+ rc = libxl__device_vfb_add(gc, domid, vfb);
+ if (rc) {
+ LOGD(ERROR, domid, "Unable to add vfb device");
+ goto out;
+ }
+
+out:
+ libxl__ao_complete(egc, ao, rc);
+ return AO_INPROGRESS;
+}
+
+int libxl__device_vfb_add(libxl__gc *gc, uint32_t domid, libxl_device_vfb *vfb)
+{
+ flexarray_t *front;
+ flexarray_t *back;
+ libxl__device device;
+ int rc;
+
+ rc = libxl__device_vfb_setdefault(gc, vfb);
+ if (rc) goto out;
+
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
+
+ if (vfb->devid == -1) {
+ if ((vfb->devid = libxl__device_nextid(gc, domid, "vfb")) < 0) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ }
+
+ rc = libxl__device_from_vfb(gc, domid, vfb, &device);
+ if (rc != 0) goto out;
+
+ flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid));
+ flexarray_append_pair(back, "online", "1");
+ flexarray_append_pair(back, "state", GCSPRINTF("%d", XenbusStateInitialising));
+ flexarray_append_pair(back, "vnc",
+ libxl_defbool_val(vfb->vnc.enable) ? "1" : "0");
+ flexarray_append_pair(back, "vnclisten", vfb->vnc.listen);
+ flexarray_append_pair(back, "vncpasswd", vfb->vnc.passwd);
+ flexarray_append_pair(back, "vncdisplay",
+ GCSPRINTF("%d", vfb->vnc.display));
+ flexarray_append_pair(back, "vncunused",
+ libxl_defbool_val(vfb->vnc.findunused) ? "1" : "0");
+ flexarray_append_pair(back, "sdl",
+ libxl_defbool_val(vfb->sdl.enable) ? "1" : "0");
+ flexarray_append_pair(back, "opengl",
+ libxl_defbool_val(vfb->sdl.opengl) ? "1" : "0");
+ if (vfb->sdl.xauthority) {
+ flexarray_append_pair(back, "xauthority", vfb->sdl.xauthority);
+ }
+ if (vfb->sdl.display) {
+ flexarray_append_pair(back, "display", vfb->sdl.display);
+ }
+
+ flexarray_append_pair(front, "backend-id",
+ GCSPRINTF("%d", vfb->backend_domid));
+ flexarray_append_pair(front, "state", GCSPRINTF("%d", XenbusStateInitialising));
+
+ libxl__device_generic_add(gc, XBT_NULL, &device,
+ libxl__xs_kvs_of_flexarray(gc, back),
+ libxl__xs_kvs_of_flexarray(gc, front),
+ NULL);
+ rc = 0;
+out:
+ return rc;
+}
+
+/* The following functions are defined:
+ * libxl_device_vkb_remove
+ * libxl_device_vkb_destroy
+ * libxl_device_vfb_remove
+ * libxl_device_vfb_destroy
+ */
+
+/* channel/console hotunplug is not implemented. There are 2 possibilities:
+ * 1. add support for secondary consoles to xenconsoled
+ * 2. dynamically add/remove qemu chardevs via qmp messages. */
+
+/* vkb */
+LIBXL_DEFINE_DEVICE_REMOVE(vkb)
+
+/* vfb */
+LIBXL_DEFINE_DEVICE_REMOVE(vfb)
+
+libxl_xen_console_reader *
+ libxl_xen_console_read_start(libxl_ctx *ctx, int clear)
+{
+ GC_INIT(ctx);
+ libxl_xen_console_reader *cr;
+ unsigned int size = 16384;
+
+ cr = libxl__zalloc(NOGC, sizeof(libxl_xen_console_reader));
+ cr->buffer = libxl__zalloc(NOGC, size);
+ cr->size = size;
+ cr->count = size;
+ cr->clear = clear;
+ cr->incremental = 1;
+
+ GC_FREE;
+ return cr;
+}
+
+/* return values: *line_r
+ * 1 success, whole line obtained from buffer non-0
+ * 0 no more lines available right now 0
+ * negative error code ERROR_* 0
+ * On success *line_r is updated to point to a nul-terminated
+ * string which is valid until the next call on the same console
+ * reader. The libxl caller may overwrite parts of the string
+ * if it wishes. */
+int libxl_xen_console_read_line(libxl_ctx *ctx,
+ libxl_xen_console_reader *cr,
+ char **line_r)
+{
+ int ret;
+ GC_INIT(ctx);
+
+ memset(cr->buffer, 0, cr->size);
+ ret = xc_readconsolering(ctx->xch, cr->buffer, &cr->count,
+ cr->clear, cr->incremental, &cr->index);
+ if (ret < 0) {
+ LOGE(ERROR, "reading console ring buffer");
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+ if (!ret) {
+ if (cr->count) {
+ *line_r = cr->buffer;
+ ret = 1;
+ } else {
+ *line_r = NULL;
+ ret = 0;
+ }
+ }
+
+ GC_FREE;
+ return ret;
+}
+
+void libxl_xen_console_read_finish(libxl_ctx *ctx,
+ libxl_xen_console_reader *cr)
+{
+ free(cr->buffer);
+ free(cr);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 08/12] libxl: carve out memory specific functions from libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (6 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 07/12] libxl: carve out console " Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 9:30 ` [PATCH v2 09/12] libxl: move device specific functions out of libxl.c Juergen Gross
` (5 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
libxl.c has grown to an uncomfortable size. Carve out the memory
related functions to libxl_mem.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/Makefile | 2 +-
tools/libxl/libxl.c | 577 ----------------------------------------------
tools/libxl/libxl_mem.c | 601 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 602 insertions(+), 578 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 20ae61a..f9aad9b 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);
- 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..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, ¤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);
+ 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@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 09/12] libxl: move device specific functions out of libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (7 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 08/12] libxl: carve out memory " Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 9:30 ` [PATCH v2 10/12] libxl: carve out tmem specific functions from libxl.c Juergen Gross
` (4 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
Move the few generic device specific functions left in libxl.c to
libxl_device.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/libxl.c | 416 ---------------------------------------------
tools/libxl/libxl_device.c | 414 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 414 insertions(+), 416 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index f9aad9b..3cf4a56 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1527,50 +1527,6 @@ out:
/******************************************************************************/
-/* generic callback for devices that only need to set ao_complete */
-void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev)
-{
- STATE_AO_GC(aodev->ao);
-
- if (aodev->rc) {
- if (aodev->dev) {
- LOGD(ERROR, aodev->dev->domid, "Unable to %s %s with id %u",
- libxl__device_action_to_string(aodev->action),
- libxl__device_kind_to_string(aodev->dev->kind),
- aodev->dev->devid);
- } else {
- LOG(ERROR, "unable to %s device",
- libxl__device_action_to_string(aodev->action));
- }
- goto out;
- }
-
-out:
- libxl__ao_complete(egc, ao, aodev->rc);
- return;
-}
-
-/* common function to get next device id */
-int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
-{
- char *libxl_dom_path, **l;
- unsigned int nb;
- int nextid = -1;
-
- if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
- return nextid;
-
- l = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/device/%s", libxl_dom_path, device),
- &nb);
- if (l == NULL || nb == 0)
- nextid = 0;
- else
- nextid = strtoul(l[nb - 1], NULL, 10) + 1;
-
- return nextid;
-}
-
int libxl__resolve_domid(libxl__gc *gc, const char *name, uint32_t *domid)
{
if (!name)
@@ -1579,378 +1535,6 @@ int libxl__resolve_domid(libxl__gc *gc, const char *name, uint32_t *domid)
}
/******************************************************************************/
-
-/*
- * Data structures used to track devices handled by driver domains
- */
-
-/*
- * Structure that describes a device handled by a driver domain
- */
-typedef struct libxl__ddomain_device {
- libxl__device *dev;
- LIBXL_SLIST_ENTRY(struct libxl__ddomain_device) next;
-} libxl__ddomain_device;
-
-/*
- * Structure that describes a domain and it's associated devices
- */
-typedef struct libxl__ddomain_guest {
- uint32_t domid;
- int num_vifs, num_vbds, num_qdisks;
- LIBXL_SLIST_HEAD(, struct libxl__ddomain_device) devices;
- LIBXL_SLIST_ENTRY(struct libxl__ddomain_guest) next;
-} libxl__ddomain_guest;
-
-/*
- * Main structure used by a driver domain to keep track of devices
- * currently in use
- */
-typedef struct {
- libxl__ao *ao;
- libxl__ev_xswatch watch;
- LIBXL_SLIST_HEAD(, struct libxl__ddomain_guest) guests;
-} libxl__ddomain;
-
-static libxl__ddomain_guest *search_for_guest(libxl__ddomain *ddomain,
- uint32_t domid)
-{
- libxl__ddomain_guest *dguest;
-
- LIBXL_SLIST_FOREACH(dguest, &ddomain->guests, next) {
- if (dguest->domid == domid)
- return dguest;
- }
- return NULL;
-}
-
-static libxl__ddomain_device *search_for_device(libxl__ddomain_guest *dguest,
- libxl__device *dev)
-{
- libxl__ddomain_device *ddev;
-
- LIBXL_SLIST_FOREACH(ddev, &dguest->devices, next) {
-#define LIBXL_DEVICE_CMP(dev1, dev2, entry) (dev1->entry == dev2->entry)
- if (LIBXL_DEVICE_CMP(ddev->dev, dev, backend_devid) &&
- LIBXL_DEVICE_CMP(ddev->dev, dev, backend_domid) &&
- LIBXL_DEVICE_CMP(ddev->dev, dev, devid) &&
- LIBXL_DEVICE_CMP(ddev->dev, dev, domid) &&
- LIBXL_DEVICE_CMP(ddev->dev, dev, backend_kind) &&
- LIBXL_DEVICE_CMP(ddev->dev, dev, kind))
- return ddev;
-#undef LIBXL_DEVICE_CMP
- }
-
- return NULL;
-}
-
-static void device_complete(libxl__egc *egc, libxl__ao_device *aodev)
-{
- STATE_AO_GC(aodev->ao);
-
- LOG(DEBUG, "device %s %s %s",
- libxl__device_backend_path(gc, aodev->dev),
- libxl__device_action_to_string(aodev->action),
- aodev->rc ? "failed" : "succeed");
-
- if (aodev->action == LIBXL__DEVICE_ACTION_REMOVE)
- free(aodev->dev);
-
- libxl__nested_ao_free(aodev->ao);
-}
-
-static void qdisk_spawn_outcome(libxl__egc *egc, libxl__dm_spawn_state *dmss,
- int rc)
-{
- STATE_AO_GC(dmss->spawn.ao);
-
- LOGD(DEBUG, dmss->guest_domid, "qdisk backend spawn %s",
- rc ? "failed" : "succeed");
-
- libxl__nested_ao_free(dmss->spawn.ao);
-}
-
-/*
- * The following comment applies to both add_device and remove_device.
- *
- * If the return value is greater than 0, it means there's no ao dispatched,
- * so the free of the nested ao should be done by the parent when it has
- * finished.
- */
-static int add_device(libxl__egc *egc, libxl__ao *ao,
- libxl__ddomain_guest *dguest,
- libxl__ddomain_device *ddev)
-{
- AO_GC;
- libxl__device *dev = ddev->dev;
- libxl__ao_device *aodev;
- libxl__dm_spawn_state *dmss;
- int rc = 0;
-
- switch(dev->backend_kind) {
- case LIBXL__DEVICE_KIND_VBD:
- case LIBXL__DEVICE_KIND_VIF:
- if (dev->backend_kind == LIBXL__DEVICE_KIND_VBD) dguest->num_vbds++;
- if (dev->backend_kind == LIBXL__DEVICE_KIND_VIF) dguest->num_vifs++;
-
- GCNEW(aodev);
- libxl__prepare_ao_device(ao, aodev);
- aodev->dev = dev;
- aodev->action = LIBXL__DEVICE_ACTION_ADD;
- aodev->callback = device_complete;
- libxl__wait_device_connection(egc, aodev);
-
- break;
- case LIBXL__DEVICE_KIND_QDISK:
- if (dguest->num_qdisks == 0) {
- GCNEW(dmss);
- dmss->guest_domid = dev->domid;
- dmss->spawn.ao = ao;
- dmss->callback = qdisk_spawn_outcome;
-
- libxl__spawn_qdisk_backend(egc, dmss);
- }
- dguest->num_qdisks++;
-
- break;
- default:
- rc = 1;
- break;
- }
-
- return rc;
-}
-
-static int remove_device(libxl__egc *egc, libxl__ao *ao,
- libxl__ddomain_guest *dguest,
- libxl__ddomain_device *ddev)
-{
- AO_GC;
- libxl__device *dev = ddev->dev;
- libxl__ao_device *aodev;
- int rc = 0;
-
- switch(ddev->dev->backend_kind) {
- case LIBXL__DEVICE_KIND_VBD:
- case LIBXL__DEVICE_KIND_VIF:
- if (dev->backend_kind == LIBXL__DEVICE_KIND_VBD) dguest->num_vbds--;
- if (dev->backend_kind == LIBXL__DEVICE_KIND_VIF) dguest->num_vifs--;
-
- GCNEW(aodev);
- libxl__prepare_ao_device(ao, aodev);
- aodev->dev = dev;
- aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
- aodev->callback = device_complete;
- libxl__initiate_device_generic_remove(egc, aodev);
- break;
- case LIBXL__DEVICE_KIND_QDISK:
- if (--dguest->num_qdisks == 0) {
- rc = libxl__destroy_qdisk_backend(gc, dev->domid);
- if (rc)
- goto out;
- }
- libxl__device_destroy(gc, dev);
- free(dev);
- /* Fall through to return > 0, no ao has been dispatched */
- default:
- rc = 1;
- break;
- }
-
-out:
- return rc;
-}
-
-static void backend_watch_callback(libxl__egc *egc, libxl__ev_xswatch *watch,
- const char *watch_path,
- const char *event_path)
-{
- libxl__ddomain *ddomain = CONTAINER_OF(watch, *ddomain, watch);
- libxl__ao *nested_ao = libxl__nested_ao_create(ddomain->ao);
- STATE_AO_GC(nested_ao);
- char *p, *path;
- const char *sstate, *sonline;
- int state, online, rc, num_devs;
- libxl__device *dev = NULL;
- libxl__ddomain_device *ddev = NULL;
- libxl__ddomain_guest *dguest = NULL;
- bool free_ao = false;
-
- /* Check if event_path ends with "state" or "online" and truncate it. */
- path = libxl__strdup(gc, event_path);
- p = strrchr(path, '/');
- if (p == NULL)
- goto skip;
- if (strcmp(p, "/state") != 0 && strcmp(p, "/online") != 0)
- goto skip;
- /* Truncate the string so it points to the backend directory. */
- *p = '\0';
-
- /* Fetch the value of the state and online nodes. */
- rc = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/state", path),
- &sstate);
- if (rc || !sstate)
- goto skip;
- state = atoi(sstate);
-
- rc = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/online", path),
- &sonline);
- if (rc || !sonline)
- goto skip;
- online = atoi(sonline);
-
- dev = libxl__zalloc(NOGC, sizeof(*dev));
- rc = libxl__parse_backend_path(gc, path, dev);
- if (rc)
- goto skip;
-
- dguest = search_for_guest(ddomain, dev->domid);
- if (dguest == NULL && state == XenbusStateClosed) {
- /*
- * Spurious state change, device has already been disconnected
- * or never attached.
- */
- goto skip;
- }
- if (dguest == NULL) {
- /* Create a new guest struct and initialize it */
- dguest = libxl__zalloc(NOGC, sizeof(*dguest));
- dguest->domid = dev->domid;
- LIBXL_SLIST_INIT(&dguest->devices);
- LIBXL_SLIST_INSERT_HEAD(&ddomain->guests, dguest, next);
- LOGD(DEBUG, dguest->domid, "Added domain to the list of active guests");
- }
- ddev = search_for_device(dguest, dev);
- if (ddev == NULL && state == XenbusStateClosed) {
- /*
- * Spurious state change, device has already been disconnected
- * or never attached.
- */
- goto skip;
- } else if (ddev == NULL) {
- /*
- * New device addition, allocate a struct to hold it and add it
- * to the list of active devices for a given guest.
- */
- ddev = libxl__zalloc(NOGC, sizeof(*ddev));
- ddev->dev = dev;
- LIBXL_SLIST_INSERT_HEAD(&dguest->devices, ddev, next);
- LOGD(DEBUG, dev->domid, "Added device %s to the list of active devices",
- path);
- rc = add_device(egc, nested_ao, dguest, ddev);
- if (rc > 0)
- free_ao = true;
- } else if (state == XenbusStateClosed && online == 0) {
- /*
- * Removal of an active device, remove it from the list and
- * free it's data structures if they are no longer needed.
- *
- * The free of the associated libxl__device is left to the
- * helper remove_device function.
- */
- LIBXL_SLIST_REMOVE(&dguest->devices, ddev, libxl__ddomain_device,
- next);
- LOGD(DEBUG, dev->domid, "Removed device %s from the list of active devices",
- path);
- rc = remove_device(egc, nested_ao, dguest, ddev);
- if (rc > 0)
- free_ao = true;
-
- free(ddev);
- /* If this was the last device in the domain, remove it from the list */
- num_devs = dguest->num_vifs + dguest->num_vbds + dguest->num_qdisks;
- if (num_devs == 0) {
- LIBXL_SLIST_REMOVE(&ddomain->guests, dguest, libxl__ddomain_guest,
- next);
- LOGD(DEBUG, dguest->domid, "Removed domain from the list of active guests");
- /* Clear any leftovers in libxl/<domid> */
- libxl__xs_rm_checked(gc, XBT_NULL,
- GCSPRINTF("libxl/%u", dguest->domid));
- free(dguest);
- }
- }
-
- if (free_ao)
- libxl__nested_ao_free(nested_ao);
-
- return;
-
-skip:
- libxl__nested_ao_free(nested_ao);
- free(dev);
- free(ddev);
- free(dguest);
- return;
-}
-
-/* Handler of events for device driver domains */
-int libxl_device_events_handler(libxl_ctx *ctx,
- const libxl_asyncop_how *ao_how)
-{
- AO_CREATE(ctx, 0, ao_how);
- int rc;
- uint32_t domid;
- libxl__ddomain ddomain;
- char *be_path;
- char **kinds = NULL, **domains = NULL, **devs = NULL;
- const char *sstate;
- char *state_path;
- int state;
- unsigned int nkinds, ndomains, ndevs;
- int i, j, k;
-
- ddomain.ao = ao;
- LIBXL_SLIST_INIT(&ddomain.guests);
-
- rc = libxl__get_domid(gc, &domid);
- if (rc) {
- LOG(ERROR, "unable to get domain id");
- goto out;
- }
-
- /*
- * We use absolute paths because we want xswatch to also return
- * absolute paths that can be parsed by libxl__parse_backend_path.
- */
- be_path = GCSPRINTF("/local/domain/%u/backend", domid);
- rc = libxl__ev_xswatch_register(gc, &ddomain.watch, backend_watch_callback,
- be_path);
- if (rc) goto out;
-
- kinds = libxl__xs_directory(gc, XBT_NULL, be_path, &nkinds);
- if (kinds) {
- for (i = 0; i < nkinds; i++) {
- domains = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/%s", be_path, kinds[i]), &ndomains);
- if (!domains)
- continue;
- for (j = 0; j < ndomains; j++) {
- devs = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/%s/%s", be_path, kinds[i], domains[j]), &ndevs);
- if (!devs)
- continue;
- for (k = 0; k < ndevs; k++) {
- state_path = GCSPRINTF("%s/%s/%s/%s/state",
- be_path, kinds[i], domains[j], devs[k]);
- rc = libxl__xs_read_checked(gc, XBT_NULL, state_path, &sstate);
- if (rc || !sstate)
- continue;
- state = atoi(sstate);
- if (state == XenbusStateInitWait)
- backend_watch_callback(egc, &ddomain.watch,
- be_path, state_path);
- }
- }
- }
- }
-
- return AO_INPROGRESS;
-
-out:
- return AO_CREATE_FAIL(rc);
-}
-
-/******************************************************************************/
int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
{
xc_physinfo_t xcphysinfo = { 0 };
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index b2aeefc..c72a2b8 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -1362,6 +1362,420 @@ int libxl__wait_for_backend(libxl__gc *gc, const char *be_path,
return ERROR_FAIL;
}
+/* generic callback for devices that only need to set ao_complete */
+void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev)
+{
+ STATE_AO_GC(aodev->ao);
+
+ if (aodev->rc) {
+ if (aodev->dev) {
+ LOGD(ERROR, aodev->dev->domid, "Unable to %s %s with id %u",
+ libxl__device_action_to_string(aodev->action),
+ libxl__device_kind_to_string(aodev->dev->kind),
+ aodev->dev->devid);
+ } else {
+ LOG(ERROR, "unable to %s device",
+ libxl__device_action_to_string(aodev->action));
+ }
+ goto out;
+ }
+
+out:
+ libxl__ao_complete(egc, ao, aodev->rc);
+ return;
+}
+
+/* common function to get next device id */
+int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
+{
+ char *libxl_dom_path, **l;
+ unsigned int nb;
+ int nextid = -1;
+
+ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
+ return nextid;
+
+ l = libxl__xs_directory(gc, XBT_NULL,
+ GCSPRINTF("%s/device/%s", libxl_dom_path, device),
+ &nb);
+ if (l == NULL || nb == 0)
+ nextid = 0;
+ else
+ nextid = strtoul(l[nb - 1], NULL, 10) + 1;
+
+ return nextid;
+}
+
+static void device_complete(libxl__egc *egc, libxl__ao_device *aodev)
+{
+ STATE_AO_GC(aodev->ao);
+
+ LOG(DEBUG, "device %s %s %s",
+ libxl__device_backend_path(gc, aodev->dev),
+ libxl__device_action_to_string(aodev->action),
+ aodev->rc ? "failed" : "succeed");
+
+ if (aodev->action == LIBXL__DEVICE_ACTION_REMOVE)
+ free(aodev->dev);
+
+ libxl__nested_ao_free(aodev->ao);
+}
+
+static void qdisk_spawn_outcome(libxl__egc *egc, libxl__dm_spawn_state *dmss,
+ int rc)
+{
+ STATE_AO_GC(dmss->spawn.ao);
+
+ LOGD(DEBUG, dmss->guest_domid, "qdisk backend spawn %s",
+ rc ? "failed" : "succeed");
+
+ libxl__nested_ao_free(dmss->spawn.ao);
+}
+
+/*
+ * Data structures used to track devices handled by driver domains
+ */
+
+/*
+ * Structure that describes a device handled by a driver domain
+ */
+typedef struct libxl__ddomain_device {
+ libxl__device *dev;
+ LIBXL_SLIST_ENTRY(struct libxl__ddomain_device) next;
+} libxl__ddomain_device;
+
+/*
+ * Structure that describes a domain and it's associated devices
+ */
+typedef struct libxl__ddomain_guest {
+ uint32_t domid;
+ int num_vifs, num_vbds, num_qdisks;
+ LIBXL_SLIST_HEAD(, struct libxl__ddomain_device) devices;
+ LIBXL_SLIST_ENTRY(struct libxl__ddomain_guest) next;
+} libxl__ddomain_guest;
+
+/*
+ * Main structure used by a driver domain to keep track of devices
+ * currently in use
+ */
+typedef struct {
+ libxl__ao *ao;
+ libxl__ev_xswatch watch;
+ LIBXL_SLIST_HEAD(, struct libxl__ddomain_guest) guests;
+} libxl__ddomain;
+
+static libxl__ddomain_guest *search_for_guest(libxl__ddomain *ddomain,
+ uint32_t domid)
+{
+ libxl__ddomain_guest *dguest;
+
+ LIBXL_SLIST_FOREACH(dguest, &ddomain->guests, next) {
+ if (dguest->domid == domid)
+ return dguest;
+ }
+ return NULL;
+}
+
+static libxl__ddomain_device *search_for_device(libxl__ddomain_guest *dguest,
+ libxl__device *dev)
+{
+ libxl__ddomain_device *ddev;
+
+ LIBXL_SLIST_FOREACH(ddev, &dguest->devices, next) {
+#define LIBXL_DEVICE_CMP(dev1, dev2, entry) (dev1->entry == dev2->entry)
+ if (LIBXL_DEVICE_CMP(ddev->dev, dev, backend_devid) &&
+ LIBXL_DEVICE_CMP(ddev->dev, dev, backend_domid) &&
+ LIBXL_DEVICE_CMP(ddev->dev, dev, devid) &&
+ LIBXL_DEVICE_CMP(ddev->dev, dev, domid) &&
+ LIBXL_DEVICE_CMP(ddev->dev, dev, backend_kind) &&
+ LIBXL_DEVICE_CMP(ddev->dev, dev, kind))
+ return ddev;
+#undef LIBXL_DEVICE_CMP
+ }
+
+ return NULL;
+}
+
+/*
+ * The following comment applies to both add_device and remove_device.
+ *
+ * If the return value is greater than 0, it means there's no ao dispatched,
+ * so the free of the nested ao should be done by the parent when it has
+ * finished.
+ */
+static int add_device(libxl__egc *egc, libxl__ao *ao,
+ libxl__ddomain_guest *dguest,
+ libxl__ddomain_device *ddev)
+{
+ AO_GC;
+ libxl__device *dev = ddev->dev;
+ libxl__ao_device *aodev;
+ libxl__dm_spawn_state *dmss;
+ int rc = 0;
+
+ switch(dev->backend_kind) {
+ case LIBXL__DEVICE_KIND_VBD:
+ case LIBXL__DEVICE_KIND_VIF:
+ if (dev->backend_kind == LIBXL__DEVICE_KIND_VBD) dguest->num_vbds++;
+ if (dev->backend_kind == LIBXL__DEVICE_KIND_VIF) dguest->num_vifs++;
+
+ GCNEW(aodev);
+ libxl__prepare_ao_device(ao, aodev);
+ aodev->dev = dev;
+ aodev->action = LIBXL__DEVICE_ACTION_ADD;
+ aodev->callback = device_complete;
+ libxl__wait_device_connection(egc, aodev);
+
+ break;
+ case LIBXL__DEVICE_KIND_QDISK:
+ if (dguest->num_qdisks == 0) {
+ GCNEW(dmss);
+ dmss->guest_domid = dev->domid;
+ dmss->spawn.ao = ao;
+ dmss->callback = qdisk_spawn_outcome;
+
+ libxl__spawn_qdisk_backend(egc, dmss);
+ }
+ dguest->num_qdisks++;
+
+ break;
+ default:
+ rc = 1;
+ break;
+ }
+
+ return rc;
+}
+
+static int remove_device(libxl__egc *egc, libxl__ao *ao,
+ libxl__ddomain_guest *dguest,
+ libxl__ddomain_device *ddev)
+{
+ AO_GC;
+ libxl__device *dev = ddev->dev;
+ libxl__ao_device *aodev;
+ int rc = 0;
+
+ switch(ddev->dev->backend_kind) {
+ case LIBXL__DEVICE_KIND_VBD:
+ case LIBXL__DEVICE_KIND_VIF:
+ if (dev->backend_kind == LIBXL__DEVICE_KIND_VBD) dguest->num_vbds--;
+ if (dev->backend_kind == LIBXL__DEVICE_KIND_VIF) dguest->num_vifs--;
+
+ GCNEW(aodev);
+ libxl__prepare_ao_device(ao, aodev);
+ aodev->dev = dev;
+ aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
+ aodev->callback = device_complete;
+ libxl__initiate_device_generic_remove(egc, aodev);
+ break;
+ case LIBXL__DEVICE_KIND_QDISK:
+ if (--dguest->num_qdisks == 0) {
+ rc = libxl__destroy_qdisk_backend(gc, dev->domid);
+ if (rc)
+ goto out;
+ }
+ libxl__device_destroy(gc, dev);
+ free(dev);
+ /* Fall through to return > 0, no ao has been dispatched */
+ default:
+ rc = 1;
+ break;
+ }
+
+out:
+ return rc;
+}
+
+static void backend_watch_callback(libxl__egc *egc, libxl__ev_xswatch *watch,
+ const char *watch_path,
+ const char *event_path)
+{
+ libxl__ddomain *ddomain = CONTAINER_OF(watch, *ddomain, watch);
+ libxl__ao *nested_ao = libxl__nested_ao_create(ddomain->ao);
+ STATE_AO_GC(nested_ao);
+ char *p, *path;
+ const char *sstate, *sonline;
+ int state, online, rc, num_devs;
+ libxl__device *dev = NULL;
+ libxl__ddomain_device *ddev = NULL;
+ libxl__ddomain_guest *dguest = NULL;
+ bool free_ao = false;
+
+ /* Check if event_path ends with "state" or "online" and truncate it. */
+ path = libxl__strdup(gc, event_path);
+ p = strrchr(path, '/');
+ if (p == NULL)
+ goto skip;
+ if (strcmp(p, "/state") != 0 && strcmp(p, "/online") != 0)
+ goto skip;
+ /* Truncate the string so it points to the backend directory. */
+ *p = '\0';
+
+ /* Fetch the value of the state and online nodes. */
+ rc = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/state", path),
+ &sstate);
+ if (rc || !sstate)
+ goto skip;
+ state = atoi(sstate);
+
+ rc = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/online", path),
+ &sonline);
+ if (rc || !sonline)
+ goto skip;
+ online = atoi(sonline);
+
+ dev = libxl__zalloc(NOGC, sizeof(*dev));
+ rc = libxl__parse_backend_path(gc, path, dev);
+ if (rc)
+ goto skip;
+
+ dguest = search_for_guest(ddomain, dev->domid);
+ if (dguest == NULL && state == XenbusStateClosed) {
+ /*
+ * Spurious state change, device has already been disconnected
+ * or never attached.
+ */
+ goto skip;
+ }
+ if (dguest == NULL) {
+ /* Create a new guest struct and initialize it */
+ dguest = libxl__zalloc(NOGC, sizeof(*dguest));
+ dguest->domid = dev->domid;
+ LIBXL_SLIST_INIT(&dguest->devices);
+ LIBXL_SLIST_INSERT_HEAD(&ddomain->guests, dguest, next);
+ LOGD(DEBUG, dguest->domid, "Added domain to the list of active guests");
+ }
+ ddev = search_for_device(dguest, dev);
+ if (ddev == NULL && state == XenbusStateClosed) {
+ /*
+ * Spurious state change, device has already been disconnected
+ * or never attached.
+ */
+ goto skip;
+ } else if (ddev == NULL) {
+ /*
+ * New device addition, allocate a struct to hold it and add it
+ * to the list of active devices for a given guest.
+ */
+ ddev = libxl__zalloc(NOGC, sizeof(*ddev));
+ ddev->dev = dev;
+ LIBXL_SLIST_INSERT_HEAD(&dguest->devices, ddev, next);
+ LOGD(DEBUG, dev->domid, "Added device %s to the list of active devices",
+ path);
+ rc = add_device(egc, nested_ao, dguest, ddev);
+ if (rc > 0)
+ free_ao = true;
+ } else if (state == XenbusStateClosed && online == 0) {
+ /*
+ * Removal of an active device, remove it from the list and
+ * free it's data structures if they are no longer needed.
+ *
+ * The free of the associated libxl__device is left to the
+ * helper remove_device function.
+ */
+ LIBXL_SLIST_REMOVE(&dguest->devices, ddev, libxl__ddomain_device,
+ next);
+ LOGD(DEBUG, dev->domid, "Removed device %s from the list of active devices",
+ path);
+ rc = remove_device(egc, nested_ao, dguest, ddev);
+ if (rc > 0)
+ free_ao = true;
+
+ free(ddev);
+ /* If this was the last device in the domain, remove it from the list */
+ num_devs = dguest->num_vifs + dguest->num_vbds + dguest->num_qdisks;
+ if (num_devs == 0) {
+ LIBXL_SLIST_REMOVE(&ddomain->guests, dguest, libxl__ddomain_guest,
+ next);
+ LOGD(DEBUG, dguest->domid, "Removed domain from the list of active guests");
+ /* Clear any leftovers in libxl/<domid> */
+ libxl__xs_rm_checked(gc, XBT_NULL,
+ GCSPRINTF("libxl/%u", dguest->domid));
+ free(dguest);
+ }
+ }
+
+ if (free_ao)
+ libxl__nested_ao_free(nested_ao);
+
+ return;
+
+skip:
+ libxl__nested_ao_free(nested_ao);
+ free(dev);
+ free(ddev);
+ free(dguest);
+ return;
+}
+
+/* Handler of events for device driver domains */
+int libxl_device_events_handler(libxl_ctx *ctx,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, 0, ao_how);
+ int rc;
+ uint32_t domid;
+ libxl__ddomain ddomain;
+ char *be_path;
+ char **kinds = NULL, **domains = NULL, **devs = NULL;
+ const char *sstate;
+ char *state_path;
+ int state;
+ unsigned int nkinds, ndomains, ndevs;
+ int i, j, k;
+
+ ddomain.ao = ao;
+ LIBXL_SLIST_INIT(&ddomain.guests);
+
+ rc = libxl__get_domid(gc, &domid);
+ if (rc) {
+ LOG(ERROR, "unable to get domain id");
+ goto out;
+ }
+
+ /*
+ * We use absolute paths because we want xswatch to also return
+ * absolute paths that can be parsed by libxl__parse_backend_path.
+ */
+ be_path = GCSPRINTF("/local/domain/%u/backend", domid);
+ rc = libxl__ev_xswatch_register(gc, &ddomain.watch, backend_watch_callback,
+ be_path);
+ if (rc) goto out;
+
+ kinds = libxl__xs_directory(gc, XBT_NULL, be_path, &nkinds);
+ if (kinds) {
+ for (i = 0; i < nkinds; i++) {
+ domains = libxl__xs_directory(gc, XBT_NULL,
+ GCSPRINTF("%s/%s", be_path, kinds[i]), &ndomains);
+ if (!domains)
+ continue;
+ for (j = 0; j < ndomains; j++) {
+ devs = libxl__xs_directory(gc, XBT_NULL,
+ GCSPRINTF("%s/%s/%s", be_path, kinds[i], domains[j]), &ndevs);
+ if (!devs)
+ continue;
+ for (k = 0; k < ndevs; k++) {
+ state_path = GCSPRINTF("%s/%s/%s/%s/state",
+ be_path, kinds[i], domains[j], devs[k]);
+ rc = libxl__xs_read_checked(gc, XBT_NULL, state_path, &sstate);
+ if (rc || !sstate)
+ continue;
+ state = atoi(sstate);
+ if (state == XenbusStateInitWait)
+ backend_watch_callback(egc, &ddomain.watch,
+ be_path, state_path);
+ }
+ }
+ }
+ }
+
+ return AO_INPROGRESS;
+
+out:
+ return AO_CREATE_FAIL(rc);
+}
+
/*
* Local variables:
* mode: C
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 10/12] libxl: carve out tmem specific functions from libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (8 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 09/12] libxl: move device specific functions out of libxl.c Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 9:30 ` [PATCH v2 11/12] libxl: carve out domain " Juergen Gross
` (3 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
libxl.c has grown to an uncomfortable size. Carve out the tmem
related functions to libxl_tmem.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/Makefile | 2 +-
tools/libxl/libxl.c | 142 ----------------------------------------
tools/libxl/libxl_tmem.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 168 insertions(+), 143 deletions(-)
create mode 100644 tools/libxl/libxl_tmem.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 4b05e34..99ddae1 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_mem.o libxl_sched.o \
+ libxl_cpupool.o libxl_mem.o libxl_sched.o libxl_tmem.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 3cf4a56..67c0a13 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2105,148 +2105,6 @@ uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid)
return ret;
}
-char *libxl_tmem_list(libxl_ctx *ctx, uint32_t domid, int use_long)
-{
- int r;
- char _buf[32768];
- GC_INIT(ctx);
-
- r = xc_tmem_control(ctx->xch, -1, XEN_SYSCTL_TMEM_OP_LIST, domid, 32768,
- use_long, _buf);
- if (r < 0) {
- LOGED(ERROR, domid, "Can not get tmem list");
- GC_FREE;
- return NULL;
- }
-
- GC_FREE;
- return strdup(_buf);
-}
-
-int libxl_tmem_freeze(libxl_ctx *ctx, uint32_t domid)
-{
- int r, rc;
- GC_INIT(ctx);
-
- r = xc_tmem_control(ctx->xch, -1, XEN_SYSCTL_TMEM_OP_FREEZE, domid, 0, 0,
- NULL);
- if (r < 0) {
- LOGED(ERROR, domid, "Can not freeze tmem pools");
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = 0;
-out:
- GC_FREE;
- return rc;
-}
-
-int libxl_tmem_thaw(libxl_ctx *ctx, uint32_t domid)
-{
- int r, rc;
- GC_INIT(ctx);
-
- r = xc_tmem_control(ctx->xch, -1, XEN_SYSCTL_TMEM_OP_THAW, domid, 0, 0,
- NULL);
- if (r < 0) {
- LOGED(ERROR, domid, "Can not thaw tmem pools");
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = 0;
-out:
- GC_FREE;
- return rc;
-}
-
-static int32_t tmem_setop_from_string(char *set_name, uint32_t val,
- xen_tmem_client_t *info)
-{
- if (!strcmp(set_name, "weight"))
- info->weight = val;
- else if (!strcmp(set_name, "compress"))
- info->flags.u.compress = val;
- else
- return -1;
-
- return 0;
-}
-
-int libxl_tmem_set(libxl_ctx *ctx, uint32_t domid, char* name, uint32_t set)
-{
- int r, rc;
- xen_tmem_client_t info;
- GC_INIT(ctx);
-
- r = xc_tmem_control(ctx->xch, -1 /* pool_id */,
- XEN_SYSCTL_TMEM_OP_GET_CLIENT_INFO,
- domid, sizeof(info), 0 /* arg */, &info);
- if (r < 0) {
- LOGED(ERROR, domid, "Can not get tmem data!");
- rc = ERROR_FAIL;
- goto out;
- }
- rc = tmem_setop_from_string(name, set, &info);
- if (rc == -1) {
- LOGEVD(ERROR, -1, domid, "Invalid set, valid sets are <weight|compress>");
- rc = ERROR_INVAL;
- goto out;
- }
- r = xc_tmem_control(ctx->xch, -1 /* pool_id */,
- XEN_SYSCTL_TMEM_OP_SET_CLIENT_INFO,
- domid, sizeof(info), 0 /* arg */, &info);
- if (r < 0) {
- LOGED(ERROR, domid, "Can not set tmem %s", name);
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = 0;
-out:
- GC_FREE;
- return rc;
-}
-
-int libxl_tmem_shared_auth(libxl_ctx *ctx, uint32_t domid,
- char* uuid, int auth)
-{
- int r, rc;
- GC_INIT(ctx);
-
- r = xc_tmem_auth(ctx->xch, domid, uuid, auth);
- if (r < 0) {
- LOGED(ERROR, domid, "Can not set tmem shared auth");
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = 0;
-out:
- GC_FREE;
- return rc;
-}
-
-int libxl_tmem_freeable(libxl_ctx *ctx)
-{
- int r, rc;
- GC_INIT(ctx);
-
- r = xc_tmem_control(ctx->xch, -1, XEN_SYSCTL_TMEM_OP_QUERY_FREEABLE_MB,
- -1, 0, 0, 0);
- if (r < 0) {
- LOGE(ERROR, "Can not get tmem freeable memory");
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = 0;
-out:
- GC_FREE;
- return rc;
-}
-
static int fd_set_flags(libxl_ctx *ctx, int fd,
int fcntlgetop, int fcntlsetop, const char *fl,
int flagmask, int set_p)
diff --git a/tools/libxl/libxl_tmem.c b/tools/libxl/libxl_tmem.c
new file mode 100644
index 0000000..2bee8d1
--- /dev/null
+++ b/tools/libxl/libxl_tmem.c
@@ -0,0 +1,167 @@
+/*
+ * 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"
+
+char *libxl_tmem_list(libxl_ctx *ctx, uint32_t domid, int use_long)
+{
+ int r;
+ char _buf[32768];
+ GC_INIT(ctx);
+
+ r = xc_tmem_control(ctx->xch, -1, XEN_SYSCTL_TMEM_OP_LIST, domid, 32768,
+ use_long, _buf);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Can not get tmem list");
+ GC_FREE;
+ return NULL;
+ }
+
+ GC_FREE;
+ return strdup(_buf);
+}
+
+int libxl_tmem_freeze(libxl_ctx *ctx, uint32_t domid)
+{
+ int r, rc;
+ GC_INIT(ctx);
+
+ r = xc_tmem_control(ctx->xch, -1, XEN_SYSCTL_TMEM_OP_FREEZE, domid, 0, 0,
+ NULL);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Can not freeze tmem pools");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl_tmem_thaw(libxl_ctx *ctx, uint32_t domid)
+{
+ int r, rc;
+ GC_INIT(ctx);
+
+ r = xc_tmem_control(ctx->xch, -1, XEN_SYSCTL_TMEM_OP_THAW, domid, 0, 0,
+ NULL);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Can not thaw tmem pools");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+out:
+ GC_FREE;
+ return rc;
+}
+
+static int32_t tmem_setop_from_string(char *set_name, uint32_t val,
+ xen_tmem_client_t *info)
+{
+ if (!strcmp(set_name, "weight"))
+ info->weight = val;
+ else if (!strcmp(set_name, "compress"))
+ info->flags.u.compress = val;
+ else
+ return -1;
+
+ return 0;
+}
+
+int libxl_tmem_set(libxl_ctx *ctx, uint32_t domid, char* name, uint32_t set)
+{
+ int r, rc;
+ xen_tmem_client_t info;
+ GC_INIT(ctx);
+
+ r = xc_tmem_control(ctx->xch, -1 /* pool_id */,
+ XEN_SYSCTL_TMEM_OP_GET_CLIENT_INFO,
+ domid, sizeof(info), 0 /* arg */, &info);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Can not get tmem data!");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ rc = tmem_setop_from_string(name, set, &info);
+ if (rc == -1) {
+ LOGEVD(ERROR, -1, domid, "Invalid set, valid sets are <weight|compress>");
+ rc = ERROR_INVAL;
+ goto out;
+ }
+ r = xc_tmem_control(ctx->xch, -1 /* pool_id */,
+ XEN_SYSCTL_TMEM_OP_SET_CLIENT_INFO,
+ domid, sizeof(info), 0 /* arg */, &info);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Can not set tmem %s", name);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl_tmem_shared_auth(libxl_ctx *ctx, uint32_t domid,
+ char* uuid, int auth)
+{
+ int r, rc;
+ GC_INIT(ctx);
+
+ r = xc_tmem_auth(ctx->xch, domid, uuid, auth);
+ if (r < 0) {
+ LOGED(ERROR, domid, "Can not set tmem shared auth");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl_tmem_freeable(libxl_ctx *ctx)
+{
+ int r, rc;
+ GC_INIT(ctx);
+
+ r = xc_tmem_control(ctx->xch, -1, XEN_SYSCTL_TMEM_OP_QUERY_FREEABLE_MB,
+ -1, 0, 0, 0);
+ if (r < 0) {
+ LOGE(ERROR, "Can not get tmem freeable memory");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+out:
+ GC_FREE;
+ return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 11/12] libxl: carve out domain specific functions from libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (9 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 10/12] libxl: carve out tmem specific functions from libxl.c Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 9:30 ` [PATCH v2 12/12] libxl: make one function static Juergen Gross
` (2 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
libxl.c has grown to an uncomfortable size. Carve out the domain
related functions to libxl_domain.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/Makefile | 1 +
tools/libxl/libxl.c | 1722 -------------------------------------------
tools/libxl/libxl_domain.c | 1744 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1745 insertions(+), 1722 deletions(-)
create mode 100644 tools/libxl/libxl_domain.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 99ddae1..6cc7b45 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -138,6 +138,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.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_mem.o libxl_sched.o libxl_tmem.o \
+ libxl_domain.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 67c0a13..0ef8744 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -16,8 +16,6 @@
#include "libxl_internal.h"
-#define PAGE_TO_MEMKB(pages) ((pages) * 4)
-
int libxl_ctx_alloc(libxl_ctx **pctx, int version,
unsigned flags, xentoollog_logger * lg)
{
@@ -353,1188 +351,6 @@ const char *libxl_defbool_to_string(libxl_defbool b)
}
/******************************************************************************/
-int libxl__domain_rename(libxl__gc *gc, uint32_t domid,
- const char *old_name, const char *new_name,
- xs_transaction_t trans)
-{
- libxl_ctx *ctx = libxl__gc_owner(gc);
- char *dom_path = 0;
- const char *name_path;
- char *got_old_name;
- unsigned int got_old_len;
- xs_transaction_t our_trans = 0;
- uint32_t stub_dm_domid;
- const char *stub_dm_old_name = NULL, *stub_dm_new_name = NULL;
- int rc;
- libxl_dominfo info;
- char *uuid;
- const char *vm_name_path;
-
- libxl_dominfo_init(&info);
-
- dom_path = libxl__xs_get_dompath(gc, domid);
- if (!dom_path) goto x_nomem;
-
- name_path= GCSPRINTF("%s/name", dom_path);
- if (!name_path) goto x_nomem;
-
- stub_dm_domid = libxl_get_stubdom_id(CTX, domid);
- if (stub_dm_domid) {
- stub_dm_old_name = libxl__stub_dm_name(gc, old_name);
- stub_dm_new_name = libxl__stub_dm_name(gc, new_name);
- }
-
- retry_transaction:
- if (!trans) {
- trans = our_trans = xs_transaction_start(ctx->xsh);
- if (!our_trans) {
- LOGEVD(ERROR, errno, domid, "Create xs transaction for domain (re)name");
- goto x_fail;
- }
- }
-
- if (!new_name) {
- LOGD(ERROR, domid, "New domain name not specified");
- rc = ERROR_INVAL;
- goto x_rc;
- }
-
- if (new_name[0]) {
- /* nonempty names must be unique */
- uint32_t domid_e;
- rc = libxl_name_to_domid(ctx, new_name, &domid_e);
- if (rc == ERROR_INVAL) {
- /* no such domain, good */
- } else if (rc != 0) {
- LOGD(ERROR, domid, "Unexpected error checking for existing domain");
- goto x_rc;
- } else if (domid_e == domid) {
- /* domain already has this name, ok (but we do still
- * need the rest of the code as we may need to check
- * old_name, for example). */
- } else {
- LOGD(ERROR, domid, "Domain with name \"%s\" already exists.", new_name);
- rc = ERROR_INVAL;
- goto x_rc;
- }
- }
-
- if (old_name) {
- got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
- if (!got_old_name) {
- LOGEVD(ERROR, errno, domid,
- "Check old name for domain allegedly named `%s'",
- old_name);
- goto x_fail;
- }
- if (strcmp(old_name, got_old_name)) {
- LOGD(ERROR, domid,
- "Allegedly named `%s' is actually named `%s' - racing ?",
- old_name,
- got_old_name);
- free(got_old_name);
- goto x_fail;
- }
- free(got_old_name);
- }
- if (!xs_write(ctx->xsh, trans, name_path,
- new_name, strlen(new_name))) {
- LOGD(ERROR, domid,
- "Failed to write new name `%s'"
- " for domain previously named `%s'",
- new_name,
- old_name);
- goto x_fail;
- }
-
- /* update /vm/<uuid>/name */
- rc = libxl_domain_info(ctx, &info, domid);
- if (rc)
- goto x_rc;
-
- uuid = GCSPRINTF(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info.uuid));
- vm_name_path = GCSPRINTF("/vm/%s/name", uuid);
- if (libxl__xs_write_checked(gc, trans, vm_name_path, new_name))
- goto x_fail;
-
- if (stub_dm_domid) {
- rc = libxl__domain_rename(gc, stub_dm_domid,
- stub_dm_old_name,
- stub_dm_new_name,
- trans);
- if (rc) {
- LOGED(ERROR, domid, "Unable to rename stub-domain");
- goto x_rc;
- }
- }
-
- if (our_trans) {
- if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
- trans = our_trans = 0;
- if (errno != EAGAIN) {
- LOGD(ERROR, domid,
- "Failed to commit new name `%s'"
- " for domain previously named `%s'",
- new_name,
- old_name);
- goto x_fail;
- }
- LOGD(DEBUG, domid,
- "Need to retry rename transaction"
- " for domain (name_path=\"%s\", new_name=\"%s\")",
- name_path,
- new_name);
- goto retry_transaction;
- }
- our_trans = 0;
- }
-
- rc = 0;
- x_rc:
- if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
- libxl_dominfo_dispose(&info);
- return rc;
-
- x_fail: rc = ERROR_FAIL; goto x_rc;
- x_nomem: rc = ERROR_NOMEM; goto x_rc;
-}
-
-int libxl_domain_rename(libxl_ctx *ctx, uint32_t domid,
- const char *old_name, const char *new_name)
-{
- GC_INIT(ctx);
- int rc;
- rc = libxl__domain_rename(gc, domid, old_name, new_name, XBT_NULL);
- GC_FREE;
- return rc;
-}
-
-int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid, int suspend_cancel,
- const libxl_asyncop_how *ao_how)
-{
- AO_CREATE(ctx, domid, ao_how);
- int rc = libxl__domain_resume(gc, domid, suspend_cancel);
- libxl__ao_complete(egc, ao, rc);
- return AO_INPROGRESS;
-}
-
-/*
- * Preserves a domain but rewrites xenstore etc to make it unique so
- * that the domain can be restarted.
- *
- * Does not modify info so that it may be reused.
- */
-int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid,
- libxl_domain_create_info *info, const char *name_suffix, libxl_uuid new_uuid)
-{
- GC_INIT(ctx);
- struct xs_permissions roperm[2];
- xs_transaction_t t;
- char *preserved_name;
- char *uuid_string;
- char *vm_path;
- char *dom_path;
-
- int rc;
-
- preserved_name = GCSPRINTF("%s%s", info->name, name_suffix);
- if (!preserved_name) {
- GC_FREE;
- return ERROR_NOMEM;
- }
-
- uuid_string = libxl__uuid2string(gc, new_uuid);
- if (!uuid_string) {
- GC_FREE;
- return ERROR_NOMEM;
- }
-
- dom_path = libxl__xs_get_dompath(gc, domid);
- if (!dom_path) {
- GC_FREE;
- return ERROR_FAIL;
- }
-
- vm_path = GCSPRINTF("/vm/%s", uuid_string);
- if (!vm_path) {
- GC_FREE;
- return ERROR_FAIL;
- }
-
- roperm[0].id = 0;
- roperm[0].perms = XS_PERM_NONE;
- roperm[1].id = domid;
- roperm[1].perms = XS_PERM_READ;
-
- retry_transaction:
- t = xs_transaction_start(ctx->xsh);
-
- xs_rm(ctx->xsh, t, vm_path);
- xs_mkdir(ctx->xsh, t, vm_path);
- xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
-
- xs_write(ctx->xsh, t, GCSPRINTF("%s/vm", dom_path), vm_path, strlen(vm_path));
- rc = libxl__domain_rename(gc, domid, info->name, preserved_name, t);
- if (rc) {
- GC_FREE;
- return rc;
- }
-
- xs_write(ctx->xsh, t, GCSPRINTF("%s/uuid", vm_path), uuid_string, strlen(uuid_string));
-
- if (!xs_transaction_end(ctx->xsh, t, 0))
- if (errno == EAGAIN)
- goto retry_transaction;
-
- GC_FREE;
- return 0;
-}
-
-void xcinfo2xlinfo(libxl_ctx *ctx,
- const xc_domaininfo_t *xcinfo,
- libxl_dominfo *xlinfo)
-{
- size_t size;
-
- memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t));
- xlinfo->domid = xcinfo->domain;
- xlinfo->ssidref = xcinfo->ssidref;
- if (libxl_flask_sid_to_context(ctx, xlinfo->ssidref,
- &xlinfo->ssid_label, &size) < 0)
- xlinfo->ssid_label = NULL;
-
- xlinfo->dying = !!(xcinfo->flags&XEN_DOMINF_dying);
- xlinfo->shutdown = !!(xcinfo->flags&XEN_DOMINF_shutdown);
- xlinfo->paused = !!(xcinfo->flags&XEN_DOMINF_paused);
- xlinfo->blocked = !!(xcinfo->flags&XEN_DOMINF_blocked);
- xlinfo->running = !!(xcinfo->flags&XEN_DOMINF_running);
- xlinfo->never_stop = !!(xcinfo->flags&XEN_DOMINF_xs_domain);
-
- if (xlinfo->shutdown)
- xlinfo->shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask;
- else
- xlinfo->shutdown_reason = LIBXL_SHUTDOWN_REASON_UNKNOWN;
-
- xlinfo->outstanding_memkb = PAGE_TO_MEMKB(xcinfo->outstanding_pages);
- xlinfo->current_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages);
- xlinfo->shared_memkb = PAGE_TO_MEMKB(xcinfo->shr_pages);
- xlinfo->paged_memkb = PAGE_TO_MEMKB(xcinfo->paged_pages);
- xlinfo->max_memkb = PAGE_TO_MEMKB(xcinfo->max_pages);
- xlinfo->cpu_time = xcinfo->cpu_time;
- xlinfo->vcpu_max_id = xcinfo->max_vcpu_id;
- xlinfo->vcpu_online = xcinfo->nr_online_vcpus;
- xlinfo->cpupool = xcinfo->cpupool;
- xlinfo->domain_type = (xcinfo->flags & XEN_DOMINF_hvm_guest) ?
- LIBXL_DOMAIN_TYPE_HVM : LIBXL_DOMAIN_TYPE_PV;
-}
-
-libxl_dominfo * libxl_list_domain(libxl_ctx *ctx, int *nb_domain_out)
-{
- libxl_dominfo *ptr = NULL;
- int i, ret;
- xc_domaininfo_t info[1024];
- int size = 0;
- uint32_t domid = 0;
- GC_INIT(ctx);
-
- while ((ret = xc_domain_getinfolist(ctx->xch, domid, 1024, info)) > 0) {
- ptr = libxl__realloc(NOGC, ptr, (size + ret) * sizeof(libxl_dominfo));
- for (i = 0; i < ret; i++) {
- xcinfo2xlinfo(ctx, &info[i], &ptr[size + i]);
- }
- domid = info[ret - 1].domain + 1;
- size += ret;
- }
-
- if (ret < 0) {
- LOGE(ERROR, "getting domain info list");
- free(ptr);
- GC_FREE;
- return NULL;
- }
-
- *nb_domain_out = size;
- GC_FREE;
- return ptr;
-}
-
-int libxl_domain_info(libxl_ctx *ctx, libxl_dominfo *info_r,
- uint32_t domid) {
- xc_domaininfo_t xcinfo;
- int ret;
- GC_INIT(ctx);
-
- ret = xc_domain_getinfolist(ctx->xch, domid, 1, &xcinfo);
- if (ret<0) {
- LOGED(ERROR, domid, "Getting domain info list");
- GC_FREE;
- return ERROR_FAIL;
- }
- if (ret==0 || xcinfo.domain != domid) {
- GC_FREE;
- return ERROR_DOMAIN_NOTFOUND;
- }
-
- if (info_r)
- xcinfo2xlinfo(ctx, &xcinfo, info_r);
- GC_FREE;
- return 0;
-}
-
-/* this API call only list VM running on this host. A VM can
- * be an aggregate of multiple domains. */
-libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm_out)
-{
- GC_INIT(ctx);
- libxl_dominfo *info;
- libxl_vminfo *ptr = NULL;
- int idx, i, n_doms;
-
- info = libxl_list_domain(ctx, &n_doms);
- if (!info)
- goto out;
-
- /*
- * Always make sure to allocate at least one element; if we don't and we
- * request zero, libxl__calloc (might) think its internal call to calloc
- * has failed (if it returns null), if so it would kill our process.
- */
- ptr = libxl__calloc(NOGC, n_doms ? n_doms : 1, sizeof(libxl_vminfo));
-
- for (idx = i = 0; i < n_doms; i++) {
- if (libxl_is_stubdom(ctx, info[i].domid, NULL))
- continue;
- ptr[idx].uuid = info[i].uuid;
- ptr[idx].domid = info[i].domid;
-
- idx++;
- }
- *nb_vm_out = idx;
- libxl_dominfo_list_free(info, n_doms);
-
-out:
- GC_FREE;
- return ptr;
-}
-
-static void remus_failover_cb(libxl__egc *egc,
- libxl__domain_save_state *dss, int rc);
-
-int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
- uint32_t domid, int send_fd, int recv_fd,
- const libxl_asyncop_how *ao_how)
-{
- AO_CREATE(ctx, domid, ao_how);
- libxl__domain_save_state *dss;
- int rc;
-
- libxl_domain_type type = libxl__domain_type(gc, domid);
- if (type == LIBXL_DOMAIN_TYPE_INVALID) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- /* The caller must set this defbool */
- if (libxl_defbool_is_default(info->colo)) {
- LOGD(ERROR, domid, "Colo mode must be enabled/disabled");
- rc = ERROR_FAIL;
- goto out;
- }
-
- libxl_defbool_setdefault(&info->allow_unsafe, false);
- libxl_defbool_setdefault(&info->blackhole, false);
- libxl_defbool_setdefault(&info->compression,
- !libxl_defbool_val(info->colo));
- libxl_defbool_setdefault(&info->netbuf, true);
- libxl_defbool_setdefault(&info->diskbuf, true);
-
- if (libxl_defbool_val(info->colo) &&
- libxl_defbool_val(info->compression)) {
- LOGD(ERROR, domid, "Cannot use memory checkpoint "
- "compression in COLO mode");
- rc = ERROR_FAIL;
- goto out;
- }
-
- if (!libxl_defbool_val(info->allow_unsafe) &&
- (libxl_defbool_val(info->blackhole) ||
- !libxl_defbool_val(info->netbuf) ||
- !libxl_defbool_val(info->diskbuf))) {
- LOGD(ERROR, domid, "Unsafe mode must be enabled to replicate to /dev/null,"
- "disable network buffering and disk replication");
- rc = ERROR_FAIL;
- goto out;
- }
-
-
- GCNEW(dss);
- dss->ao = ao;
- dss->callback = remus_failover_cb;
- dss->domid = domid;
- dss->fd = send_fd;
- dss->recv_fd = recv_fd;
- dss->type = type;
- dss->live = 1;
- dss->debug = 0;
- dss->remus = info;
- if (libxl_defbool_val(info->colo))
- dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_COLO;
- else
- dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_REMUS;
-
- assert(info);
-
- /* Point of no return */
- if (libxl_defbool_val(info->colo))
- libxl__colo_save_setup(egc, &dss->css);
- else
- libxl__remus_setup(egc, &dss->rs);
- return AO_INPROGRESS;
-
- out:
- return AO_CREATE_FAIL(rc);
-}
-
-static void remus_failover_cb(libxl__egc *egc,
- libxl__domain_save_state *dss, int rc)
-{
- STATE_AO_GC(dss->ao);
- /*
- * With Remus, if we reach this point, it means either
- * backup died or some network error occurred preventing us
- * from sending checkpoints.
- */
- libxl__ao_complete(egc, ao, rc);
-}
-
-static void domain_suspend_cb(libxl__egc *egc,
- libxl__domain_save_state *dss, int rc)
-{
- STATE_AO_GC(dss->ao);
- int flrc;
-
- flrc = libxl__fd_flags_restore(gc, dss->fd, dss->fdfl);
- /* If suspend has failed already then report that error not this one. */
- if (flrc && !rc) rc = flrc;
-
- libxl__ao_complete(egc,ao,rc);
-
-}
-
-int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
- const libxl_asyncop_how *ao_how)
-{
- AO_CREATE(ctx, domid, ao_how);
- int rc;
-
- libxl_domain_type type = libxl__domain_type(gc, domid);
- if (type == LIBXL_DOMAIN_TYPE_INVALID) {
- rc = ERROR_FAIL;
- goto out_err;
- }
-
- libxl__domain_save_state *dss;
- GCNEW(dss);
-
- dss->ao = ao;
- dss->callback = domain_suspend_cb;
-
- dss->domid = domid;
- dss->fd = fd;
- dss->type = type;
- dss->live = flags & LIBXL_SUSPEND_LIVE;
- dss->debug = flags & LIBXL_SUSPEND_DEBUG;
- dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_NONE;
-
- rc = libxl__fd_flags_modify_save(gc, dss->fd,
- ~(O_NONBLOCK|O_NDELAY), 0,
- &dss->fdfl);
- if (rc < 0) goto out_err;
-
- libxl__domain_save(egc, dss);
- return AO_INPROGRESS;
-
- out_err:
- return AO_CREATE_FAIL(rc);
-}
-
-int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid)
-{
- int ret;
- GC_INIT(ctx);
- ret = xc_domain_pause(ctx->xch, domid);
- if (ret<0) {
- LOGED(ERROR, domid, "Pausing domain");
- GC_FREE;
- return ERROR_FAIL;
- }
- GC_FREE;
- return 0;
-}
-
-int libxl_domain_core_dump(libxl_ctx *ctx, uint32_t domid,
- const char *filename,
- const libxl_asyncop_how *ao_how)
-{
- AO_CREATE(ctx, domid, ao_how);
- int ret, rc;
-
- ret = xc_domain_dumpcore(ctx->xch, domid, filename);
- if (ret<0) {
- LOGED(ERROR, domid, "Core dumping domain to %s", filename);
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = 0;
-out:
-
- libxl__ao_complete(egc, ao, rc);
-
- return AO_INPROGRESS;
-}
-
-int libxl_domain_unpause(libxl_ctx *ctx, uint32_t domid)
-{
- GC_INIT(ctx);
- int ret, rc = 0;
-
- libxl_domain_type type = libxl__domain_type(gc, domid);
- if (type == LIBXL_DOMAIN_TYPE_INVALID) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- if (type == LIBXL_DOMAIN_TYPE_HVM) {
- if (libxl__device_model_version_running(gc, domid) !=
- LIBXL_DEVICE_MODEL_VERSION_NONE) {
- rc = libxl__domain_resume_device_model(gc, domid);
- if (rc < 0) {
- LOGD(ERROR, domid, "Failed to unpause device model for domain:%d",
- rc);
- goto out;
- }
- }
- }
- ret = xc_domain_unpause(ctx->xch, domid);
- if (ret<0) {
- LOGED(ERROR, domid, "Unpausing domain");
- rc = ERROR_FAIL;
- }
- out:
- GC_FREE;
- return rc;
-}
-
-int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid)
-{
- libxl_ctx *ctx = libxl__gc_owner(gc);
-
- uint64_t pvdriver = 0;
- int ret;
-
- libxl_domain_type domtype = libxl__domain_type(gc, domid);
- if (domtype == LIBXL_DOMAIN_TYPE_INVALID)
- return ERROR_FAIL;
-
- if (domtype == LIBXL_DOMAIN_TYPE_PV)
- return 1;
-
- ret = xc_hvm_param_get(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
- if (ret<0) {
- LOGED(ERROR, domid, "Getting HVM callback IRQ");
- return ERROR_FAIL;
- }
- return !!pvdriver;
-}
-
-const char *libxl__domain_pvcontrol_xspath(libxl__gc *gc, uint32_t domid)
-{
- const char *dom_path;
-
- dom_path = libxl__xs_get_dompath(gc, domid);
- if (!dom_path)
- return NULL;
-
- return GCSPRINTF("%s/control/shutdown", dom_path);
-}
-
-char * libxl__domain_pvcontrol_read(libxl__gc *gc, xs_transaction_t t,
- uint32_t domid)
-{
- const char *shutdown_path;
-
- shutdown_path = libxl__domain_pvcontrol_xspath(gc, domid);
- if (!shutdown_path)
- return NULL;
-
- return libxl__xs_read(gc, t, shutdown_path);
-}
-
-int libxl__domain_pvcontrol_write(libxl__gc *gc, xs_transaction_t t,
- uint32_t domid, const char *cmd)
-{
- const char *shutdown_path;
-
- shutdown_path = libxl__domain_pvcontrol_xspath(gc, domid);
- if (!shutdown_path)
- return ERROR_FAIL;
-
- return libxl__xs_printf(gc, t, shutdown_path, "%s", cmd);
-}
-
-static int libxl__domain_pvcontrol(libxl__gc *gc, uint32_t domid,
- const char *cmd)
-{
- int ret;
-
- ret = libxl__domain_pvcontrol_available(gc, domid);
- if (ret < 0)
- return ret;
-
- if (!ret)
- return ERROR_NOPARAVIRT;
-
- return libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, cmd);
-}
-
-int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid)
-{
- GC_INIT(ctx);
- int ret;
- ret = libxl__domain_pvcontrol(gc, domid, "poweroff");
- GC_FREE;
- return ret;
-}
-
-int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid)
-{
- GC_INIT(ctx);
- int ret;
- ret = libxl__domain_pvcontrol(gc, domid, "reboot");
- GC_FREE;
- return ret;
-}
-
-static void domain_death_occurred(libxl__egc *egc,
- libxl_evgen_domain_death **evg_upd,
- const char *why) {
- /* Removes **evg_upd from death_list and puts it on death_reported
- * and advances *evg_upd to the next entry.
- * Call sites in domain_death_xswatch_callback must use "continue". */
- EGC_GC;
- libxl_evgen_domain_death *const evg = *evg_upd;
-
- LOGD(DEBUG, evg->domid, "%s", why);
-
- libxl_evgen_domain_death *evg_next = LIBXL_TAILQ_NEXT(evg, entry);
- *evg_upd = evg_next;
-
- libxl_event *ev = NEW_EVENT(egc, DOMAIN_DEATH, evg->domid, evg->user);
-
- libxl__event_occurred(egc, ev);
-
- evg->death_reported = 1;
- LIBXL_TAILQ_REMOVE(&CTX->death_list, evg, entry);
- LIBXL_TAILQ_INSERT_HEAD(&CTX->death_reported, evg, entry);
-}
-
-static void domain_death_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
- const char *wpath, const char *epath) {
- EGC_GC;
- libxl_evgen_domain_death *evg;
- int rc;
-
- CTX_LOCK;
-
- evg = LIBXL_TAILQ_FIRST(&CTX->death_list);
-
- for (;;) {
- if (!evg) goto out;
-
- int nentries = LIBXL_TAILQ_NEXT(evg, entry) ? 200 : 1;
- xc_domaininfo_t domaininfos[nentries];
- const xc_domaininfo_t *got = domaininfos, *gotend;
-
- rc = xc_domain_getinfolist(CTX->xch, evg->domid, nentries, domaininfos);
- if (rc == -1) {
- LIBXL__EVENT_DISASTER(egc, "xc_domain_getinfolist failed while"
- " processing @releaseDomain watch event",
- errno, 0);
- goto out;
- }
- gotend = &domaininfos[rc];
-
- LOGD(DEBUG, evg->domid, "[evg=%p] nentries=%d rc=%d %ld..%ld",
- evg, nentries, rc,
- rc>0 ? (long)domaininfos[0].domain : 0,
- rc>0 ? (long)domaininfos[rc-1].domain : 0);
-
- for (;;) {
- if (!evg) {
- LOG(DEBUG, "[evg=0] all reported");
- goto all_reported;
- }
-
- LOGD(DEBUG, evg->domid, "[evg=%p]"
- " got=domaininfos[%d] got->domain=%ld",
- evg, (int)(got - domaininfos),
- got < gotend ? (long)got->domain : -1L);
-
- if (!rc) {
- domain_death_occurred(egc, &evg, "empty list");
- continue;
- }
-
- if (got == gotend) {
- LOG(DEBUG, " got==gotend");
- break;
- }
-
- if (got->domain > evg->domid) {
- /* ie, the list doesn't contain evg->domid any more so
- * the domain has been destroyed */
- domain_death_occurred(egc, &evg, "missing from list");
- continue;
- }
-
- if (got->domain < evg->domid) {
- got++;
- continue;
- }
-
- assert(evg->domid == got->domain);
- LOGD(DEBUG, evg->domid, "Exists shutdown_reported=%d"" dominf.flags=%x",
- evg->shutdown_reported, got->flags);
-
- if (got->flags & XEN_DOMINF_dying) {
- domain_death_occurred(egc, &evg, "dying");
- continue;
- }
-
- if (!evg->shutdown_reported &&
- (got->flags & XEN_DOMINF_shutdown)) {
- libxl_event *ev = NEW_EVENT(egc, DOMAIN_SHUTDOWN,
- got->domain, evg->user);
-
- LOG(DEBUG, " shutdown reporting");
-
- ev->u.domain_shutdown.shutdown_reason =
- (got->flags >> XEN_DOMINF_shutdownshift) &
- XEN_DOMINF_shutdownmask;
- libxl__event_occurred(egc, ev);
-
- evg->shutdown_reported = 1;
- }
- evg = LIBXL_TAILQ_NEXT(evg, entry);
- }
-
- assert(rc); /* rc==0 results in us eating all evgs and quitting */
- }
- all_reported:
- out:
-
- LOG(DEBUG, "domain death search done");
-
- CTX_UNLOCK;
-}
-
-int libxl_evenable_domain_death(libxl_ctx *ctx, uint32_t domid,
- libxl_ev_user user, libxl_evgen_domain_death **evgen_out) {
- GC_INIT(ctx);
- libxl_evgen_domain_death *evg, *evg_search;
- int rc;
-
- CTX_LOCK;
-
- evg = malloc(sizeof(*evg)); if (!evg) { rc = ERROR_NOMEM; goto out; }
- memset(evg, 0, sizeof(*evg));
- evg->domid = domid;
- evg->user = user;
-
- LIBXL_TAILQ_INSERT_SORTED(&ctx->death_list, entry, evg, evg_search, ,
- evg->domid > evg_search->domid);
-
- if (!libxl__ev_xswatch_isregistered(&ctx->death_watch)) {
- rc = libxl__ev_xswatch_register(gc, &ctx->death_watch,
- domain_death_xswatch_callback, "@releaseDomain");
- if (rc) { libxl__evdisable_domain_death(gc, evg); goto out; }
- }
-
- *evgen_out = evg;
- rc = 0;
-
- out:
- CTX_UNLOCK;
- GC_FREE;
- return rc;
-};
-
-void libxl__evdisable_domain_death(libxl__gc *gc,
- libxl_evgen_domain_death *evg) {
- CTX_LOCK;
-
- if (!evg->death_reported)
- LIBXL_TAILQ_REMOVE(&CTX->death_list, evg, entry);
- else
- LIBXL_TAILQ_REMOVE(&CTX->death_reported, evg, entry);
-
- free(evg);
-
- if (!LIBXL_TAILQ_FIRST(&CTX->death_list) &&
- libxl__ev_xswatch_isregistered(&CTX->death_watch))
- libxl__ev_xswatch_deregister(gc, &CTX->death_watch);
-
- CTX_UNLOCK;
-}
-
-void libxl_evdisable_domain_death(libxl_ctx *ctx,
- libxl_evgen_domain_death *evg) {
- GC_INIT(ctx);
- libxl__evdisable_domain_death(gc, evg);
- GC_FREE;
-}
-
-/* Callbacks for libxl_domain_destroy */
-
-static void domain_destroy_cb(libxl__egc *egc, libxl__domain_destroy_state *dds,
- int rc);
-
-int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid,
- const libxl_asyncop_how *ao_how)
-{
- AO_CREATE(ctx, domid, ao_how);
- libxl__domain_destroy_state *dds;
-
- GCNEW(dds);
- dds->ao = ao;
- dds->domid = domid;
- dds->callback = domain_destroy_cb;
- libxl__domain_destroy(egc, dds);
-
- return AO_INPROGRESS;
-}
-
-static void domain_destroy_cb(libxl__egc *egc, libxl__domain_destroy_state *dds,
- int rc)
-{
- STATE_AO_GC(dds->ao);
-
- if (rc)
- LOGD(ERROR, dds->domid, "Destruction of domain failed");
-
- libxl__ao_complete(egc, ao, rc);
-}
-
-/* Callbacks for libxl__domain_destroy */
-
-static void stubdom_destroy_callback(libxl__egc *egc,
- libxl__destroy_domid_state *dis,
- int rc);
-
-static void domain_destroy_callback(libxl__egc *egc,
- libxl__destroy_domid_state *dis,
- int rc);
-
-static void destroy_finish_check(libxl__egc *egc,
- libxl__domain_destroy_state *dds);
-
-void libxl__domain_destroy(libxl__egc *egc, libxl__domain_destroy_state *dds)
-{
- STATE_AO_GC(dds->ao);
- uint32_t stubdomid = libxl_get_stubdom_id(CTX, dds->domid);
-
- if (stubdomid) {
- dds->stubdom.ao = ao;
- dds->stubdom.domid = stubdomid;
- dds->stubdom.callback = stubdom_destroy_callback;
- dds->stubdom.soft_reset = false;
- libxl__destroy_domid(egc, &dds->stubdom);
- } else {
- dds->stubdom_finished = 1;
- }
-
- dds->domain.ao = ao;
- dds->domain.domid = dds->domid;
- dds->domain.callback = domain_destroy_callback;
- dds->domain.soft_reset = dds->soft_reset;
- libxl__destroy_domid(egc, &dds->domain);
-}
-
-static void stubdom_destroy_callback(libxl__egc *egc,
- libxl__destroy_domid_state *dis,
- int rc)
-{
- STATE_AO_GC(dis->ao);
- libxl__domain_destroy_state *dds = CONTAINER_OF(dis, *dds, stubdom);
- const char *savefile;
-
- if (rc) {
- LOGD(ERROR, dds->domain.domid, "Unable to destroy stubdom with domid %u",
- dis->domid);
- dds->rc = rc;
- }
-
- dds->stubdom_finished = 1;
- savefile = libxl__device_model_savefile(gc, dis->domid);
- rc = libxl__remove_file(gc, savefile);
- if (rc) {
- LOGD(ERROR, dds->domain.domid, "Failed to remove device-model savefile %s",
- savefile);
- }
-
- destroy_finish_check(egc, dds);
-}
-
-static void domain_destroy_callback(libxl__egc *egc,
- libxl__destroy_domid_state *dis,
- int rc)
-{
- STATE_AO_GC(dis->ao);
- libxl__domain_destroy_state *dds = CONTAINER_OF(dis, *dds, domain);
-
- if (rc) {
- LOGD(ERROR, dis->domid, "Unable to destroy guest");
- dds->rc = rc;
- }
-
- dds->domain_finished = 1;
- destroy_finish_check(egc, dds);
-}
-
-static void destroy_finish_check(libxl__egc *egc,
- libxl__domain_destroy_state *dds)
-{
- if (!(dds->domain_finished && dds->stubdom_finished))
- return;
-
- dds->callback(egc, dds, dds->rc);
-}
-
-/* Callbacks for libxl__destroy_domid */
-static void devices_destroy_cb(libxl__egc *egc,
- libxl__devices_remove_state *drs,
- int rc);
-
-static void domain_destroy_domid_cb(libxl__egc *egc,
- libxl__ev_child *destroyer,
- pid_t pid, int status);
-
-void libxl__destroy_domid(libxl__egc *egc, libxl__destroy_domid_state *dis)
-{
- STATE_AO_GC(dis->ao);
- libxl_ctx *ctx = CTX;
- uint32_t domid = dis->domid;
- char *dom_path;
- int rc, dm_present;
-
- libxl__ev_child_init(&dis->destroyer);
-
- rc = libxl_domain_info(ctx, NULL, domid);
- switch(rc) {
- case 0:
- break;
- case ERROR_DOMAIN_NOTFOUND:
- LOGD(ERROR, domid, "Non-existant domain");
- default:
- goto out;
- }
-
- switch (libxl__domain_type(gc, domid)) {
- case LIBXL_DOMAIN_TYPE_HVM:
- if (libxl_get_stubdom_id(CTX, domid)) {
- dm_present = 0;
- break;
- }
- /* fall through */
- case LIBXL_DOMAIN_TYPE_PV:
- dm_present = libxl__dm_active(gc, domid);
- break;
- case LIBXL_DOMAIN_TYPE_INVALID:
- rc = ERROR_FAIL;
- goto out;
- default:
- abort();
- }
-
- dom_path = libxl__xs_get_dompath(gc, domid);
- if (!dom_path) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- if (libxl__device_pci_destroy_all(gc, domid) < 0)
- LOGD(ERROR, domid, "Pci shutdown failed");
- rc = xc_domain_pause(ctx->xch, domid);
- if (rc < 0) {
- LOGEVD(ERROR, rc, domid, "xc_domain_pause failed");
- }
- if (dm_present) {
- if (libxl__destroy_device_model(gc, domid) < 0)
- LOGD(ERROR, domid, "libxl__destroy_device_model failed");
-
- libxl__qmp_cleanup(gc, domid);
- }
- dis->drs.ao = ao;
- dis->drs.domid = domid;
- dis->drs.callback = devices_destroy_cb;
- dis->drs.force = 1;
- libxl__devices_destroy(egc, &dis->drs);
- return;
-
-out:
- assert(rc);
- dis->callback(egc, dis, rc);
- return;
-}
-
-static void devices_destroy_cb(libxl__egc *egc,
- libxl__devices_remove_state *drs,
- int rc)
-{
- STATE_AO_GC(drs->ao);
- libxl__destroy_domid_state *dis = CONTAINER_OF(drs, *dis, drs);
- libxl_ctx *ctx = CTX;
- uint32_t domid = dis->domid;
- char *dom_path;
- char *vm_path;
- libxl__domain_userdata_lock *lock;
-
- dom_path = libxl__xs_get_dompath(gc, domid);
- if (!dom_path) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- if (rc < 0)
- LOGD(ERROR, domid, "libxl__devices_destroy failed");
-
- vm_path = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/vm", dom_path));
- if (vm_path)
- if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
- LOGED(ERROR, domid, "xs_rm failed for %s", vm_path);
-
- if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
- LOGED(ERROR, domid, "xs_rm failed for %s", dom_path);
-
- xs_rm(ctx->xsh, XBT_NULL, libxl__xs_libxl_path(gc, domid));
- xs_rm(ctx->xsh, XBT_NULL, GCSPRINTF( "/local/domain/%d/hvmloader", domid));
-
- /* This is async operation, we already hold CTX lock */
- lock = libxl__lock_domain_userdata(gc, domid);
- if (!lock) {
- rc = ERROR_LOCK_FAIL;
- goto out;
- }
- libxl__userdata_destroyall(gc, domid);
-
- libxl__unlock_domain_userdata(lock);
-
- /* Clean up qemu-save and qemu-resume files. They are
- * intermediate files created by libxc. Unfortunately they
- * don't fit in existing userdata scheme very well. In soft reset
- * case we need to keep the file.
- */
- if (!dis->soft_reset) {
- rc = libxl__remove_file(gc,
- libxl__device_model_savefile(gc, domid));
- if (rc < 0) goto out;
- }
- rc = libxl__remove_file(gc,
- GCSPRINTF(LIBXL_DEVICE_MODEL_RESTORE_FILE".%u", domid));
- if (rc < 0) goto out;
-
- rc = libxl__ev_child_fork(gc, &dis->destroyer, domain_destroy_domid_cb);
- if (rc < 0) goto out;
- if (!rc) { /* child */
- ctx->xch = xc_interface_open(ctx->lg,0,0);
- if (!ctx->xch) goto badchild;
-
- if (!dis->soft_reset) {
- rc = xc_domain_destroy(ctx->xch, domid);
- } else {
- rc = xc_domain_pause(ctx->xch, domid);
- if (rc < 0) goto badchild;
- rc = xc_domain_soft_reset(ctx->xch, domid);
- if (rc < 0) goto badchild;
- rc = xc_domain_unpause(ctx->xch, domid);
- }
- if (rc < 0) goto badchild;
- _exit(0);
-
- badchild:
- if (errno > 0 && errno < 126) {
- _exit(errno);
- } else {
- LOGED(ERROR, domid,
- "xc_domain_destroy failed (with difficult errno value %d)",
- errno);
- _exit(-1);
- }
- }
- LOGD(DEBUG, domid, "Forked pid %ld for destroy of domain", (long)rc);
-
- return;
-
-out:
- dis->callback(egc, dis, rc);
- return;
-}
-
-static void domain_destroy_domid_cb(libxl__egc *egc,
- libxl__ev_child *destroyer,
- pid_t pid, int status)
-{
- libxl__destroy_domid_state *dis = CONTAINER_OF(destroyer, *dis, destroyer);
- STATE_AO_GC(dis->ao);
- int rc;
-
- if (status) {
- if (WIFEXITED(status) && WEXITSTATUS(status)<126) {
- LOGEVD(ERROR, WEXITSTATUS(status), dis->domid,
- "xc_domain_destroy failed");
- } else {
- libxl_report_child_exitstatus(CTX, XTL_ERROR,
- "async domain destroy", pid, status);
- }
- rc = ERROR_FAIL;
- goto out;
- }
- rc = 0;
-
- out:
- dis->callback(egc, dis, rc);
-}
-
-int libxl__get_domid(libxl__gc *gc, uint32_t *domid)
-{
- int rc;
- const char *xs_domid;
-
- rc = libxl__xs_read_checked(gc, XBT_NULL, DOMID_XS_PATH, &xs_domid);
- if (rc) goto out;
- if (!xs_domid) {
- LOG(ERROR, "failed to get own domid (%s)", DOMID_XS_PATH);
- rc = ERROR_FAIL;
- goto out;
- }
-
- *domid = atoi(xs_domid);
-
-out:
- return rc;
-}
-
-/******************************************************************************/
-
-int libxl__resolve_domid(libxl__gc *gc, const char *name, uint32_t *domid)
-{
- if (!name)
- return 0;
- return libxl_domain_qualifier_to_domid(CTX, name, domid);
-}
-
-/******************************************************************************/
int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
{
xc_physinfo_t xcphysinfo = { 0 };
@@ -1810,254 +626,6 @@ const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
return info;
}
-libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
- int *nr_vcpus_out, int *nr_cpus_out)
-{
- GC_INIT(ctx);
- libxl_vcpuinfo *ptr, *ret;
- xc_domaininfo_t domaininfo;
- xc_vcpuinfo_t vcpuinfo;
-
- if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
- LOGED(ERROR, domid, "Getting infolist");
- GC_FREE;
- return NULL;
- }
-
- if (domaininfo.max_vcpu_id == XEN_INVALID_MAX_VCPU_ID) {
- GC_FREE;
- return NULL;
- }
-
- *nr_cpus_out = libxl_get_max_cpus(ctx);
- ret = ptr = libxl__calloc(NOGC, domaininfo.max_vcpu_id + 1,
- sizeof(libxl_vcpuinfo));
-
- for (*nr_vcpus_out = 0;
- *nr_vcpus_out <= domaininfo.max_vcpu_id;
- ++*nr_vcpus_out, ++ptr) {
- libxl_bitmap_init(&ptr->cpumap);
- if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap, 0))
- goto err;
- libxl_bitmap_init(&ptr->cpumap_soft);
- if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap_soft, 0))
- goto err;
- if (xc_vcpu_getinfo(ctx->xch, domid, *nr_vcpus_out, &vcpuinfo) == -1) {
- LOGED(ERROR, domid, "Getting vcpu info");
- goto err;
- }
-
- if (xc_vcpu_getaffinity(ctx->xch, domid, *nr_vcpus_out,
- ptr->cpumap.map, ptr->cpumap_soft.map,
- XEN_VCPUAFFINITY_SOFT|XEN_VCPUAFFINITY_HARD) == -1) {
- LOGED(ERROR, domid, "Getting vcpu affinity");
- goto err;
- }
- ptr->vcpuid = *nr_vcpus_out;
- ptr->cpu = vcpuinfo.cpu;
- ptr->online = !!vcpuinfo.online;
- ptr->blocked = !!vcpuinfo.blocked;
- ptr->running = !!vcpuinfo.running;
- ptr->vcpu_time = vcpuinfo.cpu_time;
- }
- GC_FREE;
- return ret;
-
-err:
- libxl_bitmap_dispose(&ptr->cpumap);
- libxl_bitmap_dispose(&ptr->cpumap_soft);
- free(ret);
- GC_FREE;
- return NULL;
-}
-
-static int libxl__set_vcpuonline_xenstore(libxl__gc *gc, uint32_t domid,
- libxl_bitmap *cpumap,
- const libxl_dominfo *info)
-{
- char *dompath;
- xs_transaction_t t;
- int i, rc = ERROR_FAIL;
-
- if (!(dompath = libxl__xs_get_dompath(gc, domid)))
- goto out;
-
-retry_transaction:
- t = xs_transaction_start(CTX->xsh);
- for (i = 0; i <= info->vcpu_max_id; i++)
- libxl__xs_printf(gc, t,
- GCSPRINTF("%s/cpu/%u/availability", dompath, i),
- "%s", libxl_bitmap_test(cpumap, i) ? "online" : "offline");
- if (!xs_transaction_end(CTX->xsh, t, 0)) {
- if (errno == EAGAIN)
- goto retry_transaction;
- } else
- rc = 0;
-out:
- return rc;
-}
-
-static int libxl__set_vcpuonline_qmp(libxl__gc *gc, uint32_t domid,
- libxl_bitmap *cpumap,
- const libxl_dominfo *info)
-{
- int i, rc;
- libxl_bitmap current_map, final_map;
-
- libxl_bitmap_init(¤t_map);
- libxl_bitmap_init(&final_map);
-
- libxl_bitmap_alloc(CTX, ¤t_map, info->vcpu_max_id + 1);
- libxl_bitmap_set_none(¤t_map);
- rc = libxl__qmp_query_cpus(gc, domid, ¤t_map);
- if (rc) {
- LOGD(ERROR, domid, "Failed to query cpus");
- goto out;
- }
-
- libxl_bitmap_copy_alloc(CTX, &final_map, cpumap);
-
- libxl_for_each_set_bit(i, current_map)
- libxl_bitmap_reset(&final_map, i);
-
- libxl_for_each_set_bit(i, final_map) {
- rc = libxl__qmp_cpu_add(gc, domid, i);
- if (rc) {
- LOGD(ERROR, domid, "Failed to add cpu %d", i);
- goto out;
- }
- }
-
- rc = 0;
-out:
- libxl_bitmap_dispose(¤t_map);
- libxl_bitmap_dispose(&final_map);
- return rc;
-}
-
-int libxl_set_vcpuonline(libxl_ctx *ctx, uint32_t domid, libxl_bitmap *cpumap)
-{
- GC_INIT(ctx);
- int rc, maxcpus;
- libxl_dominfo info;
-
- libxl_dominfo_init(&info);
-
- rc = libxl_domain_info(CTX, &info, domid);
- if (rc < 0) {
- LOGED(ERROR, domid, "Getting domain info list");
- goto out;
- }
-
- maxcpus = libxl_bitmap_count_set(cpumap);
- if (maxcpus > info.vcpu_max_id + 1)
- {
- LOGED(ERROR, domid, "Requested %d VCPUs, however maxcpus is %d!",
- maxcpus, info.vcpu_max_id + 1);
- rc = ERROR_FAIL;
- goto out;
- }
-
- switch (libxl__domain_type(gc, domid)) {
- case LIBXL_DOMAIN_TYPE_HVM:
- switch (libxl__device_model_version_running(gc, domid)) {
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
- case LIBXL_DEVICE_MODEL_VERSION_NONE:
- break;
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
- rc = libxl__set_vcpuonline_qmp(gc, domid, cpumap, &info);
- break;
- default:
- rc = ERROR_INVAL;
- }
- break;
- case LIBXL_DOMAIN_TYPE_PV:
- break;
- default:
- rc = ERROR_INVAL;
- }
-
- if (!rc)
- rc = libxl__set_vcpuonline_xenstore(gc, domid, cpumap, &info);
-
-out:
- libxl_dominfo_dispose(&info);
- GC_FREE;
- return rc;
-}
-
-static int libxl__domain_s3_resume(libxl__gc *gc, int domid)
-{
- int rc = 0;
-
- switch (libxl__domain_type(gc, domid)) {
- case LIBXL_DOMAIN_TYPE_HVM:
- switch (libxl__device_model_version_running(gc, domid)) {
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
- rc = xc_hvm_param_set(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, 0);
- break;
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
- rc = libxl__qmp_system_wakeup(gc, domid);
- break;
- default:
- rc = ERROR_INVAL;
- break;
- }
- break;
- default:
- rc = ERROR_INVAL;
- break;
- }
-
- return rc;
-}
-
-int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid,
- libxl_trigger trigger, uint32_t vcpuid)
-{
- int rc;
- GC_INIT(ctx);
-
- switch (trigger) {
- case LIBXL_TRIGGER_POWER:
- rc = xc_domain_send_trigger(ctx->xch, domid,
- XEN_DOMCTL_SENDTRIGGER_POWER, vcpuid);
- break;
- case LIBXL_TRIGGER_SLEEP:
- rc = xc_domain_send_trigger(ctx->xch, domid,
- XEN_DOMCTL_SENDTRIGGER_SLEEP, vcpuid);
- break;
- case LIBXL_TRIGGER_NMI:
- rc = xc_domain_send_trigger(ctx->xch, domid,
- XEN_DOMCTL_SENDTRIGGER_NMI, vcpuid);
- break;
- case LIBXL_TRIGGER_INIT:
- rc = xc_domain_send_trigger(ctx->xch, domid,
- XEN_DOMCTL_SENDTRIGGER_INIT, vcpuid);
- break;
- case LIBXL_TRIGGER_RESET:
- rc = xc_domain_send_trigger(ctx->xch, domid,
- XEN_DOMCTL_SENDTRIGGER_RESET, vcpuid);
- break;
- case LIBXL_TRIGGER_S3RESUME:
- rc = libxl__domain_s3_resume(gc, domid);
- break;
- default:
- rc = -1;
- errno = EINVAL;
- break;
- }
-
- if (rc != 0) {
- LOGED(ERROR, domid, "Send trigger '%s' failed",
- libxl_trigger_to_string(trigger));
- rc = ERROR_FAIL;
- }
-
- GC_FREE;
- return rc;
-}
-
int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq)
{
GC_INIT(ctx);
@@ -2084,27 +652,6 @@ int libxl_send_debug_keys(libxl_ctx *ctx, char *keys)
return 0;
}
-uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid)
-{
- GC_INIT(ctx);
- char *dompath = libxl__xs_get_dompath(gc, domid);
- char *vm_path, *start_time;
- uint32_t ret;
-
- vm_path = libxl__xs_read(
- gc, XBT_NULL, GCSPRINTF("%s/vm", dompath));
- start_time = libxl__xs_read(
- gc, XBT_NULL, GCSPRINTF("%s/start_time", vm_path));
- if (start_time == NULL) {
- LOGEVD(ERROR, -1, domid, "Can't get start time of domain");
- ret = -1;
- }else{
- ret = strtoul(start_time, NULL, 10);
- }
- GC_FREE;
- return ret;
-}
-
static int fd_set_flags(libxl_ctx *ctx, int fd,
int fcntlgetop, int fcntlsetop, const char *fl,
int flagmask, int set_p)
@@ -2212,275 +759,6 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src)
(*dst)[i] = (*src)[i];
}
-/* For QEMU upstream we always need to provide the number of cpus present to
- * QEMU whether they are online or not; otherwise QEMU won't accept the saved
- * state. See implementation of libxl__qmp_query_cpus.
- */
-static int libxl__update_avail_vcpus_qmp(libxl__gc *gc, uint32_t domid,
- unsigned int max_vcpus,
- libxl_bitmap *map)
-{
- int rc;
-
- rc = libxl__qmp_query_cpus(gc, domid, map);
- if (rc) {
- LOGD(ERROR, domid, "Fail to get number of cpus");
- goto out;
- }
-
- rc = 0;
-out:
- return rc;
-}
-
-static int libxl__update_avail_vcpus_xenstore(libxl__gc *gc, uint32_t domid,
- unsigned int max_vcpus,
- libxl_bitmap *map)
-{
- int rc;
- unsigned int i;
- const char *dompath;
-
- dompath = libxl__xs_get_dompath(gc, domid);
- if (!dompath) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- for (i = 0; i < max_vcpus; i++) {
- const char *path = GCSPRINTF("%s/cpu/%u/availability", dompath, i);
- const char *content;
- rc = libxl__xs_read_checked(gc, XBT_NULL, path, &content);
- if (rc) goto out;
- if (content && !strcmp(content, "online"))
- libxl_bitmap_set(map, i);
- }
-
- rc = 0;
-out:
- return rc;
-}
-
-int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
- libxl_domain_config *d_config)
-{
- GC_INIT(ctx);
- int rc;
- libxl__domain_userdata_lock *lock = NULL;
-
- CTX_LOCK;
-
- lock = libxl__lock_domain_userdata(gc, domid);
- if (!lock) {
- rc = ERROR_LOCK_FAIL;
- goto out;
- }
-
- rc = libxl__get_domain_configuration(gc, domid, d_config);
- if (rc) {
- LOGD(ERROR, domid, "Fail to get domain configuration");
- rc = ERROR_FAIL;
- goto out;
- }
-
- /* Domain name */
- {
- char *domname;
- domname = libxl_domid_to_name(ctx, domid);
- if (!domname) {
- LOGD(ERROR, domid, "Fail to get domain name");
- goto out;
- }
- free(d_config->c_info.name);
- d_config->c_info.name = domname; /* steals allocation */
- }
-
- /* Domain UUID */
- {
- libxl_dominfo info;
- libxl_dominfo_init(&info);
- rc = libxl_domain_info(ctx, &info, domid);
- if (rc) {
- LOGD(ERROR, domid, "Fail to get domain info");
- libxl_dominfo_dispose(&info);
- goto out;
- }
- libxl_uuid_copy(ctx, &d_config->c_info.uuid, &info.uuid);
- libxl_dominfo_dispose(&info);
- }
-
- /* VCPUs */
- {
- libxl_bitmap *map = &d_config->b_info.avail_vcpus;
- unsigned int max_vcpus = d_config->b_info.max_vcpus;
- libxl_device_model_version version;
-
- libxl_bitmap_dispose(map);
- libxl_bitmap_init(map);
- libxl_bitmap_alloc(CTX, map, max_vcpus);
- libxl_bitmap_set_none(map);
-
- switch (d_config->b_info.type) {
- case LIBXL_DOMAIN_TYPE_HVM:
- version = libxl__device_model_version_running(gc, domid);
- assert(version != LIBXL_DEVICE_MODEL_VERSION_UNKNOWN);
- switch (version) {
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
- rc = libxl__update_avail_vcpus_qmp(gc, domid,
- max_vcpus, map);
- break;
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
- case LIBXL_DEVICE_MODEL_VERSION_NONE:
- rc = libxl__update_avail_vcpus_xenstore(gc, domid,
- max_vcpus, map);
- break;
- default:
- abort();
- }
- break;
- case LIBXL_DOMAIN_TYPE_PV:
- rc = libxl__update_avail_vcpus_xenstore(gc, domid,
- max_vcpus, map);
- break;
- default:
- abort();
- }
-
- if (rc) {
- LOGD(ERROR, domid, "Fail to update available cpu map");
- goto out;
- }
- }
-
- /* Memory limits:
- *
- * Currently there are three memory limits:
- * 1. "target" in xenstore (originally memory= in config file)
- * 2. "static-max" in xenstore (originally maxmem= in config file)
- * 3. "max_memkb" in hypervisor
- *
- * The third one is not visible and currently managed by
- * toolstack. In order to rebuild a domain we only need to have
- * "target" and "static-max".
- */
- {
- uint64_t target_memkb = 0, max_memkb = 0;
-
- /* "target" */
- rc = libxl__get_memory_target(gc, domid, &target_memkb, &max_memkb);
- if (rc) {
- LOGD(ERROR, domid, "Fail to get memory target");
- goto out;
- }
-
- /* libxl__get_targetmem_fudge() calculates the difference from
- * what is in xenstore to what we have in the domain build info.
- */
- d_config->b_info.target_memkb = target_memkb +
- libxl__get_targetmem_fudge(gc, &d_config->b_info);
-
- d_config->b_info.max_memkb = max_memkb;
- }
-
- /* Scheduler params */
- {
- libxl_domain_sched_params_dispose(&d_config->b_info.sched_params);
- rc = libxl_domain_sched_params_get(ctx, domid,
- &d_config->b_info.sched_params);
- if (rc) {
- LOGD(ERROR, domid, "Fail to get scheduler parameters");
- goto out;
- }
- }
-
- /* Devices: disk, nic, vtpm, pcidev etc. */
-
- /* The MERGE macro implements following logic:
- * 0. retrieve JSON (done by now)
- * 1. retrieve list of device from xenstore
- * 2. use xenstore entries as primary reference and compare JSON
- * entries with them.
- * a. if a device is present in xenstore and in JSON, merge the
- * two views.
- * b. if a device is not present in xenstore but in JSON, delete
- * it from the result.
- * c. it's impossible to have an entry present in xenstore but
- * not in JSON, because we maintain an invariant that every
- * entry in xenstore must have a corresponding entry in JSON.
- * 3. "merge" operates on "src" and "dst". "src" points to the
- * entry retrieved from xenstore while "dst" points to the entry
- * retrieve from JSON.
- */
- {
- const struct libxl_device_type *dt;
- int idx;
-
- for (idx = 0;; idx++) {
- void *p = NULL;
- void **devs;
- int i, j, num;
- int *num_dev;
-
- dt = device_type_tbl[idx];
- if (!dt)
- break;
-
- if (!dt->list || !dt->compare)
- continue;
-
- num_dev = libxl__device_type_get_num(dt, d_config);
- p = dt->list(CTX, domid, &num);
- if (p == NULL) {
- LOGD(DEBUG, domid, "No %s from xenstore",
- dt->type);
- }
- devs = libxl__device_type_get_ptr(dt, d_config);
-
- for (i = 0; i < *num_dev; i++) {
- void *q;
-
- q = libxl__device_type_get_elem(dt, d_config, i);
- for (j = 0; j < num; j++) {
- if (dt->compare(p + dt->dev_elem_size * j, q))
- break;
- }
-
- if (j < num) { /* found in xenstore */
- if (dt->merge)
- dt->merge(ctx, p + dt->dev_elem_size * j, q);
- } else { /* not found in xenstore */
- LOGD(WARN, domid,
- "Device present in JSON but not in xenstore, ignored");
-
- dt->dispose(q);
-
- for (j = i; j < *num_dev - 1; j++)
- memcpy(libxl__device_type_get_elem(dt, d_config, j),
- libxl__device_type_get_elem(dt, d_config, j+1),
- dt->dev_elem_size);
-
- /* rewind counters */
- (*num_dev)--;
- i--;
-
- *devs = libxl__realloc(NOGC, *devs,
- dt->dev_elem_size * *num_dev);
- }
- }
-
- for (i = 0; i < num; i++)
- dt->dispose(p + dt->dev_elem_size * i);
- free(p);
- }
- }
-
-out:
- if (lock) libxl__unlock_domain_userdata(lock);
- CTX_UNLOCK;
- GC_FREE;
- return rc;
-}
-
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl_domain.c b/tools/libxl/libxl_domain.c
new file mode 100644
index 0000000..9102f40
--- /dev/null
+++ b/tools/libxl/libxl_domain.c
@@ -0,0 +1,1744 @@
+/*
+ * 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"
+
+#define PAGE_TO_MEMKB(pages) ((pages) * 4)
+
+int libxl__domain_rename(libxl__gc *gc, uint32_t domid,
+ const char *old_name, const char *new_name,
+ xs_transaction_t trans)
+{
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ char *dom_path = 0;
+ const char *name_path;
+ char *got_old_name;
+ unsigned int got_old_len;
+ xs_transaction_t our_trans = 0;
+ uint32_t stub_dm_domid;
+ const char *stub_dm_old_name = NULL, *stub_dm_new_name = NULL;
+ int rc;
+ libxl_dominfo info;
+ char *uuid;
+ const char *vm_name_path;
+
+ libxl_dominfo_init(&info);
+
+ dom_path = libxl__xs_get_dompath(gc, domid);
+ if (!dom_path) goto x_nomem;
+
+ name_path= GCSPRINTF("%s/name", dom_path);
+ if (!name_path) goto x_nomem;
+
+ stub_dm_domid = libxl_get_stubdom_id(CTX, domid);
+ if (stub_dm_domid) {
+ stub_dm_old_name = libxl__stub_dm_name(gc, old_name);
+ stub_dm_new_name = libxl__stub_dm_name(gc, new_name);
+ }
+
+ retry_transaction:
+ if (!trans) {
+ trans = our_trans = xs_transaction_start(ctx->xsh);
+ if (!our_trans) {
+ LOGEVD(ERROR, errno, domid, "Create xs transaction for domain (re)name");
+ goto x_fail;
+ }
+ }
+
+ if (!new_name) {
+ LOGD(ERROR, domid, "New domain name not specified");
+ rc = ERROR_INVAL;
+ goto x_rc;
+ }
+
+ if (new_name[0]) {
+ /* nonempty names must be unique */
+ uint32_t domid_e;
+ rc = libxl_name_to_domid(ctx, new_name, &domid_e);
+ if (rc == ERROR_INVAL) {
+ /* no such domain, good */
+ } else if (rc != 0) {
+ LOGD(ERROR, domid, "Unexpected error checking for existing domain");
+ goto x_rc;
+ } else if (domid_e == domid) {
+ /* domain already has this name, ok (but we do still
+ * need the rest of the code as we may need to check
+ * old_name, for example). */
+ } else {
+ LOGD(ERROR, domid, "Domain with name \"%s\" already exists.", new_name);
+ rc = ERROR_INVAL;
+ goto x_rc;
+ }
+ }
+
+ if (old_name) {
+ got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
+ if (!got_old_name) {
+ LOGEVD(ERROR, errno, domid,
+ "Check old name for domain allegedly named `%s'",
+ old_name);
+ goto x_fail;
+ }
+ if (strcmp(old_name, got_old_name)) {
+ LOGD(ERROR, domid,
+ "Allegedly named `%s' is actually named `%s' - racing ?",
+ old_name,
+ got_old_name);
+ free(got_old_name);
+ goto x_fail;
+ }
+ free(got_old_name);
+ }
+ if (!xs_write(ctx->xsh, trans, name_path,
+ new_name, strlen(new_name))) {
+ LOGD(ERROR, domid,
+ "Failed to write new name `%s'"
+ " for domain previously named `%s'",
+ new_name,
+ old_name);
+ goto x_fail;
+ }
+
+ /* update /vm/<uuid>/name */
+ rc = libxl_domain_info(ctx, &info, domid);
+ if (rc)
+ goto x_rc;
+
+ uuid = GCSPRINTF(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info.uuid));
+ vm_name_path = GCSPRINTF("/vm/%s/name", uuid);
+ if (libxl__xs_write_checked(gc, trans, vm_name_path, new_name))
+ goto x_fail;
+
+ if (stub_dm_domid) {
+ rc = libxl__domain_rename(gc, stub_dm_domid,
+ stub_dm_old_name,
+ stub_dm_new_name,
+ trans);
+ if (rc) {
+ LOGED(ERROR, domid, "Unable to rename stub-domain");
+ goto x_rc;
+ }
+ }
+
+ if (our_trans) {
+ if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
+ trans = our_trans = 0;
+ if (errno != EAGAIN) {
+ LOGD(ERROR, domid,
+ "Failed to commit new name `%s'"
+ " for domain previously named `%s'",
+ new_name,
+ old_name);
+ goto x_fail;
+ }
+ LOGD(DEBUG, domid,
+ "Need to retry rename transaction"
+ " for domain (name_path=\"%s\", new_name=\"%s\")",
+ name_path,
+ new_name);
+ goto retry_transaction;
+ }
+ our_trans = 0;
+ }
+
+ rc = 0;
+ x_rc:
+ if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
+ libxl_dominfo_dispose(&info);
+ return rc;
+
+ x_fail: rc = ERROR_FAIL; goto x_rc;
+ x_nomem: rc = ERROR_NOMEM; goto x_rc;
+}
+
+int libxl_domain_rename(libxl_ctx *ctx, uint32_t domid,
+ const char *old_name, const char *new_name)
+{
+ GC_INIT(ctx);
+ int rc;
+ rc = libxl__domain_rename(gc, domid, old_name, new_name, XBT_NULL);
+ GC_FREE;
+ return rc;
+}
+
+int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid, int suspend_cancel,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ int rc = libxl__domain_resume(gc, domid, suspend_cancel);
+ libxl__ao_complete(egc, ao, rc);
+ return AO_INPROGRESS;
+}
+
+/*
+ * Preserves a domain but rewrites xenstore etc to make it unique so
+ * that the domain can be restarted.
+ *
+ * Does not modify info so that it may be reused.
+ */
+int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid,
+ libxl_domain_create_info *info, const char *name_suffix, libxl_uuid new_uuid)
+{
+ GC_INIT(ctx);
+ struct xs_permissions roperm[2];
+ xs_transaction_t t;
+ char *preserved_name;
+ char *uuid_string;
+ char *vm_path;
+ char *dom_path;
+
+ int rc;
+
+ preserved_name = GCSPRINTF("%s%s", info->name, name_suffix);
+ if (!preserved_name) {
+ GC_FREE;
+ return ERROR_NOMEM;
+ }
+
+ uuid_string = libxl__uuid2string(gc, new_uuid);
+ if (!uuid_string) {
+ GC_FREE;
+ return ERROR_NOMEM;
+ }
+
+ dom_path = libxl__xs_get_dompath(gc, domid);
+ if (!dom_path) {
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+
+ vm_path = GCSPRINTF("/vm/%s", uuid_string);
+ if (!vm_path) {
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+
+ roperm[0].id = 0;
+ roperm[0].perms = XS_PERM_NONE;
+ roperm[1].id = domid;
+ roperm[1].perms = XS_PERM_READ;
+
+ retry_transaction:
+ t = xs_transaction_start(ctx->xsh);
+
+ xs_rm(ctx->xsh, t, vm_path);
+ xs_mkdir(ctx->xsh, t, vm_path);
+ xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
+
+ xs_write(ctx->xsh, t, GCSPRINTF("%s/vm", dom_path), vm_path, strlen(vm_path));
+ rc = libxl__domain_rename(gc, domid, info->name, preserved_name, t);
+ if (rc) {
+ GC_FREE;
+ return rc;
+ }
+
+ xs_write(ctx->xsh, t, GCSPRINTF("%s/uuid", vm_path), uuid_string, strlen(uuid_string));
+
+ if (!xs_transaction_end(ctx->xsh, t, 0))
+ if (errno == EAGAIN)
+ goto retry_transaction;
+
+ GC_FREE;
+ return 0;
+}
+
+void xcinfo2xlinfo(libxl_ctx *ctx,
+ const xc_domaininfo_t *xcinfo,
+ libxl_dominfo *xlinfo)
+{
+ size_t size;
+
+ memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t));
+ xlinfo->domid = xcinfo->domain;
+ xlinfo->ssidref = xcinfo->ssidref;
+ if (libxl_flask_sid_to_context(ctx, xlinfo->ssidref,
+ &xlinfo->ssid_label, &size) < 0)
+ xlinfo->ssid_label = NULL;
+
+ xlinfo->dying = !!(xcinfo->flags&XEN_DOMINF_dying);
+ xlinfo->shutdown = !!(xcinfo->flags&XEN_DOMINF_shutdown);
+ xlinfo->paused = !!(xcinfo->flags&XEN_DOMINF_paused);
+ xlinfo->blocked = !!(xcinfo->flags&XEN_DOMINF_blocked);
+ xlinfo->running = !!(xcinfo->flags&XEN_DOMINF_running);
+ xlinfo->never_stop = !!(xcinfo->flags&XEN_DOMINF_xs_domain);
+
+ if (xlinfo->shutdown)
+ xlinfo->shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask;
+ else
+ xlinfo->shutdown_reason = LIBXL_SHUTDOWN_REASON_UNKNOWN;
+
+ xlinfo->outstanding_memkb = PAGE_TO_MEMKB(xcinfo->outstanding_pages);
+ xlinfo->current_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages);
+ xlinfo->shared_memkb = PAGE_TO_MEMKB(xcinfo->shr_pages);
+ xlinfo->paged_memkb = PAGE_TO_MEMKB(xcinfo->paged_pages);
+ xlinfo->max_memkb = PAGE_TO_MEMKB(xcinfo->max_pages);
+ xlinfo->cpu_time = xcinfo->cpu_time;
+ xlinfo->vcpu_max_id = xcinfo->max_vcpu_id;
+ xlinfo->vcpu_online = xcinfo->nr_online_vcpus;
+ xlinfo->cpupool = xcinfo->cpupool;
+ xlinfo->domain_type = (xcinfo->flags & XEN_DOMINF_hvm_guest) ?
+ LIBXL_DOMAIN_TYPE_HVM : LIBXL_DOMAIN_TYPE_PV;
+}
+
+libxl_dominfo * libxl_list_domain(libxl_ctx *ctx, int *nb_domain_out)
+{
+ libxl_dominfo *ptr = NULL;
+ int i, ret;
+ xc_domaininfo_t info[1024];
+ int size = 0;
+ uint32_t domid = 0;
+ GC_INIT(ctx);
+
+ while ((ret = xc_domain_getinfolist(ctx->xch, domid, 1024, info)) > 0) {
+ ptr = libxl__realloc(NOGC, ptr, (size + ret) * sizeof(libxl_dominfo));
+ for (i = 0; i < ret; i++) {
+ xcinfo2xlinfo(ctx, &info[i], &ptr[size + i]);
+ }
+ domid = info[ret - 1].domain + 1;
+ size += ret;
+ }
+
+ if (ret < 0) {
+ LOGE(ERROR, "getting domain info list");
+ free(ptr);
+ GC_FREE;
+ return NULL;
+ }
+
+ *nb_domain_out = size;
+ GC_FREE;
+ return ptr;
+}
+
+int libxl_domain_info(libxl_ctx *ctx, libxl_dominfo *info_r,
+ uint32_t domid) {
+ xc_domaininfo_t xcinfo;
+ int ret;
+ GC_INIT(ctx);
+
+ ret = xc_domain_getinfolist(ctx->xch, domid, 1, &xcinfo);
+ if (ret<0) {
+ LOGED(ERROR, domid, "Getting domain info list");
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+ if (ret==0 || xcinfo.domain != domid) {
+ GC_FREE;
+ return ERROR_DOMAIN_NOTFOUND;
+ }
+
+ if (info_r)
+ xcinfo2xlinfo(ctx, &xcinfo, info_r);
+ GC_FREE;
+ return 0;
+}
+
+/* this API call only list VM running on this host. A VM can
+ * be an aggregate of multiple domains. */
+libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm_out)
+{
+ GC_INIT(ctx);
+ libxl_dominfo *info;
+ libxl_vminfo *ptr = NULL;
+ int idx, i, n_doms;
+
+ info = libxl_list_domain(ctx, &n_doms);
+ if (!info)
+ goto out;
+
+ /*
+ * Always make sure to allocate at least one element; if we don't and we
+ * request zero, libxl__calloc (might) think its internal call to calloc
+ * has failed (if it returns null), if so it would kill our process.
+ */
+ ptr = libxl__calloc(NOGC, n_doms ? n_doms : 1, sizeof(libxl_vminfo));
+
+ for (idx = i = 0; i < n_doms; i++) {
+ if (libxl_is_stubdom(ctx, info[i].domid, NULL))
+ continue;
+ ptr[idx].uuid = info[i].uuid;
+ ptr[idx].domid = info[i].domid;
+
+ idx++;
+ }
+ *nb_vm_out = idx;
+ libxl_dominfo_list_free(info, n_doms);
+
+out:
+ GC_FREE;
+ return ptr;
+}
+
+static void remus_failover_cb(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc);
+
+int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
+ uint32_t domid, int send_fd, int recv_fd,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ libxl__domain_save_state *dss;
+ int rc;
+
+ libxl_domain_type type = libxl__domain_type(gc, domid);
+ if (type == LIBXL_DOMAIN_TYPE_INVALID) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /* The caller must set this defbool */
+ if (libxl_defbool_is_default(info->colo)) {
+ LOGD(ERROR, domid, "Colo mode must be enabled/disabled");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ libxl_defbool_setdefault(&info->allow_unsafe, false);
+ libxl_defbool_setdefault(&info->blackhole, false);
+ libxl_defbool_setdefault(&info->compression,
+ !libxl_defbool_val(info->colo));
+ libxl_defbool_setdefault(&info->netbuf, true);
+ libxl_defbool_setdefault(&info->diskbuf, true);
+
+ if (libxl_defbool_val(info->colo) &&
+ libxl_defbool_val(info->compression)) {
+ LOGD(ERROR, domid, "Cannot use memory checkpoint "
+ "compression in COLO mode");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (!libxl_defbool_val(info->allow_unsafe) &&
+ (libxl_defbool_val(info->blackhole) ||
+ !libxl_defbool_val(info->netbuf) ||
+ !libxl_defbool_val(info->diskbuf))) {
+ LOGD(ERROR, domid, "Unsafe mode must be enabled to replicate to /dev/null,"
+ "disable network buffering and disk replication");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+
+ GCNEW(dss);
+ dss->ao = ao;
+ dss->callback = remus_failover_cb;
+ dss->domid = domid;
+ dss->fd = send_fd;
+ dss->recv_fd = recv_fd;
+ dss->type = type;
+ dss->live = 1;
+ dss->debug = 0;
+ dss->remus = info;
+ if (libxl_defbool_val(info->colo))
+ dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_COLO;
+ else
+ dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_REMUS;
+
+ assert(info);
+
+ /* Point of no return */
+ if (libxl_defbool_val(info->colo))
+ libxl__colo_save_setup(egc, &dss->css);
+ else
+ libxl__remus_setup(egc, &dss->rs);
+ return AO_INPROGRESS;
+
+ out:
+ return AO_CREATE_FAIL(rc);
+}
+
+static void remus_failover_cb(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc)
+{
+ STATE_AO_GC(dss->ao);
+ /*
+ * With Remus, if we reach this point, it means either
+ * backup died or some network error occurred preventing us
+ * from sending checkpoints.
+ */
+ libxl__ao_complete(egc, ao, rc);
+}
+
+static void domain_suspend_cb(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc)
+{
+ STATE_AO_GC(dss->ao);
+ int flrc;
+
+ flrc = libxl__fd_flags_restore(gc, dss->fd, dss->fdfl);
+ /* If suspend has failed already then report that error not this one. */
+ if (flrc && !rc) rc = flrc;
+
+ libxl__ao_complete(egc,ao,rc);
+
+}
+
+int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ int rc;
+
+ libxl_domain_type type = libxl__domain_type(gc, domid);
+ if (type == LIBXL_DOMAIN_TYPE_INVALID) {
+ rc = ERROR_FAIL;
+ goto out_err;
+ }
+
+ libxl__domain_save_state *dss;
+ GCNEW(dss);
+
+ dss->ao = ao;
+ dss->callback = domain_suspend_cb;
+
+ dss->domid = domid;
+ dss->fd = fd;
+ dss->type = type;
+ dss->live = flags & LIBXL_SUSPEND_LIVE;
+ dss->debug = flags & LIBXL_SUSPEND_DEBUG;
+ dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_NONE;
+
+ rc = libxl__fd_flags_modify_save(gc, dss->fd,
+ ~(O_NONBLOCK|O_NDELAY), 0,
+ &dss->fdfl);
+ if (rc < 0) goto out_err;
+
+ libxl__domain_save(egc, dss);
+ return AO_INPROGRESS;
+
+ out_err:
+ return AO_CREATE_FAIL(rc);
+}
+
+int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid)
+{
+ int ret;
+ GC_INIT(ctx);
+ ret = xc_domain_pause(ctx->xch, domid);
+ if (ret<0) {
+ LOGED(ERROR, domid, "Pausing domain");
+ GC_FREE;
+ return ERROR_FAIL;
+ }
+ GC_FREE;
+ return 0;
+}
+
+int libxl_domain_core_dump(libxl_ctx *ctx, uint32_t domid,
+ const char *filename,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ int ret, rc;
+
+ ret = xc_domain_dumpcore(ctx->xch, domid, filename);
+ if (ret<0) {
+ LOGED(ERROR, domid, "Core dumping domain to %s", filename);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = 0;
+out:
+
+ libxl__ao_complete(egc, ao, rc);
+
+ return AO_INPROGRESS;
+}
+
+int libxl_domain_unpause(libxl_ctx *ctx, uint32_t domid)
+{
+ GC_INIT(ctx);
+ int ret, rc = 0;
+
+ libxl_domain_type type = libxl__domain_type(gc, domid);
+ if (type == LIBXL_DOMAIN_TYPE_INVALID) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (type == LIBXL_DOMAIN_TYPE_HVM) {
+ if (libxl__device_model_version_running(gc, domid) !=
+ LIBXL_DEVICE_MODEL_VERSION_NONE) {
+ rc = libxl__domain_resume_device_model(gc, domid);
+ if (rc < 0) {
+ LOGD(ERROR, domid, "Failed to unpause device model for domain:%d",
+ rc);
+ goto out;
+ }
+ }
+ }
+ ret = xc_domain_unpause(ctx->xch, domid);
+ if (ret<0) {
+ LOGED(ERROR, domid, "Unpausing domain");
+ rc = ERROR_FAIL;
+ }
+ out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid)
+{
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+
+ uint64_t pvdriver = 0;
+ int ret;
+
+ libxl_domain_type domtype = libxl__domain_type(gc, domid);
+ if (domtype == LIBXL_DOMAIN_TYPE_INVALID)
+ return ERROR_FAIL;
+
+ if (domtype == LIBXL_DOMAIN_TYPE_PV)
+ return 1;
+
+ ret = xc_hvm_param_get(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
+ if (ret<0) {
+ LOGED(ERROR, domid, "Getting HVM callback IRQ");
+ return ERROR_FAIL;
+ }
+ return !!pvdriver;
+}
+
+const char *libxl__domain_pvcontrol_xspath(libxl__gc *gc, uint32_t domid)
+{
+ const char *dom_path;
+
+ dom_path = libxl__xs_get_dompath(gc, domid);
+ if (!dom_path)
+ return NULL;
+
+ return GCSPRINTF("%s/control/shutdown", dom_path);
+}
+
+char * libxl__domain_pvcontrol_read(libxl__gc *gc, xs_transaction_t t,
+ uint32_t domid)
+{
+ const char *shutdown_path;
+
+ shutdown_path = libxl__domain_pvcontrol_xspath(gc, domid);
+ if (!shutdown_path)
+ return NULL;
+
+ return libxl__xs_read(gc, t, shutdown_path);
+}
+
+int libxl__domain_pvcontrol_write(libxl__gc *gc, xs_transaction_t t,
+ uint32_t domid, const char *cmd)
+{
+ const char *shutdown_path;
+
+ shutdown_path = libxl__domain_pvcontrol_xspath(gc, domid);
+ if (!shutdown_path)
+ return ERROR_FAIL;
+
+ return libxl__xs_printf(gc, t, shutdown_path, "%s", cmd);
+}
+
+static int libxl__domain_pvcontrol(libxl__gc *gc, uint32_t domid,
+ const char *cmd)
+{
+ int ret;
+
+ ret = libxl__domain_pvcontrol_available(gc, domid);
+ if (ret < 0)
+ return ret;
+
+ if (!ret)
+ return ERROR_NOPARAVIRT;
+
+ return libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, cmd);
+}
+
+int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid)
+{
+ GC_INIT(ctx);
+ int ret;
+ ret = libxl__domain_pvcontrol(gc, domid, "poweroff");
+ GC_FREE;
+ return ret;
+}
+
+int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid)
+{
+ GC_INIT(ctx);
+ int ret;
+ ret = libxl__domain_pvcontrol(gc, domid, "reboot");
+ GC_FREE;
+ return ret;
+}
+
+static void domain_death_occurred(libxl__egc *egc,
+ libxl_evgen_domain_death **evg_upd,
+ const char *why) {
+ /* Removes **evg_upd from death_list and puts it on death_reported
+ * and advances *evg_upd to the next entry.
+ * Call sites in domain_death_xswatch_callback must use "continue". */
+ EGC_GC;
+ libxl_evgen_domain_death *const evg = *evg_upd;
+
+ LOGD(DEBUG, evg->domid, "%s", why);
+
+ libxl_evgen_domain_death *evg_next = LIBXL_TAILQ_NEXT(evg, entry);
+ *evg_upd = evg_next;
+
+ libxl_event *ev = NEW_EVENT(egc, DOMAIN_DEATH, evg->domid, evg->user);
+
+ libxl__event_occurred(egc, ev);
+
+ evg->death_reported = 1;
+ LIBXL_TAILQ_REMOVE(&CTX->death_list, evg, entry);
+ LIBXL_TAILQ_INSERT_HEAD(&CTX->death_reported, evg, entry);
+}
+
+static void domain_death_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
+ const char *wpath, const char *epath) {
+ EGC_GC;
+ libxl_evgen_domain_death *evg;
+ int rc;
+
+ CTX_LOCK;
+
+ evg = LIBXL_TAILQ_FIRST(&CTX->death_list);
+
+ for (;;) {
+ if (!evg) goto out;
+
+ int nentries = LIBXL_TAILQ_NEXT(evg, entry) ? 200 : 1;
+ xc_domaininfo_t domaininfos[nentries];
+ const xc_domaininfo_t *got = domaininfos, *gotend;
+
+ rc = xc_domain_getinfolist(CTX->xch, evg->domid, nentries, domaininfos);
+ if (rc == -1) {
+ LIBXL__EVENT_DISASTER(egc, "xc_domain_getinfolist failed while"
+ " processing @releaseDomain watch event",
+ errno, 0);
+ goto out;
+ }
+ gotend = &domaininfos[rc];
+
+ LOGD(DEBUG, evg->domid, "[evg=%p] nentries=%d rc=%d %ld..%ld",
+ evg, nentries, rc,
+ rc>0 ? (long)domaininfos[0].domain : 0,
+ rc>0 ? (long)domaininfos[rc-1].domain : 0);
+
+ for (;;) {
+ if (!evg) {
+ LOG(DEBUG, "[evg=0] all reported");
+ goto all_reported;
+ }
+
+ LOGD(DEBUG, evg->domid, "[evg=%p]"
+ " got=domaininfos[%d] got->domain=%ld",
+ evg, (int)(got - domaininfos),
+ got < gotend ? (long)got->domain : -1L);
+
+ if (!rc) {
+ domain_death_occurred(egc, &evg, "empty list");
+ continue;
+ }
+
+ if (got == gotend) {
+ LOG(DEBUG, " got==gotend");
+ break;
+ }
+
+ if (got->domain > evg->domid) {
+ /* ie, the list doesn't contain evg->domid any more so
+ * the domain has been destroyed */
+ domain_death_occurred(egc, &evg, "missing from list");
+ continue;
+ }
+
+ if (got->domain < evg->domid) {
+ got++;
+ continue;
+ }
+
+ assert(evg->domid == got->domain);
+ LOGD(DEBUG, evg->domid, "Exists shutdown_reported=%d"" dominf.flags=%x",
+ evg->shutdown_reported, got->flags);
+
+ if (got->flags & XEN_DOMINF_dying) {
+ domain_death_occurred(egc, &evg, "dying");
+ continue;
+ }
+
+ if (!evg->shutdown_reported &&
+ (got->flags & XEN_DOMINF_shutdown)) {
+ libxl_event *ev = NEW_EVENT(egc, DOMAIN_SHUTDOWN,
+ got->domain, evg->user);
+
+ LOG(DEBUG, " shutdown reporting");
+
+ ev->u.domain_shutdown.shutdown_reason =
+ (got->flags >> XEN_DOMINF_shutdownshift) &
+ XEN_DOMINF_shutdownmask;
+ libxl__event_occurred(egc, ev);
+
+ evg->shutdown_reported = 1;
+ }
+ evg = LIBXL_TAILQ_NEXT(evg, entry);
+ }
+
+ assert(rc); /* rc==0 results in us eating all evgs and quitting */
+ }
+ all_reported:
+ out:
+
+ LOG(DEBUG, "domain death search done");
+
+ CTX_UNLOCK;
+}
+
+int libxl_evenable_domain_death(libxl_ctx *ctx, uint32_t domid,
+ libxl_ev_user user, libxl_evgen_domain_death **evgen_out) {
+ GC_INIT(ctx);
+ libxl_evgen_domain_death *evg, *evg_search;
+ int rc;
+
+ CTX_LOCK;
+
+ evg = malloc(sizeof(*evg)); if (!evg) { rc = ERROR_NOMEM; goto out; }
+ memset(evg, 0, sizeof(*evg));
+ evg->domid = domid;
+ evg->user = user;
+
+ LIBXL_TAILQ_INSERT_SORTED(&ctx->death_list, entry, evg, evg_search, ,
+ evg->domid > evg_search->domid);
+
+ if (!libxl__ev_xswatch_isregistered(&ctx->death_watch)) {
+ rc = libxl__ev_xswatch_register(gc, &ctx->death_watch,
+ domain_death_xswatch_callback, "@releaseDomain");
+ if (rc) { libxl__evdisable_domain_death(gc, evg); goto out; }
+ }
+
+ *evgen_out = evg;
+ rc = 0;
+
+ out:
+ CTX_UNLOCK;
+ GC_FREE;
+ return rc;
+};
+
+void libxl__evdisable_domain_death(libxl__gc *gc,
+ libxl_evgen_domain_death *evg) {
+ CTX_LOCK;
+
+ if (!evg->death_reported)
+ LIBXL_TAILQ_REMOVE(&CTX->death_list, evg, entry);
+ else
+ LIBXL_TAILQ_REMOVE(&CTX->death_reported, evg, entry);
+
+ free(evg);
+
+ if (!LIBXL_TAILQ_FIRST(&CTX->death_list) &&
+ libxl__ev_xswatch_isregistered(&CTX->death_watch))
+ libxl__ev_xswatch_deregister(gc, &CTX->death_watch);
+
+ CTX_UNLOCK;
+}
+
+void libxl_evdisable_domain_death(libxl_ctx *ctx,
+ libxl_evgen_domain_death *evg) {
+ GC_INIT(ctx);
+ libxl__evdisable_domain_death(gc, evg);
+ GC_FREE;
+}
+
+/* Callbacks for libxl_domain_destroy */
+
+static void domain_destroy_cb(libxl__egc *egc, libxl__domain_destroy_state *dds,
+ int rc);
+
+int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ libxl__domain_destroy_state *dds;
+
+ GCNEW(dds);
+ dds->ao = ao;
+ dds->domid = domid;
+ dds->callback = domain_destroy_cb;
+ libxl__domain_destroy(egc, dds);
+
+ return AO_INPROGRESS;
+}
+
+static void domain_destroy_cb(libxl__egc *egc, libxl__domain_destroy_state *dds,
+ int rc)
+{
+ STATE_AO_GC(dds->ao);
+
+ if (rc)
+ LOGD(ERROR, dds->domid, "Destruction of domain failed");
+
+ libxl__ao_complete(egc, ao, rc);
+}
+
+/* Callbacks for libxl__domain_destroy */
+
+static void stubdom_destroy_callback(libxl__egc *egc,
+ libxl__destroy_domid_state *dis,
+ int rc);
+
+static void domain_destroy_callback(libxl__egc *egc,
+ libxl__destroy_domid_state *dis,
+ int rc);
+
+static void destroy_finish_check(libxl__egc *egc,
+ libxl__domain_destroy_state *dds);
+
+void libxl__domain_destroy(libxl__egc *egc, libxl__domain_destroy_state *dds)
+{
+ STATE_AO_GC(dds->ao);
+ uint32_t stubdomid = libxl_get_stubdom_id(CTX, dds->domid);
+
+ if (stubdomid) {
+ dds->stubdom.ao = ao;
+ dds->stubdom.domid = stubdomid;
+ dds->stubdom.callback = stubdom_destroy_callback;
+ dds->stubdom.soft_reset = false;
+ libxl__destroy_domid(egc, &dds->stubdom);
+ } else {
+ dds->stubdom_finished = 1;
+ }
+
+ dds->domain.ao = ao;
+ dds->domain.domid = dds->domid;
+ dds->domain.callback = domain_destroy_callback;
+ dds->domain.soft_reset = dds->soft_reset;
+ libxl__destroy_domid(egc, &dds->domain);
+}
+
+static void stubdom_destroy_callback(libxl__egc *egc,
+ libxl__destroy_domid_state *dis,
+ int rc)
+{
+ STATE_AO_GC(dis->ao);
+ libxl__domain_destroy_state *dds = CONTAINER_OF(dis, *dds, stubdom);
+ const char *savefile;
+
+ if (rc) {
+ LOGD(ERROR, dds->domain.domid, "Unable to destroy stubdom with domid %u",
+ dis->domid);
+ dds->rc = rc;
+ }
+
+ dds->stubdom_finished = 1;
+ savefile = libxl__device_model_savefile(gc, dis->domid);
+ rc = libxl__remove_file(gc, savefile);
+ if (rc) {
+ LOGD(ERROR, dds->domain.domid, "Failed to remove device-model savefile %s",
+ savefile);
+ }
+
+ destroy_finish_check(egc, dds);
+}
+
+static void domain_destroy_callback(libxl__egc *egc,
+ libxl__destroy_domid_state *dis,
+ int rc)
+{
+ STATE_AO_GC(dis->ao);
+ libxl__domain_destroy_state *dds = CONTAINER_OF(dis, *dds, domain);
+
+ if (rc) {
+ LOGD(ERROR, dis->domid, "Unable to destroy guest");
+ dds->rc = rc;
+ }
+
+ dds->domain_finished = 1;
+ destroy_finish_check(egc, dds);
+}
+
+static void destroy_finish_check(libxl__egc *egc,
+ libxl__domain_destroy_state *dds)
+{
+ if (!(dds->domain_finished && dds->stubdom_finished))
+ return;
+
+ dds->callback(egc, dds, dds->rc);
+}
+
+/* Callbacks for libxl__destroy_domid */
+static void devices_destroy_cb(libxl__egc *egc,
+ libxl__devices_remove_state *drs,
+ int rc);
+
+static void domain_destroy_domid_cb(libxl__egc *egc,
+ libxl__ev_child *destroyer,
+ pid_t pid, int status);
+
+void libxl__destroy_domid(libxl__egc *egc, libxl__destroy_domid_state *dis)
+{
+ STATE_AO_GC(dis->ao);
+ libxl_ctx *ctx = CTX;
+ uint32_t domid = dis->domid;
+ char *dom_path;
+ int rc, dm_present;
+
+ libxl__ev_child_init(&dis->destroyer);
+
+ rc = libxl_domain_info(ctx, NULL, domid);
+ switch(rc) {
+ case 0:
+ break;
+ case ERROR_DOMAIN_NOTFOUND:
+ LOGD(ERROR, domid, "Non-existant domain");
+ default:
+ goto out;
+ }
+
+ switch (libxl__domain_type(gc, domid)) {
+ case LIBXL_DOMAIN_TYPE_HVM:
+ if (libxl_get_stubdom_id(CTX, domid)) {
+ dm_present = 0;
+ break;
+ }
+ /* fall through */
+ case LIBXL_DOMAIN_TYPE_PV:
+ dm_present = libxl__dm_active(gc, domid);
+ break;
+ case LIBXL_DOMAIN_TYPE_INVALID:
+ rc = ERROR_FAIL;
+ goto out;
+ default:
+ abort();
+ }
+
+ dom_path = libxl__xs_get_dompath(gc, domid);
+ if (!dom_path) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (libxl__device_pci_destroy_all(gc, domid) < 0)
+ LOGD(ERROR, domid, "Pci shutdown failed");
+ rc = xc_domain_pause(ctx->xch, domid);
+ if (rc < 0) {
+ LOGEVD(ERROR, rc, domid, "xc_domain_pause failed");
+ }
+ if (dm_present) {
+ if (libxl__destroy_device_model(gc, domid) < 0)
+ LOGD(ERROR, domid, "libxl__destroy_device_model failed");
+
+ libxl__qmp_cleanup(gc, domid);
+ }
+ dis->drs.ao = ao;
+ dis->drs.domid = domid;
+ dis->drs.callback = devices_destroy_cb;
+ dis->drs.force = 1;
+ libxl__devices_destroy(egc, &dis->drs);
+ return;
+
+out:
+ assert(rc);
+ dis->callback(egc, dis, rc);
+ return;
+}
+
+static void devices_destroy_cb(libxl__egc *egc,
+ libxl__devices_remove_state *drs,
+ int rc)
+{
+ STATE_AO_GC(drs->ao);
+ libxl__destroy_domid_state *dis = CONTAINER_OF(drs, *dis, drs);
+ libxl_ctx *ctx = CTX;
+ uint32_t domid = dis->domid;
+ char *dom_path;
+ char *vm_path;
+ libxl__domain_userdata_lock *lock;
+
+ dom_path = libxl__xs_get_dompath(gc, domid);
+ if (!dom_path) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (rc < 0)
+ LOGD(ERROR, domid, "libxl__devices_destroy failed");
+
+ vm_path = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/vm", dom_path));
+ if (vm_path)
+ if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
+ LOGED(ERROR, domid, "xs_rm failed for %s", vm_path);
+
+ if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
+ LOGED(ERROR, domid, "xs_rm failed for %s", dom_path);
+
+ xs_rm(ctx->xsh, XBT_NULL, libxl__xs_libxl_path(gc, domid));
+ xs_rm(ctx->xsh, XBT_NULL, GCSPRINTF( "/local/domain/%d/hvmloader", domid));
+
+ /* This is async operation, we already hold CTX lock */
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+ libxl__userdata_destroyall(gc, domid);
+
+ libxl__unlock_domain_userdata(lock);
+
+ /* Clean up qemu-save and qemu-resume files. They are
+ * intermediate files created by libxc. Unfortunately they
+ * don't fit in existing userdata scheme very well. In soft reset
+ * case we need to keep the file.
+ */
+ if (!dis->soft_reset) {
+ rc = libxl__remove_file(gc,
+ libxl__device_model_savefile(gc, domid));
+ if (rc < 0) goto out;
+ }
+ rc = libxl__remove_file(gc,
+ GCSPRINTF(LIBXL_DEVICE_MODEL_RESTORE_FILE".%u", domid));
+ if (rc < 0) goto out;
+
+ rc = libxl__ev_child_fork(gc, &dis->destroyer, domain_destroy_domid_cb);
+ if (rc < 0) goto out;
+ if (!rc) { /* child */
+ ctx->xch = xc_interface_open(ctx->lg,0,0);
+ if (!ctx->xch) goto badchild;
+
+ if (!dis->soft_reset) {
+ rc = xc_domain_destroy(ctx->xch, domid);
+ } else {
+ rc = xc_domain_pause(ctx->xch, domid);
+ if (rc < 0) goto badchild;
+ rc = xc_domain_soft_reset(ctx->xch, domid);
+ if (rc < 0) goto badchild;
+ rc = xc_domain_unpause(ctx->xch, domid);
+ }
+ if (rc < 0) goto badchild;
+ _exit(0);
+
+ badchild:
+ if (errno > 0 && errno < 126) {
+ _exit(errno);
+ } else {
+ LOGED(ERROR, domid,
+ "xc_domain_destroy failed (with difficult errno value %d)",
+ errno);
+ _exit(-1);
+ }
+ }
+ LOGD(DEBUG, domid, "Forked pid %ld for destroy of domain", (long)rc);
+
+ return;
+
+out:
+ dis->callback(egc, dis, rc);
+ return;
+}
+
+static void domain_destroy_domid_cb(libxl__egc *egc,
+ libxl__ev_child *destroyer,
+ pid_t pid, int status)
+{
+ libxl__destroy_domid_state *dis = CONTAINER_OF(destroyer, *dis, destroyer);
+ STATE_AO_GC(dis->ao);
+ int rc;
+
+ if (status) {
+ if (WIFEXITED(status) && WEXITSTATUS(status)<126) {
+ LOGEVD(ERROR, WEXITSTATUS(status), dis->domid,
+ "xc_domain_destroy failed");
+ } else {
+ libxl_report_child_exitstatus(CTX, XTL_ERROR,
+ "async domain destroy", pid, status);
+ }
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ rc = 0;
+
+ out:
+ dis->callback(egc, dis, rc);
+}
+
+int libxl__get_domid(libxl__gc *gc, uint32_t *domid)
+{
+ int rc;
+ const char *xs_domid;
+
+ rc = libxl__xs_read_checked(gc, XBT_NULL, DOMID_XS_PATH, &xs_domid);
+ if (rc) goto out;
+ if (!xs_domid) {
+ LOG(ERROR, "failed to get own domid (%s)", DOMID_XS_PATH);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ *domid = atoi(xs_domid);
+
+out:
+ return rc;
+}
+
+int libxl__resolve_domid(libxl__gc *gc, const char *name, uint32_t *domid)
+{
+ if (!name)
+ return 0;
+ return libxl_domain_qualifier_to_domid(CTX, name, domid);
+}
+
+libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
+ int *nr_vcpus_out, int *nr_cpus_out)
+{
+ GC_INIT(ctx);
+ libxl_vcpuinfo *ptr, *ret;
+ xc_domaininfo_t domaininfo;
+ xc_vcpuinfo_t vcpuinfo;
+
+ if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
+ LOGED(ERROR, domid, "Getting infolist");
+ GC_FREE;
+ return NULL;
+ }
+
+ if (domaininfo.max_vcpu_id == XEN_INVALID_MAX_VCPU_ID) {
+ GC_FREE;
+ return NULL;
+ }
+
+ *nr_cpus_out = libxl_get_max_cpus(ctx);
+ ret = ptr = libxl__calloc(NOGC, domaininfo.max_vcpu_id + 1,
+ sizeof(libxl_vcpuinfo));
+
+ for (*nr_vcpus_out = 0;
+ *nr_vcpus_out <= domaininfo.max_vcpu_id;
+ ++*nr_vcpus_out, ++ptr) {
+ libxl_bitmap_init(&ptr->cpumap);
+ if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap, 0))
+ goto err;
+ libxl_bitmap_init(&ptr->cpumap_soft);
+ if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap_soft, 0))
+ goto err;
+ if (xc_vcpu_getinfo(ctx->xch, domid, *nr_vcpus_out, &vcpuinfo) == -1) {
+ LOGED(ERROR, domid, "Getting vcpu info");
+ goto err;
+ }
+
+ if (xc_vcpu_getaffinity(ctx->xch, domid, *nr_vcpus_out,
+ ptr->cpumap.map, ptr->cpumap_soft.map,
+ XEN_VCPUAFFINITY_SOFT|XEN_VCPUAFFINITY_HARD) == -1) {
+ LOGED(ERROR, domid, "Getting vcpu affinity");
+ goto err;
+ }
+ ptr->vcpuid = *nr_vcpus_out;
+ ptr->cpu = vcpuinfo.cpu;
+ ptr->online = !!vcpuinfo.online;
+ ptr->blocked = !!vcpuinfo.blocked;
+ ptr->running = !!vcpuinfo.running;
+ ptr->vcpu_time = vcpuinfo.cpu_time;
+ }
+ GC_FREE;
+ return ret;
+
+err:
+ libxl_bitmap_dispose(&ptr->cpumap);
+ libxl_bitmap_dispose(&ptr->cpumap_soft);
+ free(ret);
+ GC_FREE;
+ return NULL;
+}
+
+static int libxl__set_vcpuonline_xenstore(libxl__gc *gc, uint32_t domid,
+ libxl_bitmap *cpumap,
+ const libxl_dominfo *info)
+{
+ char *dompath;
+ xs_transaction_t t;
+ int i, rc = ERROR_FAIL;
+
+ if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+ goto out;
+
+retry_transaction:
+ t = xs_transaction_start(CTX->xsh);
+ for (i = 0; i <= info->vcpu_max_id; i++)
+ libxl__xs_printf(gc, t,
+ GCSPRINTF("%s/cpu/%u/availability", dompath, i),
+ "%s", libxl_bitmap_test(cpumap, i) ? "online" : "offline");
+ if (!xs_transaction_end(CTX->xsh, t, 0)) {
+ if (errno == EAGAIN)
+ goto retry_transaction;
+ } else
+ rc = 0;
+out:
+ return rc;
+}
+
+static int libxl__set_vcpuonline_qmp(libxl__gc *gc, uint32_t domid,
+ libxl_bitmap *cpumap,
+ const libxl_dominfo *info)
+{
+ int i, rc;
+ libxl_bitmap current_map, final_map;
+
+ libxl_bitmap_init(¤t_map);
+ libxl_bitmap_init(&final_map);
+
+ libxl_bitmap_alloc(CTX, ¤t_map, info->vcpu_max_id + 1);
+ libxl_bitmap_set_none(¤t_map);
+ rc = libxl__qmp_query_cpus(gc, domid, ¤t_map);
+ if (rc) {
+ LOGD(ERROR, domid, "Failed to query cpus");
+ goto out;
+ }
+
+ libxl_bitmap_copy_alloc(CTX, &final_map, cpumap);
+
+ libxl_for_each_set_bit(i, current_map)
+ libxl_bitmap_reset(&final_map, i);
+
+ libxl_for_each_set_bit(i, final_map) {
+ rc = libxl__qmp_cpu_add(gc, domid, i);
+ if (rc) {
+ LOGD(ERROR, domid, "Failed to add cpu %d", i);
+ goto out;
+ }
+ }
+
+ rc = 0;
+out:
+ libxl_bitmap_dispose(¤t_map);
+ libxl_bitmap_dispose(&final_map);
+ return rc;
+}
+
+int libxl_set_vcpuonline(libxl_ctx *ctx, uint32_t domid, libxl_bitmap *cpumap)
+{
+ GC_INIT(ctx);
+ int rc, maxcpus;
+ libxl_dominfo info;
+
+ libxl_dominfo_init(&info);
+
+ rc = libxl_domain_info(CTX, &info, domid);
+ if (rc < 0) {
+ LOGED(ERROR, domid, "Getting domain info list");
+ goto out;
+ }
+
+ maxcpus = libxl_bitmap_count_set(cpumap);
+ if (maxcpus > info.vcpu_max_id + 1)
+ {
+ LOGED(ERROR, domid, "Requested %d VCPUs, however maxcpus is %d!",
+ maxcpus, info.vcpu_max_id + 1);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ switch (libxl__domain_type(gc, domid)) {
+ case LIBXL_DOMAIN_TYPE_HVM:
+ switch (libxl__device_model_version_running(gc, domid)) {
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
+ case LIBXL_DEVICE_MODEL_VERSION_NONE:
+ break;
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
+ rc = libxl__set_vcpuonline_qmp(gc, domid, cpumap, &info);
+ break;
+ default:
+ rc = ERROR_INVAL;
+ }
+ break;
+ case LIBXL_DOMAIN_TYPE_PV:
+ break;
+ default:
+ rc = ERROR_INVAL;
+ }
+
+ if (!rc)
+ rc = libxl__set_vcpuonline_xenstore(gc, domid, cpumap, &info);
+
+out:
+ libxl_dominfo_dispose(&info);
+ GC_FREE;
+ return rc;
+}
+
+static int libxl__domain_s3_resume(libxl__gc *gc, int domid)
+{
+ int rc = 0;
+
+ switch (libxl__domain_type(gc, domid)) {
+ case LIBXL_DOMAIN_TYPE_HVM:
+ switch (libxl__device_model_version_running(gc, domid)) {
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
+ rc = xc_hvm_param_set(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, 0);
+ break;
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
+ rc = libxl__qmp_system_wakeup(gc, domid);
+ break;
+ default:
+ rc = ERROR_INVAL;
+ break;
+ }
+ break;
+ default:
+ rc = ERROR_INVAL;
+ break;
+ }
+
+ return rc;
+}
+
+int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid,
+ libxl_trigger trigger, uint32_t vcpuid)
+{
+ int rc;
+ GC_INIT(ctx);
+
+ switch (trigger) {
+ case LIBXL_TRIGGER_POWER:
+ rc = xc_domain_send_trigger(ctx->xch, domid,
+ XEN_DOMCTL_SENDTRIGGER_POWER, vcpuid);
+ break;
+ case LIBXL_TRIGGER_SLEEP:
+ rc = xc_domain_send_trigger(ctx->xch, domid,
+ XEN_DOMCTL_SENDTRIGGER_SLEEP, vcpuid);
+ break;
+ case LIBXL_TRIGGER_NMI:
+ rc = xc_domain_send_trigger(ctx->xch, domid,
+ XEN_DOMCTL_SENDTRIGGER_NMI, vcpuid);
+ break;
+ case LIBXL_TRIGGER_INIT:
+ rc = xc_domain_send_trigger(ctx->xch, domid,
+ XEN_DOMCTL_SENDTRIGGER_INIT, vcpuid);
+ break;
+ case LIBXL_TRIGGER_RESET:
+ rc = xc_domain_send_trigger(ctx->xch, domid,
+ XEN_DOMCTL_SENDTRIGGER_RESET, vcpuid);
+ break;
+ case LIBXL_TRIGGER_S3RESUME:
+ rc = libxl__domain_s3_resume(gc, domid);
+ break;
+ default:
+ rc = -1;
+ errno = EINVAL;
+ break;
+ }
+
+ if (rc != 0) {
+ LOGED(ERROR, domid, "Send trigger '%s' failed",
+ libxl_trigger_to_string(trigger));
+ rc = ERROR_FAIL;
+ }
+
+ GC_FREE;
+ return rc;
+}
+
+uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid)
+{
+ GC_INIT(ctx);
+ char *dompath = libxl__xs_get_dompath(gc, domid);
+ char *vm_path, *start_time;
+ uint32_t ret;
+
+ vm_path = libxl__xs_read(
+ gc, XBT_NULL, GCSPRINTF("%s/vm", dompath));
+ start_time = libxl__xs_read(
+ gc, XBT_NULL, GCSPRINTF("%s/start_time", vm_path));
+ if (start_time == NULL) {
+ LOGEVD(ERROR, -1, domid, "Can't get start time of domain");
+ ret = -1;
+ }else{
+ ret = strtoul(start_time, NULL, 10);
+ }
+ GC_FREE;
+ return ret;
+}
+
+/* For QEMU upstream we always need to provide the number of cpus present to
+ * QEMU whether they are online or not; otherwise QEMU won't accept the saved
+ * state. See implementation of libxl__qmp_query_cpus.
+ */
+static int libxl__update_avail_vcpus_qmp(libxl__gc *gc, uint32_t domid,
+ unsigned int max_vcpus,
+ libxl_bitmap *map)
+{
+ int rc;
+
+ rc = libxl__qmp_query_cpus(gc, domid, map);
+ if (rc) {
+ LOGD(ERROR, domid, "Fail to get number of cpus");
+ goto out;
+ }
+
+ rc = 0;
+out:
+ return rc;
+}
+
+static int libxl__update_avail_vcpus_xenstore(libxl__gc *gc, uint32_t domid,
+ unsigned int max_vcpus,
+ libxl_bitmap *map)
+{
+ int rc;
+ unsigned int i;
+ const char *dompath;
+
+ dompath = libxl__xs_get_dompath(gc, domid);
+ if (!dompath) {
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ for (i = 0; i < max_vcpus; i++) {
+ const char *path = GCSPRINTF("%s/cpu/%u/availability", dompath, i);
+ const char *content;
+ rc = libxl__xs_read_checked(gc, XBT_NULL, path, &content);
+ if (rc) goto out;
+ if (content && !strcmp(content, "online"))
+ libxl_bitmap_set(map, i);
+ }
+
+ rc = 0;
+out:
+ return rc;
+}
+
+int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
+ libxl_domain_config *d_config)
+{
+ GC_INIT(ctx);
+ int rc;
+ libxl__domain_userdata_lock *lock = NULL;
+
+ CTX_LOCK;
+
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, d_config);
+ if (rc) {
+ LOGD(ERROR, domid, "Fail to get domain configuration");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /* Domain name */
+ {
+ char *domname;
+ domname = libxl_domid_to_name(ctx, domid);
+ if (!domname) {
+ LOGD(ERROR, domid, "Fail to get domain name");
+ goto out;
+ }
+ free(d_config->c_info.name);
+ d_config->c_info.name = domname; /* steals allocation */
+ }
+
+ /* Domain UUID */
+ {
+ libxl_dominfo info;
+ libxl_dominfo_init(&info);
+ rc = libxl_domain_info(ctx, &info, domid);
+ if (rc) {
+ LOGD(ERROR, domid, "Fail to get domain info");
+ libxl_dominfo_dispose(&info);
+ goto out;
+ }
+ libxl_uuid_copy(ctx, &d_config->c_info.uuid, &info.uuid);
+ libxl_dominfo_dispose(&info);
+ }
+
+ /* VCPUs */
+ {
+ libxl_bitmap *map = &d_config->b_info.avail_vcpus;
+ unsigned int max_vcpus = d_config->b_info.max_vcpus;
+ libxl_device_model_version version;
+
+ libxl_bitmap_dispose(map);
+ libxl_bitmap_init(map);
+ libxl_bitmap_alloc(CTX, map, max_vcpus);
+ libxl_bitmap_set_none(map);
+
+ switch (d_config->b_info.type) {
+ case LIBXL_DOMAIN_TYPE_HVM:
+ version = libxl__device_model_version_running(gc, domid);
+ assert(version != LIBXL_DEVICE_MODEL_VERSION_UNKNOWN);
+ switch (version) {
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
+ rc = libxl__update_avail_vcpus_qmp(gc, domid,
+ max_vcpus, map);
+ break;
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
+ case LIBXL_DEVICE_MODEL_VERSION_NONE:
+ rc = libxl__update_avail_vcpus_xenstore(gc, domid,
+ max_vcpus, map);
+ break;
+ default:
+ abort();
+ }
+ break;
+ case LIBXL_DOMAIN_TYPE_PV:
+ rc = libxl__update_avail_vcpus_xenstore(gc, domid,
+ max_vcpus, map);
+ break;
+ default:
+ abort();
+ }
+
+ if (rc) {
+ LOGD(ERROR, domid, "Fail to update available cpu map");
+ goto out;
+ }
+ }
+
+ /* Memory limits:
+ *
+ * Currently there are three memory limits:
+ * 1. "target" in xenstore (originally memory= in config file)
+ * 2. "static-max" in xenstore (originally maxmem= in config file)
+ * 3. "max_memkb" in hypervisor
+ *
+ * The third one is not visible and currently managed by
+ * toolstack. In order to rebuild a domain we only need to have
+ * "target" and "static-max".
+ */
+ {
+ uint64_t target_memkb = 0, max_memkb = 0;
+
+ /* "target" */
+ rc = libxl__get_memory_target(gc, domid, &target_memkb, &max_memkb);
+ if (rc) {
+ LOGD(ERROR, domid, "Fail to get memory target");
+ goto out;
+ }
+
+ /* libxl__get_targetmem_fudge() calculates the difference from
+ * what is in xenstore to what we have in the domain build info.
+ */
+ d_config->b_info.target_memkb = target_memkb +
+ libxl__get_targetmem_fudge(gc, &d_config->b_info);
+
+ d_config->b_info.max_memkb = max_memkb;
+ }
+
+ /* Scheduler params */
+ {
+ libxl_domain_sched_params_dispose(&d_config->b_info.sched_params);
+ rc = libxl_domain_sched_params_get(ctx, domid,
+ &d_config->b_info.sched_params);
+ if (rc) {
+ LOGD(ERROR, domid, "Fail to get scheduler parameters");
+ goto out;
+ }
+ }
+
+ /* Devices: disk, nic, vtpm, pcidev etc. */
+
+ /* The MERGE macro implements following logic:
+ * 0. retrieve JSON (done by now)
+ * 1. retrieve list of device from xenstore
+ * 2. use xenstore entries as primary reference and compare JSON
+ * entries with them.
+ * a. if a device is present in xenstore and in JSON, merge the
+ * two views.
+ * b. if a device is not present in xenstore but in JSON, delete
+ * it from the result.
+ * c. it's impossible to have an entry present in xenstore but
+ * not in JSON, because we maintain an invariant that every
+ * entry in xenstore must have a corresponding entry in JSON.
+ * 3. "merge" operates on "src" and "dst". "src" points to the
+ * entry retrieved from xenstore while "dst" points to the entry
+ * retrieve from JSON.
+ */
+ {
+ const struct libxl_device_type *dt;
+ int idx;
+
+ for (idx = 0;; idx++) {
+ void *p = NULL;
+ void **devs;
+ int i, j, num;
+ int *num_dev;
+
+ dt = device_type_tbl[idx];
+ if (!dt)
+ break;
+
+ if (!dt->list || !dt->compare)
+ continue;
+
+ num_dev = libxl__device_type_get_num(dt, d_config);
+ p = dt->list(CTX, domid, &num);
+ if (p == NULL) {
+ LOGD(DEBUG, domid, "No %s from xenstore",
+ dt->type);
+ }
+ devs = libxl__device_type_get_ptr(dt, d_config);
+
+ for (i = 0; i < *num_dev; i++) {
+ void *q;
+
+ q = libxl__device_type_get_elem(dt, d_config, i);
+ for (j = 0; j < num; j++) {
+ if (dt->compare(p + dt->dev_elem_size * j, q))
+ break;
+ }
+
+ if (j < num) { /* found in xenstore */
+ if (dt->merge)
+ dt->merge(ctx, p + dt->dev_elem_size * j, q);
+ } else { /* not found in xenstore */
+ LOGD(WARN, domid,
+ "Device present in JSON but not in xenstore, ignored");
+
+ dt->dispose(q);
+
+ for (j = i; j < *num_dev - 1; j++)
+ memcpy(libxl__device_type_get_elem(dt, d_config, j),
+ libxl__device_type_get_elem(dt, d_config, j+1),
+ dt->dev_elem_size);
+
+ /* rewind counters */
+ (*num_dev)--;
+ i--;
+
+ *devs = libxl__realloc(NOGC, *devs,
+ dt->dev_elem_size * *num_dev);
+ }
+ }
+
+ for (i = 0; i < num; i++)
+ dt->dispose(p + dt->dev_elem_size * i);
+ free(p);
+ }
+ }
+
+out:
+ if (lock) libxl__unlock_domain_userdata(lock);
+ CTX_UNLOCK;
+ GC_FREE;
+ return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 12/12] libxl: make one function static
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (10 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 11/12] libxl: carve out domain " Juergen Gross
@ 2017-02-09 9:30 ` Juergen Gross
2017-02-09 11:42 ` Ian Jackson
2017-02-09 10:22 ` [PATCH v2 00/12] libxl: split up libxl.c Wei Liu
2017-02-09 11:41 ` Ian Jackson
13 siblings, 1 reply; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 9:30 UTC (permalink / raw)
To: xen-devel
Cc: Juergen Gross, haozhong.zhang, wei.liu2, zhangchen.fnst,
ian.jackson, yi.y.sun
libxl__device_frontend_path() is used in libxl_device.c only. Make it
static.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libxl/libxl_device.c | 2 +-
tools/libxl/libxl_internal.h | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index c72a2b8..5e96676 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -18,7 +18,7 @@
#include "libxl_internal.h"
-char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device)
+static char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device)
{
char *dom_path = libxl__xs_get_dompath(gc, device->domid);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index b880801..29d6de5 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1206,7 +1206,6 @@ _hidden int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
_hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents);
_hidden char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device);
-_hidden char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device);
_hidden char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
--
2.10.2
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v2 01/12] libxl: adjust copyright comment of libxl.c
2017-02-09 9:30 ` [PATCH v2 01/12] libxl: adjust copyright comment of libxl.c Juergen Gross
@ 2017-02-09 10:18 ` Wei Liu
2017-02-09 11:37 ` Ian Jackson
1 sibling, 0 replies; 23+ messages in thread
From: Wei Liu @ 2017-02-09 10:18 UTC (permalink / raw)
To: Juergen Gross
Cc: haozhong.zhang, wei.liu2, zhangchen.fnst, ian.jackson, yi.y.sun,
xen-devel
On Thu, Feb 09, 2017 at 10:30:14AM +0100, Juergen Gross wrote:
> The copyright of libxl.c is a little bit outdated.
>
> Adjust it to reality.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 00/12] libxl: split up libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (11 preceding siblings ...)
2017-02-09 9:30 ` [PATCH v2 12/12] libxl: make one function static Juergen Gross
@ 2017-02-09 10:22 ` Wei Liu
2017-02-09 11:41 ` Ian Jackson
13 siblings, 0 replies; 23+ messages in thread
From: Wei Liu @ 2017-02-09 10:22 UTC (permalink / raw)
To: Juergen Gross
Cc: haozhong.zhang, wei.liu2, zhangchen.fnst, ian.jackson, yi.y.sun,
xen-devel
On Thu, Feb 09, 2017 at 10:30:13AM +0100, Juergen Gross wrote:
> libxl.c has become rather large. Split it up into multiple files.
>
> Changes are:
> - modification of Copyright comment (patch 1)
> - made two functions non-static: libxl__get_memory_target(),
> xcinfo2xlinfo() (patch 2)
> - white space cleanup of libxl.c (patch 3)
> - moving functions into new or existing sources (patches 4-11):
> just code movement, no functional changes besides needed Makefile
> adjustments for new sources
> - made one function static: libxl__device_frontend_path() (patch 12)
>
> Changes in V2:
> - address comments of Ian Jackson: add new patches 1-3, 12
>
> Juergen Gross (12):
> libxl: adjust copyright comment of libxl.c
> libxl: make some functions global to prepare splitting up libxl.c
> libxl: white space cleanup
> libxl: carve out cpupool specific functions from libxl.c
> libxl: carve out scheduler specific functions from libxl.c
> libxl: carve out disk specific functions from libxl.c
> libxl: carve out console specific functions from libxl.c
> libxl: carve out memory specific functions from libxl.c
> libxl: move device specific functions out of libxl.c
> libxl: carve out tmem specific functions from libxl.c
> libxl: carve out domain specific functions from libxl.c
> libxl: make one function static
>
Series:
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
I'm a bit two-minded about the last patch, though.
Wei.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c
2017-02-09 9:30 ` [PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c Juergen Gross
@ 2017-02-09 11:36 ` Ian Jackson
2017-02-09 11:42 ` Juergen Gross
0 siblings, 1 reply; 23+ messages in thread
From: Ian Jackson @ 2017-02-09 11:36 UTC (permalink / raw)
To: Juergen Gross
Cc: xen-devel, wei.liu2, zhangchen.fnst, yi.y.sun, haozhong.zhang
Juergen Gross writes ("[PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c"):
> Splitting up libxl.c will require two functions to be globally visible.
> Add their prototypes to libxl_internal.h.
Thanks. However,
> -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)
This function needs a libxl__ prefix adding to its name.
Ian.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 01/12] libxl: adjust copyright comment of libxl.c
2017-02-09 9:30 ` [PATCH v2 01/12] libxl: adjust copyright comment of libxl.c Juergen Gross
2017-02-09 10:18 ` Wei Liu
@ 2017-02-09 11:37 ` Ian Jackson
1 sibling, 0 replies; 23+ messages in thread
From: Ian Jackson @ 2017-02-09 11:37 UTC (permalink / raw)
To: Juergen Gross
Cc: xen-devel, wei.liu2, zhangchen.fnst, yi.y.sun, haozhong.zhang
Juergen Gross writes ("[PATCH v2 01/12] libxl: adjust copyright comment of libxl.c"):
> The copyright of libxl.c is a little bit outdated.
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
If you felt like doing a similar thing to the other files that would
be nice (but of course not required for this series).
Regards,
Ian.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 03/12] libxl: white space cleanup
2017-02-09 9:30 ` [PATCH v2 03/12] libxl: white space cleanup Juergen Gross
@ 2017-02-09 11:37 ` Ian Jackson
0 siblings, 0 replies; 23+ messages in thread
From: Ian Jackson @ 2017-02-09 11:37 UTC (permalink / raw)
To: Juergen Gross
Cc: xen-devel, wei.liu2, zhangchen.fnst, yi.y.sun, haozhong.zhang
Juergen Gross writes ("[PATCH v2 03/12] libxl: white space cleanup"):
> Before moving code to new sources clean up some white space issues in
> libxl.c.
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 00/12] libxl: split up libxl.c
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
` (12 preceding siblings ...)
2017-02-09 10:22 ` [PATCH v2 00/12] libxl: split up libxl.c Wei Liu
@ 2017-02-09 11:41 ` Ian Jackson
13 siblings, 0 replies; 23+ messages in thread
From: Ian Jackson @ 2017-02-09 11:41 UTC (permalink / raw)
To: Juergen Gross
Cc: xen-devel, wei.liu2, zhangchen.fnst, yi.y.sun, haozhong.zhang
Juergen Gross writes ("[PATCH v2 00/12] libxl: split up libxl.c"):
> libxl: carve out cpupool specific functions from libxl.c
> libxl: carve out scheduler specific functions from libxl.c
> libxl: carve out disk specific functions from libxl.c
> libxl: carve out console specific functions from libxl.c
> libxl: carve out memory specific functions from libxl.c
> libxl: move device specific functions out of libxl.c
> libxl: carve out tmem specific functions from libxl.c
> libxl: carve out domain specific functions from libxl.c
I have verified your assertion that these patches are just code
motion.
So for patches 4-11 inclusive:
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Ian.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 12/12] libxl: make one function static
2017-02-09 9:30 ` [PATCH v2 12/12] libxl: make one function static Juergen Gross
@ 2017-02-09 11:42 ` Ian Jackson
0 siblings, 0 replies; 23+ messages in thread
From: Ian Jackson @ 2017-02-09 11:42 UTC (permalink / raw)
To: Juergen Gross
Cc: xen-devel, wei.liu2, zhangchen.fnst, yi.y.sun, haozhong.zhang
Juergen Gross writes ("[PATCH v2 12/12] libxl: make one function static"):
> libxl__device_frontend_path() is used in libxl_device.c only. Make it
> static.
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c
2017-02-09 11:36 ` Ian Jackson
@ 2017-02-09 11:42 ` Juergen Gross
2017-02-09 15:44 ` Wei Liu
0 siblings, 1 reply; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 11:42 UTC (permalink / raw)
To: Ian Jackson; +Cc: xen-devel, wei.liu2, zhangchen.fnst, yi.y.sun, haozhong.zhang
On 09/02/17 12:36, Ian Jackson wrote:
> Juergen Gross writes ("[PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c"):
>> Splitting up libxl.c will require two functions to be globally visible.
>> Add their prototypes to libxl_internal.h.
>
> Thanks. However,
>
>> -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)
>
> This function needs a libxl__ prefix adding to its name.
Aah, of course!
Will send V3 after waiting for more comments for a while...
Juergen
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c
2017-02-09 11:42 ` Juergen Gross
@ 2017-02-09 15:44 ` Wei Liu
2017-02-09 16:06 ` Juergen Gross
0 siblings, 1 reply; 23+ messages in thread
From: Wei Liu @ 2017-02-09 15:44 UTC (permalink / raw)
To: Juergen Gross
Cc: haozhong.zhang, wei.liu2, zhangchen.fnst, Ian Jackson, yi.y.sun,
xen-devel
On Thu, Feb 09, 2017 at 12:42:41PM +0100, Juergen Gross wrote:
> On 09/02/17 12:36, Ian Jackson wrote:
> > Juergen Gross writes ("[PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c"):
> >> Splitting up libxl.c will require two functions to be globally visible.
> >> Add their prototypes to libxl_internal.h.
> >
> > Thanks. However,
> >
> >> -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)
> >
> > This function needs a libxl__ prefix adding to its name.
>
> Aah, of course!
>
> Will send V3 after waiting for more comments for a while...
>
If there are no more significant comments, you can just fold in
everything and provide a branch. No need to repost.
>
> Juergen
>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c
2017-02-09 15:44 ` Wei Liu
@ 2017-02-09 16:06 ` Juergen Gross
0 siblings, 0 replies; 23+ messages in thread
From: Juergen Gross @ 2017-02-09 16:06 UTC (permalink / raw)
To: Wei Liu; +Cc: haozhong.zhang, yi.y.sun, Ian Jackson, zhangchen.fnst, xen-devel
On 09/02/17 16:44, Wei Liu wrote:
> On Thu, Feb 09, 2017 at 12:42:41PM +0100, Juergen Gross wrote:
>> On 09/02/17 12:36, Ian Jackson wrote:
>>> Juergen Gross writes ("[PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c"):
>>>> Splitting up libxl.c will require two functions to be globally visible.
>>>> Add their prototypes to libxl_internal.h.
>>>
>>> Thanks. However,
>>>
>>>> -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)
>>>
>>> This function needs a libxl__ prefix adding to its name.
>>
>> Aah, of course!
>>
>> Will send V3 after waiting for more comments for a while...
>>
>
> If there are no more significant comments, you can just fold in
> everything and provide a branch. No need to repost.
Okay. Please pull from
https://github.com/jgross1/xen.git libxl-split-v3
Thanks,
Juergen
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2017-02-09 16:06 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-09 9:30 [PATCH v2 00/12] libxl: split up libxl.c Juergen Gross
2017-02-09 9:30 ` [PATCH v2 01/12] libxl: adjust copyright comment of libxl.c Juergen Gross
2017-02-09 10:18 ` Wei Liu
2017-02-09 11:37 ` Ian Jackson
2017-02-09 9:30 ` [PATCH v2 02/12] libxl: make some functions global to prepare splitting up libxl.c Juergen Gross
2017-02-09 11:36 ` Ian Jackson
2017-02-09 11:42 ` Juergen Gross
2017-02-09 15:44 ` Wei Liu
2017-02-09 16:06 ` Juergen Gross
2017-02-09 9:30 ` [PATCH v2 03/12] libxl: white space cleanup Juergen Gross
2017-02-09 11:37 ` Ian Jackson
2017-02-09 9:30 ` [PATCH v2 04/12] libxl: carve out cpupool specific functions from libxl.c Juergen Gross
2017-02-09 9:30 ` [PATCH v2 05/12] libxl: carve out scheduler " Juergen Gross
2017-02-09 9:30 ` [PATCH v2 06/12] libxl: carve out disk " Juergen Gross
2017-02-09 9:30 ` [PATCH v2 07/12] libxl: carve out console " Juergen Gross
2017-02-09 9:30 ` [PATCH v2 08/12] libxl: carve out memory " Juergen Gross
2017-02-09 9:30 ` [PATCH v2 09/12] libxl: move device specific functions out of libxl.c Juergen Gross
2017-02-09 9:30 ` [PATCH v2 10/12] libxl: carve out tmem specific functions from libxl.c Juergen Gross
2017-02-09 9:30 ` [PATCH v2 11/12] libxl: carve out domain " Juergen Gross
2017-02-09 9:30 ` [PATCH v2 12/12] libxl: make one function static Juergen Gross
2017-02-09 11:42 ` Ian Jackson
2017-02-09 10:22 ` [PATCH v2 00/12] libxl: split up libxl.c Wei Liu
2017-02-09 11:41 ` Ian Jackson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.