mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
Carve out all libxenlight related sources and move them to tools/libs/light in order to use the generic library build environment. The closely related sources for libxl-save-helper and the libxl test environment are being moved, too. Signed-off-by: Juergen Gross <jgross@suse.com> Acked-by: Wei Liu <wl@xen.org>
174 lines
5.1 KiB
C
174 lines
5.1 KiB
C
/*
|
|
* Copyright (C) 2014 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"
|
|
|
|
#include "libxl_internal.h"
|
|
|
|
/*
|
|
* Infrastructure for converting a legacy migration stream into a
|
|
* libxl v2 stream.
|
|
*
|
|
* This is done by fork()ing the python conversion script, which takes
|
|
* in a legacy stream, and puts out a suitably-formatted v2 stream.
|
|
*/
|
|
|
|
static void helper_exited(libxl__egc *egc, libxl__ev_child *ch,
|
|
pid_t pid, int status);
|
|
static void helper_stop(libxl__egc *egc, libxl__ao_abortable *abrt, int rc);
|
|
static void helper_done(libxl__egc *egc,
|
|
libxl__conversion_helper_state *chs);
|
|
|
|
/*----- Entrypoints -----*/
|
|
|
|
void libxl__conversion_helper_init(libxl__conversion_helper_state *chs)
|
|
{
|
|
assert(chs->ao);
|
|
|
|
chs->v2_carefd = NULL;
|
|
chs->rc = 0;
|
|
libxl__ao_abortable_init(&chs->abrt);
|
|
libxl__ev_child_init(&chs->child);
|
|
}
|
|
|
|
int libxl__convert_legacy_stream(libxl__egc *egc,
|
|
libxl__conversion_helper_state *chs)
|
|
{
|
|
STATE_AO_GC(chs->ao);
|
|
libxl__carefd *child_in = NULL, *child_out = NULL;
|
|
int rc = 0;
|
|
|
|
chs->abrt.ao = chs->ao;
|
|
chs->abrt.callback = helper_stop;
|
|
rc = libxl__ao_abortable_register(&chs->abrt);
|
|
if (rc) goto err;
|
|
|
|
libxl__carefd_begin();
|
|
int fds[2];
|
|
if (libxl_pipe(CTX, fds)) {
|
|
rc = ERROR_FAIL;
|
|
libxl__carefd_unlock();
|
|
goto err;
|
|
}
|
|
child_out = libxl__carefd_record(CTX, fds[0]);
|
|
child_in = libxl__carefd_record(CTX, fds[1]);
|
|
libxl__carefd_unlock();
|
|
|
|
pid_t pid = libxl__ev_child_fork(gc, &chs->child, helper_exited);
|
|
if (!pid) {
|
|
char * const args[] =
|
|
{
|
|
getenv("LIBXL_CONVERT_HELPER") ?:
|
|
LIBEXEC_BIN "/convert-legacy-stream",
|
|
"--in", GCSPRINTF("%d", chs->legacy_fd),
|
|
"--out", GCSPRINTF("%d", fds[1]),
|
|
/*
|
|
* The width calculation is an assumption for the common
|
|
* case. The conversion script needs to know the width of
|
|
* the toolstack which saved the legacy stream.
|
|
*
|
|
* In the overwhelming majority of cases, the width of the
|
|
* saving toolstack will be the same as our current
|
|
* width. To avoid extending the libxl API with a
|
|
* parameter intended to disappear shortly, this option
|
|
* has not been exposed to the caller.
|
|
*
|
|
* If more complicated conversion is required, the
|
|
* conversion script can be instantiated manually, which
|
|
* will bypass all of this conversion logic.
|
|
*/
|
|
"--width", sizeof(unsigned long) == 8 ? "64" : "32",
|
|
|
|
"--guest", chs->hvm ? "hvm" : "pv",
|
|
"--format", "libxl",
|
|
/* "--verbose", */
|
|
NULL,
|
|
};
|
|
|
|
libxl_fd_set_cloexec(CTX, chs->legacy_fd, 0);
|
|
libxl_fd_set_cloexec(CTX, libxl__carefd_fd(child_in), 0);
|
|
|
|
libxl__exec(gc,
|
|
-1, -1, -1,
|
|
args[0], args, NULL);
|
|
}
|
|
|
|
libxl__carefd_close(child_in);
|
|
chs->v2_carefd = child_out;
|
|
|
|
assert(!rc);
|
|
return rc;
|
|
|
|
err:
|
|
libxl__ao_abortable_deregister(&chs->abrt);
|
|
assert(rc);
|
|
return rc;
|
|
}
|
|
|
|
void libxl__conversion_helper_abort(libxl__egc *egc,
|
|
libxl__conversion_helper_state *chs,
|
|
int rc)
|
|
{
|
|
STATE_AO_GC(chs->ao);
|
|
assert(rc);
|
|
|
|
if (libxl__conversion_helper_inuse(chs)) {
|
|
|
|
if (!chs->rc)
|
|
chs->rc = rc;
|
|
|
|
libxl__kill(gc, chs->child.pid, SIGTERM, "conversion helper");
|
|
}
|
|
}
|
|
|
|
/*----- State handling -----*/
|
|
|
|
static void helper_stop(libxl__egc *egc, libxl__ao_abortable *abrt, int rc)
|
|
{
|
|
libxl__conversion_helper_state *chs = CONTAINER_OF(abrt, *chs, abrt);
|
|
STATE_AO_GC(chs->ao);
|
|
|
|
libxl__conversion_helper_abort(egc, chs, rc);
|
|
}
|
|
|
|
static void helper_exited(libxl__egc *egc, libxl__ev_child *ch,
|
|
pid_t pid, int status)
|
|
{
|
|
libxl__conversion_helper_state *chs = CONTAINER_OF(ch, *chs, child);
|
|
STATE_AO_GC(chs->ao);
|
|
|
|
if (status) {
|
|
libxl_report_child_exitstatus(
|
|
CTX, chs->rc ? XTL_DEBUG : XTL_ERROR,
|
|
"conversion helper", pid, status);
|
|
|
|
if (!chs->rc)
|
|
chs->rc = ERROR_FAIL;
|
|
}
|
|
|
|
helper_done(egc, chs);
|
|
}
|
|
|
|
static void helper_done(libxl__egc *egc,
|
|
libxl__conversion_helper_state *chs)
|
|
{
|
|
STATE_AO_GC(chs->ao);
|
|
|
|
assert(!libxl__conversion_helper_inuse(chs));
|
|
|
|
libxl__ao_abortable_deregister(&chs->abrt);
|
|
|
|
chs->completion_callback(egc, chs, chs->rc);
|
|
}
|