Files
xen/tools/libs/light/libxl_convert_callout.c
T
Juergen Gross 41aea82de2 tools/libxl: move libxenlight to tools/libs/light
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>
2020-10-01 13:26:09 +02:00

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);
}