All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xen.org>
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>,
	Wei Liu <wei.liu2@citrix.com>,
	Ian Jackson <Ian.Jackson@eu.citrix.com>,
	Ian Campbell <Ian.Campbell@citrix.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>
Subject: [PATCH v3 21/28] tools/libxl: Infrastructure for writing a v2 stream
Date: Mon, 13 Jul 2015 13:01:40 +0100	[thread overview]
Message-ID: <1436788907-1921-22-git-send-email-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <1436788907-1921-1-git-send-email-andrew.cooper3@citrix.com>

From: Ross Lagerwall <ross.lagerwall@citrix.com>

This contains the event machinery and state machines to write
non-checkpointed migration v2 stream (with the exception of the
xc_domain_save() handling which is spliced later in a bisectable way).

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Ian Campbell <Ian.Campbell@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>

---
v3: Similar changes to the read side, following the read side review.
---
 tools/libxl/Makefile             |    2 +-
 tools/libxl/libxl_internal.h     |   39 ++++
 tools/libxl/libxl_stream_write.c |  425 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 465 insertions(+), 1 deletion(-)
 create mode 100644 tools/libxl/libxl_stream_write.c

diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 68fe1c1..0150ec7 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -100,7 +100,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
 			libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o \
 			libxl_internal.o libxl_utils.o libxl_uuid.o \
 			libxl_json.o libxl_aoutils.o libxl_numa.o libxl_vnuma.o \
