diff --git a/5124efbe-add-qxl-support.patch b/5124efbe-add-qxl-support.patch new file mode 100644 index 0000000..5599934 --- /dev/null +++ b/5124efbe-add-qxl-support.patch @@ -0,0 +1,159 @@ +Usage: + vga="qxl" + +Qxl vga support many resolutions that not supported by stdvga, +mainly the 16:9 ones and other high up to 2560x1600. +With QXL you can get improved performance and smooth video also +with high resolutions and high quality. +Require their drivers installed in the domU and spice used +otherwise act as a simple stdvga. + +Signed-off-by: Fabio Fantoni +Signed-off-by: Zhou Peng +Acked-by: Stefano Stabellini +Acked-by: Ian Jackson +Acked-by: George Dunlap + +--- + +Changes in v16: +- refresh +- improved commit description + +Changes in v15: +- refresh +- small code improvements in libxl_dm.c + +Changes in v14: +- refresh +- update qemu parameters (from -vga to -device) + +NOTES: +Works correctly with windows domUs, tested on windows 7 64 bit +with qxl driver from spice guest tools 0.74. +I tested some resolution not supported by stdvga (1366x768, 1600x900 +and 1920x1080) with 32 bit color and all works good equal to kvm. +For now not works on linux domUs when xorg have 100% cpu and black +screen with qxl driver installed. +Seems needed other changes/fixes on xen and/or xorg/qxl driver side +before have it full working with linux domUs. +--- + docs/man/xl.cfg.pod.5 | 10 +++++++++- + tools/libxl/libxl_create.c | 13 +++++++++++++ + tools/libxl/libxl_dm.c | 8 ++++++++ + tools/libxl/libxl_types.idl | 1 + + tools/libxl/xl_cmdimpl.c | 2 ++ + 5 files changed, 33 insertions(+), 1 deletion(-) + +Index: xen-4.5.0-testing/docs/man/xl.cfg.pod.5 +=================================================================== +--- xen-4.5.0-testing.orig/docs/man/xl.cfg.pod.5 ++++ xen-4.5.0-testing/docs/man/xl.cfg.pod.5 +@@ -1292,6 +1292,9 @@ qemu-xen-traditional device-model, the a + which is sufficient for 1024x768 at 32 bpp. For the upstream qemu-xen + device-model, the default and minimum is 8 MB. + ++For B vga, the default is both default and minimal 128MB. ++If B is set less than 128MB, an error will be triggered. ++ + =item B + + Select a standard VGA card with VBE (VESA BIOS Extensions) as the +@@ -1303,9 +1306,14 @@ This option is deprecated, use vga="stdv + + =item B + +-Selects the emulated video card (none|stdvga|cirrus). ++Selects the emulated video card (none|stdvga|cirrus|qxl). + The default is cirrus. + ++In general, QXL should work with the Spice remote display protocol ++for acceleration, and QXL driver is necessary in guest in this case. ++QXL can also work with the VNC protocol, but it will be like a standard ++VGA without acceleration. ++ + =item B + + Allow access to the display via the VNC protocol. This enables the +Index: xen-4.5.0-testing/tools/libxl/libxl_create.c +=================================================================== +--- xen-4.5.0-testing.orig/tools/libxl/libxl_create.c ++++ xen-4.5.0-testing/tools/libxl/libxl_create.c +@@ -240,6 +240,10 @@ int libxl__domain_build_info_setdefault( + if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT) + b_info->video_memkb = 0; + break; ++ case LIBXL_VGA_INTERFACE_TYPE_QXL: ++ LOG(ERROR,"qemu upstream required for qxl vga"); ++ return ERROR_INVAL; ++ break; + case LIBXL_VGA_INTERFACE_TYPE_STD: + if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT) + b_info->video_memkb = 8 * 1024; +@@ -264,6 +268,15 @@ int libxl__domain_build_info_setdefault( + if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT) + b_info->video_memkb = 0; + break; ++ case LIBXL_VGA_INTERFACE_TYPE_QXL: ++ if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT) { ++ b_info->video_memkb = (128 * 1024); ++ } else if (b_info->video_memkb < (128 * 1024)) { ++ LOG(ERROR, ++ "128 Mib videoram is the minimum for qxl default"); ++ return ERROR_INVAL; ++ } ++ break; + case LIBXL_VGA_INTERFACE_TYPE_STD: + if (b_info->video_memkb == LIBXL_MEMKB_DEFAULT) + b_info->video_memkb = 16 * 1024; +Index: xen-4.5.0-testing/tools/libxl/libxl_dm.c +=================================================================== +--- xen-4.5.0-testing.orig/tools/libxl/libxl_dm.c ++++ xen-4.5.0-testing/tools/libxl/libxl_dm.c +@@ -244,6 +244,8 @@ static char ** libxl__build_device_model + case LIBXL_VGA_INTERFACE_TYPE_NONE: + flexarray_append_pair(dm_args, "-vga", "none"); + break; ++ case LIBXL_VGA_INTERFACE_TYPE_QXL: ++ break; + } + + if (b_info->u.hvm.boot) { +@@ -590,6 +592,12 @@ static char ** libxl__build_device_model + break; + case LIBXL_VGA_INTERFACE_TYPE_NONE: + break; ++ case LIBXL_VGA_INTERFACE_TYPE_QXL: ++ /* QXL have 2 ram regions, ram and vram */ ++ flexarray_append_pair(dm_args, "-device", ++ GCSPRINTF("qxl-vga,vram_size_mb=%"PRIu64",ram_size_mb=%"PRIu64, ++ (b_info->video_memkb/2/1024), (b_info->video_memkb/2/1024) ) ); ++ break; + } + + if (b_info->u.hvm.boot) { +Index: xen-4.5.0-testing/tools/libxl/libxl_types.idl +=================================================================== +--- xen-4.5.0-testing.orig/tools/libxl/libxl_types.idl ++++ xen-4.5.0-testing/tools/libxl/libxl_types.idl +@@ -181,6 +181,7 @@ libxl_vga_interface_type = Enumeration(" + (1, "CIRRUS"), + (2, "STD"), + (3, "NONE"), ++ (4, "QXL"), + ], init_val = "LIBXL_VGA_INTERFACE_TYPE_CIRRUS") + + libxl_vendor_device = Enumeration("vendor_device", [ +Index: xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c +=================================================================== +--- xen-4.5.0-testing.orig/tools/libxl/xl_cmdimpl.c ++++ xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c +@@ -1910,6 +1910,8 @@ skip_vfb: + b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS; + } else if (!strcmp(buf, "none")) { + b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE; ++ } else if (!strcmp(buf, "qxl")) { ++ b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL; + } else { + fprintf(stderr, "Unknown vga \"%s\" specified\n", buf); + exit(1); diff --git a/libxl.pvscsi.patch b/libxl.pvscsi.patch index 88c86a5..f1b35d6 100644 --- a/libxl.pvscsi.patch +++ b/libxl.pvscsi.patch @@ -503,7 +503,7 @@ Index: xen-4.5.0-testing/tools/libxl/libxl_create.c =================================================================== --- xen-4.5.0-testing.orig/tools/libxl/libxl_create.c +++ xen-4.5.0-testing/tools/libxl/libxl_create.c -@@ -1128,6 +1128,7 @@ static void domcreate_rebuild_done(libxl +@@ -1141,6 +1141,7 @@ static void domcreate_rebuild_done(libxl libxl__multidev_begin(ao, &dcs->multidev); dcs->multidev.callback = domcreate_launch_dm; libxl__add_disks(egc, ao, domid, d_config, &dcs->multidev); @@ -594,7 +594,7 @@ Index: xen-4.5.0-testing/tools/libxl/libxl_types.idl =================================================================== --- xen-4.5.0-testing.orig/tools/libxl/libxl_types.idl +++ xen-4.5.0-testing/tools/libxl/libxl_types.idl -@@ -539,6 +539,26 @@ libxl_device_channel = Struct("device_ch +@@ -540,6 +540,26 @@ libxl_device_channel = Struct("device_ch ])), ]) @@ -621,7 +621,7 @@ Index: xen-4.5.0-testing/tools/libxl/libxl_types.idl libxl_domain_config = Struct("domain_config", [ ("c_info", libxl_domain_create_info), ("b_info", libxl_domain_build_info), -@@ -552,6 +572,8 @@ libxl_domain_config = Struct("domain_con +@@ -553,6 +573,8 @@ libxl_domain_config = Struct("domain_con # a channel manifests as a console with a name, # see docs/misc/channels.txt ("channels", Array(libxl_device_channel, "num_channels")), @@ -630,7 +630,7 @@ Index: xen-4.5.0-testing/tools/libxl/libxl_types.idl ("on_poweroff", libxl_action_on_shutdown), ("on_reboot", libxl_action_on_shutdown), -@@ -594,6 +616,28 @@ libxl_vtpminfo = Struct("vtpminfo", [ +@@ -595,6 +617,28 @@ libxl_vtpminfo = Struct("vtpminfo", [ ("uuid", libxl_uuid), ], dir=DIR_OUT) @@ -904,7 +904,7 @@ Index: xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) { d_config->num_vtpms = 0; d_config->vtpms = NULL; -@@ -6490,6 +6668,256 @@ int main_blockdetach(int argc, char **ar +@@ -6492,6 +6670,256 @@ int main_blockdetach(int argc, char **ar return rc; } diff --git a/libxl.set-migration-constraints-from-cmdline.patch b/libxl.set-migration-constraints-from-cmdline.patch index 732d2eb..b832ee5 100644 --- a/libxl.set-migration-constraints-from-cmdline.patch +++ b/libxl.set-migration-constraints-from-cmdline.patch @@ -387,7 +387,7 @@ Index: xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c =================================================================== --- xen-4.5.0-testing.orig/tools/libxl/xl_cmdimpl.c +++ xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c -@@ -3878,6 +3878,8 @@ static void migrate_do_preamble(int send +@@ -3880,6 +3880,8 @@ static void migrate_do_preamble(int send } static void migrate_domain(uint32_t domid, const char *rune, int debug, @@ -396,7 +396,7 @@ Index: xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c const char *override_config_file) { pid_t child = -1; -@@ -3886,7 +3888,13 @@ static void migrate_domain(uint32_t domi +@@ -3888,7 +3890,13 @@ static void migrate_domain(uint32_t domi char *away_domname; char rc_buf; uint8_t *config_data; @@ -411,7 +411,7 @@ Index: xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c save_domain_core_begin(domid, override_config_file, &config_data, &config_len); -@@ -3905,10 +3913,13 @@ static void migrate_domain(uint32_t domi +@@ -3907,10 +3915,13 @@ static void migrate_domain(uint32_t domi xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0); if (debug) @@ -428,7 +428,7 @@ Index: xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c " (rc=%d)\n", rc); if (rc == ERROR_GUEST_TIMEDOUT) goto failed_suspend; -@@ -4295,13 +4306,18 @@ int main_migrate(int argc, char **argv) +@@ -4297,13 +4308,18 @@ int main_migrate(int argc, char **argv) char *rune = NULL; char *host; int opt, daemonize = 1, monitor = 1, debug = 0; @@ -448,7 +448,7 @@ Index: xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c case 'C': config_filename = optarg; break; -@@ -4318,6 +4334,18 @@ int main_migrate(int argc, char **argv) +@@ -4320,6 +4336,18 @@ int main_migrate(int argc, char **argv) case 0x100: debug = 1; break; @@ -467,7 +467,7 @@ Index: xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c } domid = find_domain(argv[optind]); -@@ -4348,7 +4376,8 @@ int main_migrate(int argc, char **argv) +@@ -4350,7 +4378,8 @@ int main_migrate(int argc, char **argv) return 1; } diff --git a/qemu-xen-enable-spice-support.patch b/qemu-xen-enable-spice-support.patch new file mode 100644 index 0000000..2a22665 --- /dev/null +++ b/qemu-xen-enable-spice-support.patch @@ -0,0 +1,12 @@ +Index: xen-4.5.0-testing/tools/Makefile +=================================================================== +--- xen-4.5.0-testing.orig/tools/Makefile ++++ xen-4.5.0-testing/tools/Makefile +@@ -222,6 +222,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-fi + --datadir=$(SHAREDIR)/qemu-xen \ + --localstatedir=$(localstatedir) \ + --disable-kvm \ ++ $(QEMU_XEN_ENABLE_SPICE) \ + --disable-docs \ + --disable-guest-agent \ + --python=$(PYTHON) \ diff --git a/xen.changes b/xen.changes index e6f6cb5..3520c10 100644 --- a/xen.changes +++ b/xen.changes @@ -1,3 +1,17 @@ +------------------------------------------------------------------- +Mon Mar 16 10:14:15 MDT 2015 - carnold@suse.com + +- Enable spice support in qemu for x86_64 + 5124efbe-add-qxl-support.patch + qemu-xen-enable-spice-support.patch + +------------------------------------------------------------------- +Wed Mar 11 13:15:07 MDT 2015 - carnold@suse.com + +- bnc#921842 - Xentop doesn't display disk statistics for VMs using + qdisks + xentop-add-support-for-qdisk.patch + ------------------------------------------------------------------- Tue Feb 24 16:22:45 UTC 2015 - meissner@suse.com diff --git a/xen.spec b/xen.spec index c13fd96..30b73ba 100644 --- a/xen.spec +++ b/xen.spec @@ -1,7 +1,7 @@ # # spec file for package xen # -# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -98,6 +98,13 @@ BuildRequires: libpixman-1-0-devel BuildRequires: libuuid-devel BuildRequires: libxml2-devel BuildRequires: libyajl-devel +%ifarch x86_64 +%if 0%{?suse_version} > 1230 +BuildRequires: libspice-server-devel +BuildRequires: spice-protocol-devel +BuildRequires: usbredir-devel +%endif +%endif %if %{?with_qemu_traditional}0 BuildRequires: SDL-devel BuildRequires: pciutils-devel @@ -193,6 +200,7 @@ Source99: baselibs.conf # http://xenbits.xensource.com/ext/xenalyze Source20000: xenalyze.hg.tar.bz2 # Upstream patches +Patch1: 5124efbe-add-qxl-support.patch # Upstream qemu Patch250: VNC-Support-for-ExtendedKeyEvent-client-message.patch Patch251: 0001-net-move-the-tap-buffer-into-TAPState.patch @@ -214,6 +222,7 @@ Patch311: xl-coredump-file-location.patch Patch330: suspend_evtchn_lock.patch Patch331: xenpaging.doc.patch Patch332: local_attach_support_for_phy.patch +Patch333: xentop-add-support-for-qdisk.patch # Qemu traditional Patch350: blktap.patch Patch351: cdrom-removable.patch @@ -267,6 +276,7 @@ Patch464: set-mtu-from-bridge-for-tap-interface.patch Patch466: aarch64-rename-PSR_MODE_ELxx-to-match-linux-headers.patch Patch467: libxl.add-option-to-disable-disk-cache-flushes-in-qdisk.patch Patch470: qemu-xen-upstream-qdisk-cache-unsafe.patch +Patch471: qemu-xen-enable-spice-support.patch Patch472: tigervnc-long-press.patch # Hypervisor and PV driver Patches Patch501: x86-ioapic-ack-default.patch @@ -487,6 +497,7 @@ Authors: %prep %setup -q -n %xen_build_dir -a 1 -a 2 -a 3 -a 4 -a 5 -a 57 -a 20000 # Upstream patches +%patch1 -p1 # Upstream qemu patches %patch250 -p1 %patch251 -p1 @@ -507,6 +518,7 @@ Authors: %patch330 -p1 %patch331 -p1 %patch332 -p1 +%patch333 -p1 # Qemu traditional %patch350 -p1 %patch351 -p1 @@ -560,6 +572,7 @@ Authors: %patch466 -p1 %patch467 -p1 %patch470 -p1 +%patch471 -p1 %patch472 -p1 # Hypervisor and PV driver Patches %patch501 -p1 @@ -636,6 +649,11 @@ if diff -u xen/Makefile~ xen/Makefile then : no changes? fi +%ifarch x86_64 +%if 0%{?suse_version} > 1230 +export QEMU_XEN_ENABLE_SPICE="--enable-spice --enable-usb-redir" +%endif +%endif configure_flags= %if %{?with_stubdom}0 configure_flags=--enable-stubdom diff --git a/xentop-add-support-for-qdisk.patch b/xentop-add-support-for-qdisk.patch new file mode 100644 index 0000000..6e59d31 --- /dev/null +++ b/xentop-add-support-for-qdisk.patch @@ -0,0 +1,495 @@ +Index: xen-4.5.0-testing/tools/xenstat/libxenstat/Makefile +=================================================================== +--- xen-4.5.0-testing.orig/tools/xenstat/libxenstat/Makefile ++++ xen-4.5.0-testing/tools/xenstat/libxenstat/Makefile +@@ -24,7 +24,7 @@ MINOR=0 + LIB=src/libxenstat.a + SHLIB=src/libxenstat.so.$(MAJOR).$(MINOR) + SHLIB_LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so +-OBJECTS-y=src/xenstat.o ++OBJECTS-y=src/xenstat.o src/xenstat_qmp.o + OBJECTS-$(CONFIG_Linux) += src/xenstat_linux.o + OBJECTS-$(CONFIG_SunOS) += src/xenstat_solaris.o + OBJECTS-$(CONFIG_NetBSD) += src/xenstat_netbsd.o +Index: xen-4.5.0-testing/tools/xenstat/xentop/Makefile +=================================================================== +--- xen-4.5.0-testing.orig/tools/xenstat/xentop/Makefile ++++ xen-4.5.0-testing/tools/xenstat/xentop/Makefile +@@ -19,7 +19,7 @@ all install xentop: + else + + CFLAGS += -DGCC_PRINTF -Werror $(CFLAGS_libxenstat) +-LDLIBS += $(LDLIBS_libxenstat) $(CURSES_LIBS) $(SOCKET_LIBS) -lm ++LDLIBS += $(LDLIBS_libxenstat) $(CURSES_LIBS) $(SOCKET_LIBS) -lm -lyajl + CFLAGS += -DHOST_$(XEN_OS) + + # Include configure output (config.h) to headers search path +Index: xen-4.5.0-testing/tools/xenstat/libxenstat/src/xenstat_priv.h +=================================================================== +--- xen-4.5.0-testing.orig/tools/xenstat/libxenstat/src/xenstat_priv.h ++++ xen-4.5.0-testing/tools/xenstat/libxenstat/src/xenstat_priv.h +@@ -109,5 +109,7 @@ extern int xenstat_collect_networks(xens + extern void xenstat_uninit_networks(xenstat_handle * handle); + extern int xenstat_collect_vbds(xenstat_node * node); + extern void xenstat_uninit_vbds(xenstat_handle * handle); ++extern void read_attributes_qdisk(xenstat_node * node); ++extern xenstat_vbd *xenstat_save_vbd(xenstat_domain * domain, xenstat_vbd * vbd); + + #endif /* XENSTAT_PRIV_H */ +Index: xen-4.5.0-testing/tools/xenstat/libxenstat/src/xenstat.c +=================================================================== +--- xen-4.5.0-testing.orig/tools/xenstat/libxenstat/src/xenstat.c ++++ xen-4.5.0-testing/tools/xenstat/libxenstat/src/xenstat.c +@@ -657,6 +657,24 @@ static void xenstat_uninit_xen_version(x + * VBD functions + */ + ++/* Save VBD information */ ++xenstat_vbd *xenstat_save_vbd(xenstat_domain *domain, xenstat_vbd *vbd) ++{ ++ if (domain->vbds == NULL) { ++ domain->num_vbds = 1; ++ domain->vbds = malloc(sizeof(xenstat_vbd)); ++ } else { ++ domain->num_vbds++; ++ domain->vbds = realloc(domain->vbds, ++ domain->num_vbds * ++ sizeof(xenstat_vbd)); ++ } ++ if (domain->vbds != NULL) ++ domain->vbds[domain->num_vbds - 1] = *vbd; ++ ++ return domain->vbds; ++} ++ + /* Free VBD information */ + static void xenstat_free_vbds(xenstat_node * node) + { +Index: xen-4.5.0-testing/tools/xenstat/libxenstat/src/xenstat_linux.c +=================================================================== +--- xen-4.5.0-testing.orig/tools/xenstat/libxenstat/src/xenstat_linux.c ++++ xen-4.5.0-testing/tools/xenstat/libxenstat/src/xenstat_linux.c +@@ -417,6 +417,9 @@ int xenstat_collect_vbds(xenstat_node * + } + } + ++ /* Get qdisk statistics */ ++ read_attributes_qdisk(node); ++ + rewinddir(priv->sysfsvbd); + + for(dp = readdir(priv->sysfsvbd); dp != NULL ; +@@ -477,18 +480,10 @@ int xenstat_collect_vbds(xenstat_node * + continue; + } + +- if (domain->vbds == NULL) { +- domain->num_vbds = 1; +- domain->vbds = malloc(sizeof(xenstat_vbd)); +- } else { +- domain->num_vbds++; +- domain->vbds = realloc(domain->vbds, +- domain->num_vbds * +- sizeof(xenstat_vbd)); +- } +- if (domain->vbds == NULL) ++ if ((xenstat_save_vbd(domain, &vbd)) == NULL) { ++ perror("Allocation error"); + return 0; +- domain->vbds[domain->num_vbds - 1] = vbd; ++ } + } + + return 1; +Index: xen-4.5.0-testing/tools/xenstat/libxenstat/src/xenstat_qmp.c +=================================================================== +--- /dev/null ++++ xen-4.5.0-testing/tools/xenstat/libxenstat/src/xenstat_qmp.c +@@ -0,0 +1,387 @@ ++/* libxenstat: statistics-collection library for Xen ++ * ++ * This library 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; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "yajl/yajl_tree.h" ++ ++#include ++ ++#include "xenstat_priv.h" ++ ++static unsigned char *qmp_query(int, char *); ++ ++enum query_blockstats { ++ QMP_STATS_RETURN = 0, ++ QMP_STATS_DEVICE = 1, ++ QMP_STATS = 2, ++ QMP_RD_BYTES = 3, ++ QMP_WR_BYTES = 4, ++ QMP_RD_OPERATIONS = 5, ++ QMP_WR_OPERATIONS = 6, ++}; ++ ++enum query_block { ++ QMP_BLOCK_RETURN = 0, ++ QMP_BLOCK_DEVICE = 1, ++ QMP_INSERTED = 2, ++ QMP_FILE = 3, ++}; ++ ++ ++/* Given the qmp device name, get the image filename associated with it */ ++static char *qmp_get_block_image(xenstat_node *node, char *qmp_devname, int qfd) ++{ ++ char errbuf[1024], *tmp, *file = NULL; ++ char *query_block_cmd = "{ \"execute\": \"query-block\" }"; ++ static const char *const qblock[] = { ++ [ QMP_BLOCK_RETURN ] = "return", ++ [ QMP_BLOCK_DEVICE ] = "device", ++ [ QMP_INSERTED ] = "inserted", ++ [ QMP_FILE ] = "file", ++ }; ++ const char *ptr[] = {0, 0}; ++ unsigned char *qmp_stats; ++ yajl_val info, ret_obj, dev_obj, n; ++ int i; ++ ++ if ((qmp_stats = qmp_query(qfd, query_block_cmd)) == NULL) ++ return NULL; ++ ++ /* Use libyajl version 2.1.x or newer for the tree parser feature with bug fixes */ ++ if ((info = yajl_tree_parse((char *)qmp_stats, errbuf, sizeof(errbuf))) == NULL) { ++ free(qmp_stats); ++ return NULL; ++ } ++ ++ ptr[0] = qblock[QMP_BLOCK_RETURN]; /* "return" */ ++ if ((ret_obj = yajl_tree_get(info, ptr, yajl_t_array)) == NULL) ++ goto done; ++ ++ for (i=0; ilen; i++) { ++ n = YAJL_GET_ARRAY(ret_obj)->values[i]; ++ ++ ptr[0] = qblock[QMP_BLOCK_DEVICE]; /* "device" */ ++ if ((dev_obj = yajl_tree_get(n, ptr, yajl_t_any)) != NULL) { ++ tmp = YAJL_GET_STRING(dev_obj); ++ if (strcmp(qmp_devname, tmp)) ++ continue; ++ } ++ else ++ continue; ++ ++ ptr[0] = qblock[QMP_INSERTED]; /* "inserted" */ ++ n = yajl_tree_get(n, ptr, yajl_t_any); ++ if (n) { ++ ptr[0] = qblock[QMP_FILE]; /* "file" */ ++ n = yajl_tree_get(n, ptr, yajl_t_any); ++ if (n && YAJL_IS_STRING(n)) { ++ tmp = YAJL_GET_STRING(n); ++ file = malloc(strlen(tmp)+1); ++ if (file != NULL) ++ strcpy(file, tmp); ++ goto done; ++ } ++ } ++ } ++done: ++ yajl_tree_free(info); ++ return file; ++} ++ ++ ++/* Given a QMP device name, find the associated xenstore qdisk device id */ ++static void get_xs_devid_from_qmp_devname(xenstat_node * node, unsigned int domid, char *qmp_devname, ++ unsigned int *dev, unsigned int *sector_size, int qfd) ++{ ++ char **dev_ids, *tmp, *ptr, *image, path[80]; ++ unsigned int num_dev_ids; ++ int i, devid; ++ ++ /* Get all the qdisk dev IDs associated with the this VM */ ++ snprintf(path, sizeof(path),"/local/domain/0/backend/qdisk/%i", domid); ++ dev_ids = xs_directory(node->handle->xshandle, XBT_NULL, path, &num_dev_ids); ++ if (dev_ids == NULL) { ++ return; ++ } ++ ++ /* Get the filename of the image associated with this QMP device */ ++ image = qmp_get_block_image(node, qmp_devname, qfd); ++ if (image == NULL) { ++ free(dev_ids); ++ return; ++ } ++ ++ /* Look for a matching image in xenstore */ ++ for (i=0; ihandle->xshandle, XBT_NULL, path, NULL)) == NULL) ++ continue; ++ ++ /* Get to actual path in string */ ++ if ((tmp = strchr(ptr, '/')) == NULL) ++ tmp = ptr; ++ if (!strcmp(tmp,image)) { ++ *dev = devid; ++ free(ptr); ++ ++ /* Get the xenstore sector size of the image while we're here */ ++ snprintf(path, sizeof(path),"/local/domain/0/backend/qdisk/%i/%i/sector-size", domid, devid); ++ if ((ptr = xs_read(node->handle->xshandle, XBT_NULL, path, NULL)) != NULL) { ++ *sector_size = atoi((char *)ptr); ++ free(ptr); ++ } ++ break; ++ } ++ free(ptr); ++ } ++ ++ free(image); ++ free(dev_ids); ++} ++ ++/* Parse the stats buffer which contains I/O data for all the disks belonging to domid */ ++static void qmp_parse_stats(xenstat_node *node, unsigned int domid, unsigned char *stats_buf, int qfd) ++{ ++ char *qmp_devname, errbuf[1024]; ++ static const char *const qstats[] = { ++ [ QMP_STATS_RETURN ] = "return", ++ [ QMP_STATS_DEVICE ] = "device", ++ [ QMP_STATS ] = "stats", ++ [ QMP_RD_BYTES ] = "rd_bytes", ++ [ QMP_WR_BYTES ] = "wr_bytes", ++ [ QMP_RD_OPERATIONS ] = "rd_operations", ++ [ QMP_WR_OPERATIONS ] = "wr_operations", ++ }; ++ const char *ptr[] = {0, 0}; ++ yajl_val info, ret_obj, stats_obj, n; ++ xenstat_vbd vbd; ++ xenstat_domain *domain; ++ unsigned int sector_size = 512; ++ int i, j; ++ ++ /* Use libyajl version 2.0.3 or newer for the tree parser feature */ ++ if ((info = yajl_tree_parse((char *)stats_buf, errbuf, sizeof(errbuf))) == NULL) ++ return; ++ ++ ptr[0] = qstats[QMP_STATS_RETURN]; /* "return" */ ++ if ((ret_obj = yajl_tree_get(info, ptr, yajl_t_array)) == NULL) ++ goto done; ++ ++ /* Array of devices */ ++ for (i=0; ilen; i++) { ++ memset(&vbd, 0, sizeof(xenstat_vbd)); ++ qmp_devname = NULL; ++ stats_obj = YAJL_GET_ARRAY(ret_obj)->values[i]; ++ ++ ptr[0] = qstats[QMP_STATS_DEVICE]; /* "device" */ ++ if ((n = yajl_tree_get(stats_obj, ptr, yajl_t_any)) != NULL) ++ qmp_devname = YAJL_GET_STRING(n); ++ ++ ptr[0] = qstats[QMP_STATS]; /* "stats" */ ++ stats_obj = yajl_tree_get(stats_obj, ptr, yajl_t_object); ++ if (stats_obj && YAJL_IS_OBJECT(stats_obj)) { ++ for (j=3; j<7; j++) { ++ ptr[0] = qstats[j]; ++ n = yajl_tree_get(stats_obj, ptr, yajl_t_number); ++ if (n && YAJL_IS_NUMBER(n)) { ++ switch(j) { ++ case QMP_RD_BYTES: /* "rd_bytes" */ ++ vbd.rd_sects = YAJL_GET_INTEGER(n) / sector_size; ++ break; ++ case QMP_WR_BYTES: /* "wr_bytes" */ ++ vbd.wr_sects = YAJL_GET_INTEGER(n) / sector_size; ++ break; ++ case QMP_RD_OPERATIONS: /* "rd_operations" */ ++ vbd.rd_reqs = YAJL_GET_INTEGER(n); ++ break; ++ case QMP_WR_OPERATIONS: /* "wr_operations" */ ++ vbd.wr_reqs = YAJL_GET_INTEGER(n); ++ break; ++ } ++ } ++ } ++ /* With the QMP device name, lookup the xenstore qdisk device ID and set vdb.dev */ ++ if (qmp_devname) ++ get_xs_devid_from_qmp_devname(node, domid, qmp_devname, &vbd.dev, §or_size, qfd); ++ if ((domain = xenstat_node_domain(node, domid)) == NULL) ++ continue; ++ if ((xenstat_save_vbd(domain, &vbd)) == NULL) ++ goto done; ++ } ++ } ++done: ++ yajl_tree_free(info); ++} ++ ++/* Write a command via the QMP */ ++static size_t qmp_write(int qfd, char *cmd, size_t cmd_len) ++{ ++ size_t pos = 0; ++ ssize_t res; ++ ++ while (cmd_len > pos) { ++ res = write(qfd, cmd + pos, cmd_len - pos); ++ switch (res) { ++ case -1: ++ if (errno == EINTR || errno == EAGAIN) ++ continue; ++ return 0; ++ case 0: ++ errno = EPIPE; ++ return pos; ++ default: ++ pos += (size_t)res; ++ } ++ } ++ return pos; ++} ++ ++/* Read the data sent in response to a QMP execute query. Returns 1 for success */ ++static int qmp_read(int qfd, unsigned char **qstats) ++{ ++ unsigned char buf[1024], *ptr = NULL; ++ struct pollfd pfd[2]; ++ int n, qsize = 0; ++ ++ pfd[0].fd = qfd; ++ pfd[0].events = POLLIN; ++ while ((n = poll(pfd, POLLIN, 10)) > 0) { ++ if (pfd[0].revents & POLLIN) { ++ if ((n = read(qfd, buf, sizeof(buf))) < 0) { ++ return 0; ++ } ++ if (ptr == NULL) ++ ptr = malloc(n+1); ++ else ++ ptr = realloc(ptr, qsize+n+1); ++ if (ptr == NULL) ++ return 0; ++ memcpy(&ptr[qsize], buf, n); ++ qsize += n; ++ ptr[qsize] = 0; ++ *qstats = ptr; ++ } ++ } ++ return 1; ++} ++ ++/* With the given cmd, query QMP for requested data. Returns allocated buffer containing data or NULL */ ++static unsigned char *qmp_query(int qfd, char *cmd) ++{ ++ unsigned char *qstats = NULL; ++ int n; ++ ++ n = strlen(cmd); ++ if (qmp_write(qfd, cmd, n) != n) ++ return NULL; ++ if (!qmp_read(qfd, &qstats)) ++ return NULL; ++ return qstats; ++} ++ ++/* Returns a socket connected to the QMP socket. Returns -1 on failure. */ ++static int qmp_connect(char *path) ++{ ++ struct sockaddr_un sun; ++ int s; ++ ++ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) ++ return -1; ++ (void)fcntl(s, F_SETFD, 1); ++ ++ memset(&sun, 0, sizeof(struct sockaddr_un)); ++ sun.sun_family = AF_UNIX; ++ ++ if (strlen(path) >= sizeof(sun.sun_path)) { ++ close(s); ++ return -1; ++ } ++ ++ strcpy(sun.sun_path, path); ++ if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { ++ close(s); ++ return -1; ++ } ++ ++ return s; ++} ++ ++/* Get all the active domains */ ++static xc_domaininfo_t *get_domain_ids(int *num_doms) ++{ ++ xc_domaininfo_t *dominfo; ++ xc_interface *xc_handle; ++ ++ dominfo = calloc(1024, sizeof(xc_domaininfo_t)); ++ if (dominfo == NULL) ++ return NULL; ++ xc_handle = xc_interface_open(0,0,0); ++ *num_doms = xc_domain_getinfolist(xc_handle, 0, 1024, dominfo); ++ xc_interface_close(xc_handle); ++ return dominfo; ++} ++ ++/* Gather the qdisk statistics by querying QMP */ ++void read_attributes_qdisk(xenstat_node * node) ++{ ++ char *cmd_mode = "{ \"execute\": \"qmp_capabilities\" }"; ++ char *query_blockstats_cmd = "{ \"execute\": \"query-blockstats\" }"; ++ xc_domaininfo_t *dominfo = NULL; ++ unsigned char *qmp_stats, *val; ++ char path[80]; ++ int i, qfd, num_doms; ++ ++ dominfo = get_domain_ids(&num_doms); ++ if (dominfo == NULL) ++ return; ++ ++ for (i=0; ihandle->xshandle, XBT_NULL, path, NULL)) == NULL) ++ continue; ++ free(val); ++ ++ /* Connect to this VMs QMP socket */ ++ snprintf(path, sizeof(path), "/var/run/xen/qmp-libxl-%i", dominfo[i].domain); ++ if ((qfd = qmp_connect(path)) < 0) { ++ continue; ++ } ++ ++ /* First enable QMP capabilities so that we can query for data */ ++ if ((qmp_stats = qmp_query(qfd, cmd_mode)) != NULL) { ++ free(qmp_stats); ++ /* Query QMP for this VMs blockstats */ ++ if ((qmp_stats = qmp_query(qfd, query_blockstats_cmd)) != NULL) { ++ qmp_parse_stats(node, dominfo[i].domain, qmp_stats, qfd); ++ free(qmp_stats); ++ } ++ } ++ close(qfd); ++ } ++ ++ free(dominfo); ++} ++ diff --git a/xl-coredump-file-location.patch b/xl-coredump-file-location.patch index 0be926c..7403ce9 100644 --- a/xl-coredump-file-location.patch +++ b/xl-coredump-file-location.patch @@ -10,7 +10,7 @@ Index: xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c =================================================================== --- xen-4.5.0-testing.orig/tools/libxl/xl_cmdimpl.c +++ xen-4.5.0-testing/tools/libxl/xl_cmdimpl.c -@@ -2092,7 +2092,7 @@ static int handle_domain_death(uint32_t +@@ -2094,7 +2094,7 @@ static int handle_domain_death(uint32_t char *corefile; int rc;