mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
libxl: use vchan for QMP access with Linux stubdomain
Access to QMP of QEMU in Linux stubdomain is possible over vchan connection. Handle the actual vchan connection in a separate process (vchan-socket-proxy). This simplified integration with QMP (already quite complex), but also allows preliminary filtering of (potentially malicious) QMP input. Since only one client can be connected to vchan server at the same time and it is not enforced by the libxenvchan itself, additional client-side locking is needed. It is implicitly implemented by vchan-socket-proxy, as it handle only one connection at a time. Note that qemu supports only one simultaneous client on a control socket anyway (but in UNIX socket case, it enforce it server-side), so it doesn't add any extra limitation. libxl qmp client code already has locking to handle concurrent access attempts to the same qemu qmp interface. Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> Squash in changes of regenerated autotools files. Kill the vchan-socket-proxy so we don't leak the daemonized processes. libxl__stubdomain_is_linux_running() works against the guest_domid, but the xenstore path is beneath the stubdomain. This leads to the use of libxl_is_stubdom in addition to libxl__stubdomain_is_linux_running() so that the stubdomain calls kill for the qmp-proxy. Also call libxl__qmp_cleanup() to remove the unix sockets used by vchan-socket-proxy. vchan-socket-proxy only creates qmp-libxl-$domid, and libxl__qmp_cleanup removes that as well as qmp-libxenstat-$domid. However, it tolerates ENOENT, and a stray qmp-libxenstat-$domid should not exist. Signed-off-by: Jason Andryuk <jandryuk@gmail.com> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
This commit is contained in:
1 parent
379ab27086
commit
83c845033d
9 files changed
+213
-69
No files matched your search
@@ -644,7 +644,6 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -723,7 +722,6 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -976,15 +974,6 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1122,7 +1111,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir runstatedir
|
||||
libdir localedir mandir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1275,7 +1264,6 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
|
||||
Vendored
+1
-13
@@ -634,7 +634,6 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -711,7 +710,6 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -964,15 +962,6 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1110,7 +1099,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir runstatedir
|
||||
libdir localedir mandir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1263,7 +1252,6 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
|
||||
Vendored
+1
-13
@@ -661,7 +661,6 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -751,7 +750,6 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -1004,15 +1002,6 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1150,7 +1139,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir runstatedir
|
||||
libdir localedir mandir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1303,7 +1292,6 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
|
||||
@@ -123,6 +123,9 @@
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* QMP proxy path */
|
||||
#undef STUBDOM_QMP_PROXY_PATH
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
|
||||
Vendored
+28
-18
@@ -772,7 +772,6 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -814,6 +813,7 @@ with_linux_backend_modules
|
||||
enable_qemu_traditional
|
||||
enable_rombios
|
||||
with_system_qemu
|
||||
with_stubdom_qmp_proxy
|
||||
with_system_seabios
|
||||
with_system_ovmf
|
||||
enable_ipxe
|
||||
@@ -899,7 +899,6 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -1152,15 +1151,6 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1298,7 +1288,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir runstatedir
|
||||
libdir localedir mandir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1451,7 +1441,6 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@@ -1535,6 +1524,9 @@ Optional Packages:
|
||||
Use system supplied qemu PATH or qemu (taken from
|
||||
$PATH) as qemu-xen device model instead of building
|
||||
and installing our own version
|
||||
--stubdom-qmp-proxy[=PATH]
|
||||
Use supplied binary PATH as a QMP proxy into
|
||||
stubdomain
|
||||
--with-system-seabios[=PATH]
|
||||
Use system supplied seabios PATH instead of building
|
||||
and installing our own version
|
||||
@@ -3382,7 +3374,7 @@ else
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -3428,7 +3420,7 @@ else
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -3452,7 +3444,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -3497,7 +3489,7 @@ else
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -3521,7 +3513,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@@ -4548,6 +4540,24 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
# Check whether --with-stubdom-qmp-proxy was given.
|
||||
if test "${with_stubdom_qmp_proxy+set}" = set; then :
|
||||
withval=$with_stubdom_qmp_proxy;
|
||||
stubdom_qmp_proxy="$withval"
|
||||
|
||||
else
|
||||
|
||||
stubdom_qmp_proxy="$bindir/vchan-socket-proxy"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define STUBDOM_QMP_PROXY_PATH "$stubdom_qmp_proxy"
|
||||
_ACEOF
|
||||
|
||||
|
||||
|
||||
# Check whether --with-system-seabios was given.
|
||||
if test "${with_system_seabios+set}" = set; then :
|
||||
withval=$with_system_seabios;
|
||||
|
||||
@@ -194,6 +194,15 @@ AC_SUBST(qemu_xen)
|
||||
AC_SUBST(qemu_xen_path)
|
||||
AC_SUBST(qemu_xen_systemd)
|
||||
|
||||
AC_ARG_WITH([stubdom-qmp-proxy],
|
||||
AC_HELP_STRING([--stubdom-qmp-proxy@<:@=PATH@:>@],
|
||||
[Use supplied binary PATH as a QMP proxy into stubdomain]),[
|
||||
stubdom_qmp_proxy="$withval"
|
||||
],[
|
||||
stubdom_qmp_proxy="$bindir/vchan-socket-proxy"
|
||||
])
|
||||
AC_DEFINE_UNQUOTED([STUBDOM_QMP_PROXY_PATH], ["$stubdom_qmp_proxy"], [QMP proxy path])
|
||||
|
||||
AC_ARG_WITH([system-seabios],
|
||||
AS_HELP_STRING([--with-system-seabios@<:@=PATH@:>@],
|
||||
[Use system supplied seabios PATH instead of building and installing
|
||||
|
||||
+159
-12
@@ -1200,7 +1200,11 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
|
||||
GCSPRINTF("%d", guest_domid), NULL);
|
||||
flexarray_append(dm_args, "-no-shutdown");
|
||||
|
||||
/* There is currently no way to access the QMP socket in the stubdom */
|
||||
/*
|
||||
* QMP access to qemu running in stubdomain is done over vchan. The
|
||||
* stubdomain init script adds the appropriate monitor options for
|
||||
* vchan-socket-proxy.
|
||||
*/
|
||||
if (!is_stubdom) {
|
||||
flexarray_append(dm_args, "-chardev");
|
||||
if (state->dm_monitor_fd >= 0) {
|
||||
@@ -2205,6 +2209,23 @@ static void stubdom_pvqemu_unpaused(libxl__egc *egc,
|
||||
static void stubdom_xswait_cb(libxl__egc *egc, libxl__xswait_state *xswait,
|
||||
int rc, const char *p);
|
||||
|
||||
static void spawn_qmp_proxy(libxl__egc *egc,
|
||||
libxl__stub_dm_spawn_state *sdss);
|
||||
|
||||
static void qmp_proxy_confirm(libxl__egc *egc, libxl__spawn_state *spawn,
|
||||
const char *xsdata);
|
||||
|
||||
static void qmp_proxy_startup_failed(libxl__egc *egc,
|
||||
libxl__spawn_state *spawn,
|
||||
int rc);
|
||||
|
||||
static void qmp_proxy_detached(libxl__egc *egc,
|
||||
libxl__spawn_state *spawn);
|
||||
|
||||
static void qmp_proxy_spawn_outcome(libxl__egc *egc,
|
||||
libxl__stub_dm_spawn_state *sdss,
|
||||
int rc);
|
||||
|
||||
char *libxl__stub_dm_name(libxl__gc *gc, const char *guest_name)
|
||||
{
|
||||
return GCSPRINTF("%s-dm", guest_name);
|
||||
@@ -2486,24 +2507,150 @@ static void spawn_stub_launch_dm(libxl__egc *egc,
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdss->pvqemu.spawn.ao = ao;
|
||||
sdss->pvqemu.guest_domid = dm_domid;
|
||||
sdss->pvqemu.guest_config = &sdss->dm_config;
|
||||
sdss->pvqemu.build_state = &sdss->dm_state;
|
||||
sdss->pvqemu.callback = spawn_stubdom_pvqemu_cb;
|
||||
|
||||
if (!need_qemu) {
|
||||
/* If dom0 qemu not needed, do not launch it */
|
||||
spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, 0);
|
||||
sdss->qmp_proxy_spawn.ao = ao;
|
||||
if (libxl__stubdomain_is_linux(&guest_config->b_info)) {
|
||||
spawn_qmp_proxy(egc, sdss);
|
||||
} else {
|
||||
libxl__spawn_local_dm(egc, &sdss->pvqemu);
|
||||
qmp_proxy_spawn_outcome(egc, sdss, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
assert(ret);
|
||||
spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, ret);
|
||||
qmp_proxy_spawn_outcome(egc, sdss, ret);
|
||||
}
|
||||
|
||||
static void spawn_qmp_proxy(libxl__egc *egc,
|
||||
libxl__stub_dm_spawn_state *sdss)
|
||||
{
|
||||
STATE_AO_GC(sdss->qmp_proxy_spawn.ao);
|
||||
const uint32_t guest_domid = sdss->dm.guest_domid;
|
||||
const uint32_t dm_domid = sdss->pvqemu.guest_domid;
|
||||
const char *dom_path = libxl__xs_get_dompath(gc, dm_domid);
|
||||
char **args;
|
||||
int nr = 0;
|
||||
int rc, logfile_w, null;
|
||||
|
||||
if (access(STUBDOM_QMP_PROXY_PATH, X_OK) < 0) {
|
||||
LOGED(ERROR, guest_domid, "qmp proxy %s is not executable", STUBDOM_QMP_PROXY_PATH);
|
||||
rc = ERROR_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdss->qmp_proxy_spawn.what = GCSPRINTF("domain %d device model qmp proxy", guest_domid);
|
||||
sdss->qmp_proxy_spawn.pidpath = GCSPRINTF("%s/image/qmp-proxy-pid", dom_path);
|
||||
sdss->qmp_proxy_spawn.xspath = DEVICE_MODEL_XS_PATH(gc, LIBXL_TOOLSTACK_DOMID,
|
||||
dm_domid, "/qmp-proxy-state");
|
||||
sdss->qmp_proxy_spawn.timeout_ms = LIBXL_DEVICE_MODEL_START_TIMEOUT * 1000;
|
||||
sdss->qmp_proxy_spawn.midproc_cb = libxl__spawn_record_pid;
|
||||
sdss->qmp_proxy_spawn.confirm_cb = qmp_proxy_confirm;
|
||||
sdss->qmp_proxy_spawn.failure_cb = qmp_proxy_startup_failed;
|
||||
sdss->qmp_proxy_spawn.detached_cb = qmp_proxy_detached;
|
||||
|
||||
const int arraysize = 6;
|
||||
GCNEW_ARRAY(args, arraysize);
|
||||
args[nr++] = STUBDOM_QMP_PROXY_PATH;
|
||||
args[nr++] = GCSPRINTF("--state-path=%s", sdss->qmp_proxy_spawn.xspath);
|
||||
args[nr++] = GCSPRINTF("%u", dm_domid);
|
||||
args[nr++] = GCSPRINTF("%s/device-model/%u/qmp-vchan", dom_path, guest_domid);
|
||||
args[nr++] = (char*)libxl__qemu_qmp_path(gc, guest_domid);
|
||||
args[nr++] = NULL;
|
||||
assert(nr == arraysize);
|
||||
|
||||
logfile_w = libxl__create_qemu_logfile(gc, GCSPRINTF("qmp-proxy-%s",
|
||||
sdss->dm_config.c_info.name));
|
||||
if (logfile_w < 0) {
|
||||
rc = logfile_w;
|
||||
goto out;
|
||||
}
|
||||
null = open("/dev/null", O_RDWR);
|
||||
if (null < 0) {
|
||||
LOGED(ERROR, guest_domid, "unable to open /dev/null");
|
||||
rc = ERROR_FAIL;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
rc = libxl__spawn_spawn(egc, &sdss->qmp_proxy_spawn);
|
||||
if (rc < 0)
|
||||
goto out_close;
|
||||
if (!rc) { /* inner child */
|
||||
setsid();
|
||||
libxl__exec(gc, null, null, logfile_w, STUBDOM_QMP_PROXY_PATH, args, NULL);
|
||||
/* unreachable */
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
out_close:
|
||||
if (logfile_w >= 0)
|
||||
close(logfile_w);
|
||||
if (null >= 0)
|
||||
close(null);
|
||||
out:
|
||||
if (rc)
|
||||
qmp_proxy_spawn_outcome(egc, sdss, rc);
|
||||
}
|
||||
|
||||
static void qmp_proxy_confirm(libxl__egc *egc, libxl__spawn_state *spawn,
|
||||
const char *xsdata)
|
||||
{
|
||||
STATE_AO_GC(spawn->ao);
|
||||
|
||||
if (!xsdata)
|
||||
return;
|
||||
|
||||
if (strcmp(xsdata, "running"))
|
||||
return;
|
||||
|
||||
libxl__spawn_initiate_detach(gc, spawn);
|
||||
}
|
||||
|
||||
static void qmp_proxy_startup_failed(libxl__egc *egc,
|
||||
libxl__spawn_state *spawn,
|
||||
int rc)
|
||||
{
|
||||
libxl__stub_dm_spawn_state *sdss = CONTAINER_OF(spawn, *sdss, qmp_proxy_spawn);
|
||||
qmp_proxy_spawn_outcome(egc, sdss, rc);
|
||||
}
|
||||
|
||||
static void qmp_proxy_detached(libxl__egc *egc,
|
||||
libxl__spawn_state *spawn)
|
||||
{
|
||||
libxl__stub_dm_spawn_state *sdss = CONTAINER_OF(spawn, *sdss, qmp_proxy_spawn);
|
||||
qmp_proxy_spawn_outcome(egc, sdss, 0);
|
||||
}
|
||||
|
||||
static void qmp_proxy_spawn_outcome(libxl__egc *egc,
|
||||
libxl__stub_dm_spawn_state *sdss,
|
||||
int rc)
|
||||
{
|
||||
STATE_AO_GC(sdss->qmp_proxy_spawn.ao);
|
||||
int need_pvqemu = libxl__need_xenpv_qemu(gc, &sdss->dm_config);
|
||||
|
||||
if (rc) goto out;
|
||||
|
||||
if (need_pvqemu < 0) {
|
||||
rc = need_pvqemu;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdss->pvqemu.spawn.ao = ao;
|
||||
sdss->pvqemu.guest_config = &sdss->dm_config;
|
||||
sdss->pvqemu.build_state = &sdss->dm_state;
|
||||
sdss->pvqemu.callback = spawn_stubdom_pvqemu_cb;
|
||||
if (need_pvqemu) {
|
||||
libxl__spawn_local_dm(egc, &sdss->pvqemu);
|
||||
} else {
|
||||
/* If dom0 qemu not needed, do not launch it */
|
||||
spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
assert(rc);
|
||||
spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, rc);
|
||||
}
|
||||
|
||||
static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
|
||||
|
||||
@@ -1260,10 +1260,20 @@ static void dm_destroy_cb(libxl__egc *egc,
|
||||
libxl__destroy_domid_state *dis = CONTAINER_OF(ddms, *dis, ddms);
|
||||
STATE_AO_GC(dis->ao);
|
||||
uint32_t domid = dis->domid;
|
||||
uint32_t target_domid;
|
||||
|
||||
if (rc < 0)
|
||||
LOGD(ERROR, domid, "libxl__destroy_device_model failed");
|
||||
|
||||
if (libxl_is_stubdom(CTX, domid, &target_domid) &&
|
||||
libxl__stubdomain_is_linux_running(gc, target_domid)) {
|
||||
char *path = GCSPRINTF("/local/domain/%d/image/qmp-proxy-pid", domid);
|
||||
|
||||
libxl__kill_xs_path(gc, path, "QMP Proxy");
|
||||
/* qmp-proxy for stubdom registers target_domid's QMP sockets. */
|
||||
libxl__qmp_cleanup(gc, target_domid);
|
||||
}
|
||||
|
||||
dis->drs.ao = ao;
|
||||
dis->drs.domid = domid;
|
||||
dis->drs.callback = devices_destroy_cb;
|
||||
|
||||
@@ -4166,6 +4166,7 @@ typedef struct {
|
||||
libxl__destroy_domid_state dis;
|
||||
libxl__multidev multidev;
|
||||
libxl__xswait_state xswait;
|
||||
libxl__spawn_state qmp_proxy_spawn;
|
||||
} libxl__stub_dm_spawn_state;
|
||||
|
||||
_hidden void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state*);
|
||||
|
||||