-			libxl_stream_read.o \
+			libxl_stream_read.o libxl_stream_write.o \
 			libxl_save_callout.o _libxl_save_msgs_callout.o \
 			libxl_qmp.o libxl_event.o libxl_fork.o $(LIBXL_OBJS-y)
 LIBXL_OBJS += libxl_genid.o
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 72d544a..c93f4a6 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2958,6 +2958,45 @@ typedef void libxl__domain_suspend_cb(libxl__egc*,
 typedef void libxl__save_device_model_cb(libxl__egc*,
                                          libxl__domain_suspend_state*, int rc);
 
+/* State for writing a libxl migration v2 stream */
+typedef struct libxl__stream_write_state libxl__stream_write_state;
+typedef void (*sws_record_done_cb)(libxl__egc *egc,
+                                   libxl__stream_write_state *sws);
+struct libxl__stream_write_state {
+    /* filled by the user */
+    libxl__ao *ao;
+    libxl__domain_suspend_state *dss;
+    int fd;
+    void (*completion_callback)(libxl__egc *egc,
+                                libxl__stream_write_state *sws,
+                                int rc);
+    /* Private */
+    int rc;
+    bool running;
+
+    /* Main stream-writing data. */
+    libxl__datacopier_state dc;
+    sws_record_done_cb record_done_callback;
+
+    /* Only used when constructing an EMULATOR record. */
+    libxl__datacopier_state emu_dc;
+    libxl__carefd *emu_carefd;
+    libxl__sr_rec_hdr emu_rec_hdr;
+    void *emu_body;
+};
+
+_hidden void libxl__stream_write_init(libxl__stream_write_state *stream);
+_hidden void libxl__stream_write_start(libxl__egc *egc,
+                                       libxl__stream_write_state *stream);
+_hidden void libxl__stream_write_abort(libxl__egc *egc,
+                                       libxl__stream_write_state *stream,
+                                       int rc);
+static inline bool
+libxl__stream_write_inuse(const libxl__stream_write_state *stream)
+{
+    return stream->running;
+}
+
 typedef struct libxl__logdirty_switch {
     const char *cmd;
     const char *cmd_path;
diff --git a/tools/libxl/libxl_stream_write.c b/tools/libxl/libxl_stream_write.c
new file mode 100644
index 0000000..2e40978
--- /dev/null
+++ b/tools/libxl/libxl_stream_write.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2015      Citrix Ltd.
+ *
+ * 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" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+/*
+ * Infrastructure for writing a domain to a libxl migration v2 stream.
+ *
+ * Entry points from outside:
+ *  - libxl__stream_write_start()
+ *     - Start writing a stream from the start.
+ *
+ * In normal operation, there are two tasks running at once; this
+ * stream processing, and the libxl-save-helper.  check_all_finished()
+ * is used to join all the tasks in both success and error cases.
+ *
+ * Nomenclature for event callbacks:
+ *  - $FOO_done(): Completion callback for $FOO
+ *  - write_$FOO(): Set up the datacopier to write a $FOO
+ *  - $BAR_header(): A $BAR record header only
+ *  - $BAR_record(): A complete $BAR record with header and content
+ *
+ * The main loop for a plain VM writes:
+ *  - Stream header
+ *  - Libxc record
+ *  - Toolstack record
+ *  - if (hvm), Qemu record
+ *  - End record
+ */
+
+/* Success/error/cleanup handling. */
+static void stream_success(libxl__egc *egc,
+                           libxl__stream_write_state *stream);
+static void stream_complete(libxl__egc *egc,
+                            libxl__stream_write_state *stream, int rc);
+static void stream_done(libxl__egc *egc,
+                        libxl__stream_write_state *stream);
+static void check_all_finished(libxl__egc *egc,
+                               libxl__stream_write_state *stream, int rc);
+
+/* Event chain for a plain VM. */
+static void stream_header_done(libxl__egc *egc,
+                               libxl__datacopier_state *dc,
+                               int rc, int onwrite, int errnoval);
+static void libxc_header_done(libxl__egc *egc,
+                              libxl__stream_write_state *stream);
+/* libxl__xc_domain_save_done() lives here, event-order wise. */
+static void write_toolstack_record(libxl__egc *egc,
+                                   libxl__stream_write_state *stream);
+static void toolstack_record_done(libxl__egc *egc,
+                                  libxl__stream_write_state *stream);
+static void write_emulator_record(libxl__egc *egc,
+                                  libxl__stream_write_state *stream);
+static void emulator_read_done(libxl__egc *egc,
+                               libxl__datacopier_state *dc,
+                               int rc, int onwrite, int errnoval);
+static void emulator_record_done(libxl__egc *egc,
+                                 libxl__stream_write_state *stream);
+static void write_end_record(libxl__egc *egc,
+                             libxl__stream_write_state *stream);
+
+/*----- Helpers -----*/
+
+static void write_done(libxl__egc *egc,
+                       libxl__datacopier_state *dc,
+                       int rc, int onwrite, int errnoval);
+
+/* Helper to set up reading some data from the stream. */
+static void setup_write(libxl__egc *egc,
+                        libxl__stream_write_state *stream,
+                        const char *what,
+                        libxl__sr_rec_hdr *hdr, void *body,
+                        sws_record_done_cb cb)
+{
+    static const uint8_t zero_padding[1U << REC_ALIGN_ORDER] = { 0 };
+
+    libxl__datacopier_state *dc = &stream->dc;
+    int rc;
+
+    assert(stream->record_done_callback == NULL);
+
+    dc->writewhat = what;
+    dc->used      = 0;
+    dc->callback  = write_done;
+    rc = libxl__datacopier_start(dc);
+
+    if (rc) {
+        stream_complete(egc, stream, rc);
+        return;
+    }
+
+    size_t padsz = ROUNDUP(hdr->length, REC_ALIGN_ORDER) - hdr->length;
+
+    /* Insert header */
+    libxl__datacopier_prefixdata(egc, dc, hdr, sizeof(*hdr));
+
+    /* Optional body */
+    if (body)
+        libxl__datacopier_prefixdata(egc, dc, body, hdr->length);
+
+    /* Any required padding */
+    if (padsz > 0)
+        libxl__datacopier_prefixdata(egc, dc,
+                                     zero_padding, padsz);
+    stream->record_done_callback = cb;
+}
+
+static void write_done(libxl__egc *egc,
+                       libxl__datacopier_state *dc,
+                       int rc, int onwrite, int errnoval)
+{
+    libxl__stream_write_state *stream = CONTAINER_OF(dc, *stream, dc);
+    STATE_AO_GC(stream->ao);
+    sws_record_done_cb cb = stream->record_done_callback;
+
+    stream->record_done_callback = NULL;
+
+    if (onwrite || errnoval)
+        stream_complete(egc, stream, rc ?: ERROR_FAIL);
+    else
+        cb(egc, stream);
+}
+
+/*----- Entrypoints -----*/
+
+void libxl__stream_write_init(libxl__stream_write_state *stream)
+{
+    FILLZERO(*stream);
+}
+
+void libxl__stream_write_start(libxl__egc *egc,
+                               libxl__stream_write_state *stream)
+{
+    libxl__datacopier_state *dc = &stream->dc;
+    STATE_AO_GC(stream->ao);
+    struct libxl__sr_hdr hdr = { 0 };
+    int rc = 0;
+
+    stream->running = true;
+
+    dc->ao        = ao;
+    dc->readfd    = -1;
+    dc->writewhat = "save/migration stream";
+    dc->writefd   = stream->fd;
+    dc->maxsz     = -1;
+    dc->callback  = stream_header_done;
+
+    rc = libxl__datacopier_start(dc);
+    if (rc)
+        goto err;
+
+    hdr.ident   = htobe64(RESTORE_STREAM_IDENT);
+    hdr.version = htobe32(RESTORE_STREAM_VERSION);
+    hdr.options = htobe32(0);
+
+    libxl__datacopier_prefixdata(egc, dc, &hdr, sizeof(hdr));
+    return;
+
+ err:
+    assert(rc);
+    stream_complete(egc, stream, rc);
+}
+
+void libxl__stream_write_abort(libxl__egc *egc,
+                               libxl__stream_write_state *stream, int rc)
+{
+    assert(rc);
+
+    if (stream->running)
+        stream_complete(egc, stream, rc);
+}
+
+/*----- Event logic -----*/
+
+static void stream_header_done(libxl__egc *egc,
+                               libxl__datacopier_state *dc,
+                               int rc, int onwrite, int errnoval)
+{
+    libxl__stream_write_state *stream = CONTAINER_OF(dc, *stream, dc);
+    STATE_AO_GC(stream->ao);
+    struct libxl__sr_rec_hdr rec = { REC_TYPE_LIBXC_CONTEXT };
+
+    if (rc || errnoval)
+        stream_complete(egc, stream, rc ?: ERROR_FAIL);
+
+    setup_write(egc, stream, "libxc header",
+                &rec, NULL, libxc_header_done);
+}
+
+static void libxc_header_done(libxl__egc *egc,
+                              libxl__stream_write_state *stream)
+{
+    libxl__xc_domain_save(egc, stream->dss, &stream->dss->shs);
+}
+
+static void __attribute__((unused))
+write_toolstack_record(libxl__egc *egc,
+                                   libxl__stream_write_state *stream)
+{
+    libxl__domain_suspend_state *dss = stream->dss;
+    STATE_AO_GC(stream->ao);
+    struct libxl__sr_rec_hdr rec = { REC_TYPE_XENSTORE_DATA };
+    int rc;
+    uint8_t *toolstack_buf = NULL; /* We must free this. */
+    uint32_t toolstack_len;
+
+    rc = libxl__toolstack_save(dss->domid, &toolstack_buf,
+                               &toolstack_len, dss);
+    if (rc)
+        goto err;
+
+    rec.length = toolstack_len;
+
+    setup_write(egc, stream, "toolstack record",
+                &rec, toolstack_buf,
+                toolstack_record_done);
+
+    free(toolstack_buf);
+    return;
+
+ err:
+    assert(rc);
+    free(toolstack_buf);
+    stream_complete(egc, stream, rc);
+}
+
+static void toolstack_record_done(libxl__egc *egc,
+                                  libxl__stream_write_state *stream)
+{
+    libxl__domain_suspend_state *dss = stream->dss;
+
+    if (dss->type == LIBXL_DOMAIN_TYPE_HVM)
+        write_emulator_record(egc, stream);
+    else
+        write_end_record(egc, stream);
+}
+
+static void write_emulator_record(libxl__egc *egc,
+                                  libxl__stream_write_state *stream)
+{
+    libxl__domain_suspend_state *dss = stream->dss;
+    libxl__datacopier_state *dc = &stream->emu_dc;
+    STATE_AO_GC(stream->ao);
+    struct libxl__sr_rec_hdr *rec = &stream->emu_rec_hdr;
+    struct libxl__sr_emulator_hdr *ehdr = NULL;
+    struct stat st;
+    int rc;
+
+    assert(dss->type == LIBXL_DOMAIN_TYPE_HVM);
+
+    /* Convenience aliases */
+    const char *const filename = dss->dm_savefile;
+    const uint32_t domid = dss->domid;
+
+    libxl__carefd_begin();
+    int readfd = open(filename, O_RDONLY);
+    if (readfd == -1) {
+        rc = ERROR_FAIL;
+        LOGE(ERROR, "unable to open %s", filename);
+        libxl__carefd_unlock();
+        goto err;
+    }
+    stream->emu_carefd = libxl__carefd_opened(CTX, readfd);
+
+    if (fstat(readfd, &st)) {
+        rc = ERROR_FAIL;
+        LOGE(ERROR, "unable to fstat %s", filename);
+        goto err;
+    }
+
+    if (!S_ISREG(st.st_mode)) {
+        rc = ERROR_FAIL;
+        LOG(ERROR, "%s is not a plain file!", filename);
+        goto err;
+    }
+
+    rec->type = REC_TYPE_EMULATOR_CONTEXT;
+    rec->length = st.st_size + sizeof(*ehdr);
+    stream->emu_body = ehdr = libxl__malloc(NOGC, rec->length);
+
+    switch(libxl__device_model_version_running(gc, domid)) {
+    case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
+        ehdr->id = EMULATOR_QEMU_TRADITIONAL;
+        break;
+
+    case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
+        ehdr->id = EMULATOR_QEMU_UPSTREAM;
+        break;
+
+    default:
+        rc = ERROR_FAIL;
+        goto err;
+    }
+    ehdr->index = 0;
+
+    FILLZERO(*dc);
+    dc->ao            = stream->ao;
+    dc->readwhat      = "qemu save file";
+    dc->readfd        = readfd;
+    dc->maxsz         = -1;
+    dc->readbuf       = stream->emu_body + sizeof(*ehdr);
+    dc->bytes_to_read = rec->length - sizeof(*ehdr);
+    dc->callback      = emulator_read_done;
+
+    rc = libxl__datacopier_start(dc);
+    if (rc)
+        goto err;
+
+    return;
+
+ err:
+    assert(rc);
+    stream_complete(egc, stream, rc);
+}
+
+static void emulator_read_done(libxl__egc *egc,
+                               libxl__datacopier_state *dc,
+                               int rc, int onwrite, int errnoval)
+{
+    libxl__stream_write_state *stream = CONTAINER_OF(dc, *stream, emu_dc);
+    STATE_AO_GC(stream->ao);
+
+    if (rc || onwrite || errnoval) {
+        stream_complete(egc, stream, rc ?: ERROR_FAIL);
+        return;
+    }
+
+    libxl__carefd_close(stream->emu_carefd);
+    stream->emu_carefd = NULL;
+
+    setup_write(egc, stream, "emulator record",
+                &stream->emu_rec_hdr, stream->emu_body,
+                emulator_record_done);
+}
+
+static void emulator_record_done(libxl__egc *egc,
+                                 libxl__stream_write_state *stream)
+{
+    free(stream->emu_body);
+    stream->emu_body = NULL;
+
+    write_end_record(egc, stream);
+}
+
+static void write_end_record(libxl__egc *egc,
+                             libxl__stream_write_state *stream)
+{
+    struct libxl__sr_rec_hdr rec = { REC_TYPE_END };
+
+    setup_write(egc, stream, "end record",
+                &rec, NULL, stream_success);
+}
+
+/*----- Success/error/cleanup handling. -----*/
+
+static void stream_success(libxl__egc *egc, libxl__stream_write_state *stream)
+{
+    stream->rc = 0;
+    stream_done(egc, stream);
+}
+
+static void stream_complete(libxl__egc *egc,
+                            libxl__stream_write_state *stream, int rc)
+{
+    assert(stream->running);
+
+    if (!stream->rc)
+        stream->rc = rc;
+    stream_done(egc, stream);
+}
+
+static void stream_done(libxl__egc *egc,
+                        libxl__stream_write_state *stream)
+{
+    assert(stream->running);
+    stream->running = false;
+
+    if (stream->emu_carefd)
+        libxl__carefd_close(stream->emu_carefd);
+    free(stream->emu_body);
+
+    check_all_finished(egc, stream, stream->rc);
+}
+
+static void check_all_finished(libxl__egc *egc,
+                               libxl__stream_write_state *stream,
+                               int rc)
+{
+    libxl__domain_suspend_state *dss = stream->dss;
+    STATE_AO_GC(dss->ao);
+
+    if (!stream->rc && rc) {
+        /* First reported failure. Tear everything down. */
+        stream->rc = rc;
+
+        libxl__stream_write_abort(egc, stream, rc);
+        libxl__save_helper_abort(egc, &dss->shs);
+    }
+
+    /* Don't fire the callback until all our parallel tasks have stopped. */
+    if (!libxl__stream_write_inuse(stream) &&
+        !libxl__save_helper_inuse(&dss->shs))
+        stream->completion_callback(egc, stream, stream->rc);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.10.4

  parent reply	other threads:[~2015-07-13 12:01 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-13 12:01 [PATCH v3 00/27] Libxl migration v2 Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 01/28] bsd-sys-queue-h-seddery: Massage `offsetof' Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 02/28] tools/libxc: Always compile the compat qemu variables into xc_sr_context Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 03/28] tools/libxl: Introduce ROUNDUP() Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 04/28] tools/libxl: Introduce libxl__kill() Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 05/28] tools/libxl: Stash all restore parameters in domain_create_state Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 06/28] tools/libxl: Split libxl__domain_create_state.restore_fd in two Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 07/28] tools/libxl: Extra management APIs for the save helper Andrew Cooper
2015-07-13 13:21   ` Ian Campbell
2015-07-13 15:01   ` Ian Jackson
2015-07-13 12:01 ` [PATCH v3 08/28] tools/libxl: Add save_helper_state pointers to libxl__xc_domain_{save, restore}() Andrew Cooper
2015-07-13 13:24   ` Ian Campbell
2015-07-13 12:01 ` [PATCH v3 09/28] tools/xl: Mandatory flag indicating the format of the migration stream Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 10/28] docs: Libxl migration v2 stream specification Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 11/28] tools/python: Libxc migration v2 infrastructure Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 12/28] tools/python: Libxl " Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 13/28] tools/python: Other migration infrastructure Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 14/28] tools/python: Verification utility for v2 stream spec compliance Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 15/28] tools/python: Conversion utility for legacy migration streams Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 16/28] tools/libxl: Migration v2 stream format Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 17/28] tools/libxl: Infrastructure for reading a libxl migration v2 stream Andrew Cooper
2015-07-13 13:42   ` Ian Campbell
2015-07-13 13:53     ` Andrew Cooper
2015-07-13 14:11       ` Ian Jackson
2015-07-13 14:03     ` Ian Jackson
2015-07-13 14:31   ` Ian Jackson
2015-07-13 14:53     ` Andrew Cooper
2015-07-13 15:33       ` Ian Jackson
2015-07-13 15:08   ` Ian Jackson
2015-07-13 15:13     ` Andrew Cooper
2015-07-13 15:35       ` Ian Jackson
2015-07-13 12:01 ` [PATCH v3 18/28] tools/libxl: Infrastructure to convert a legacy stream Andrew Cooper
2015-07-13 14:45   ` Ian Jackson
2015-07-13 15:08     ` Andrew Cooper
2015-07-13 15:44       ` Ian Jackson
2015-07-13 15:53         ` Andrew Cooper
2015-07-13 15:56           ` Ian Jackson
2015-07-13 16:04           ` Ian Campbell
2015-07-13 12:01 ` [PATCH v3 19/28] tools/libxl: Convert a legacy stream if needed Andrew Cooper
2015-07-13 14:51   ` Ian Jackson
2015-07-13 15:20     ` Andrew Cooper
2015-07-13 15:44       ` Ian Jackson
2015-07-13 12:01 ` [PATCH v3 20/28] tools/libxc+libxl+xl: Restore v2 streams Andrew Cooper
2015-07-13 15:02   ` Ian Jackson
2015-07-13 12:01 ` Andrew Cooper [this message]
2015-07-13 15:09   ` [PATCH v3 21/28] tools/libxl: Infrastructure for writing a v2 stream Ian Jackson
2015-07-13 15:21   ` Ian Jackson
2015-07-13 15:33     ` Andrew Cooper
2015-07-13 15:47       ` Ian Jackson
2015-07-13 15:56         ` Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 22/28] tools/libxc+libxl+xl: Save v2 streams Andrew Cooper
2015-07-13 15:25   ` Ian Jackson
2015-07-13 12:01 ` [PATCH v3 23/28] docs/libxl: Introduce CHECKPOINT_END to support migration v2 remus streams Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 24/28] tools/libxl: Write checkpoint records into the stream Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 25/28] tools/libx{c, l}: Introduce restore_callbacks.checkpoint() Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 26/28] tools/libxl: Handle checkpoint records in a libxl migration v2 stream Andrew Cooper
2015-07-13 13:53   ` Ian Campbell
2015-07-14 10:33   ` Yang Hongyang
2015-07-14 10:35     ` Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 27/28] tools/libxc: Drop all XG_LIBXL_HVM_COMPAT code from libxc Andrew Cooper
2015-07-13 12:01 ` [PATCH v3 28/28] tools/libxl: Drop all knowledge of toolstack callbacks Andrew Cooper
2015-07-13 15:55   ` Ian Jackson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1436788907-1921-22-git-send-email-andrew.cooper3@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=Ian.Jackson@eu.citrix.com \
    --cc=ross.lagerwall@citrix.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.