[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 30/31] libxl_dm: Pre-open QMP socket for QEMU
When starting QEMU with dm_restrict=1, pre-open the QMP socket before exec QEMU. That socket will be usefull to findout if QEMU is ready, and pre-opening it means that libxl can connect to it without waiting for QEMU to create it. The pre-openning is conditionnal, based on the use of dm_restrict because it is using a new command line option of QEMU, and dm_restrict support in QEMU is newer. -chardev socket,fd=X is available with QEMU 2.12, since commit: > char: allow passing pre-opened socket file descriptor at startup > 0935700f8544033ebbd41e1f13cd528f8a58d24d dm_restrict will be available in QEMU 3.0. Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx> --- Notes: We may want to set cloexec on the socket up to the forking point. Because if the socket stay open in a random process, libxl will not detected right away if QEMU as failed to start. On the other hand, we can rely on timeouts. tools/libxl/libxl_dm.c | 73 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index 18ada69e8b..10b35d822a 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -24,6 +24,8 @@ #include <sys/types.h> #include <pwd.h> #include <grp.h> +#include <sys/socket.h> +#include <sys/un.h> static const char *libxl_tapif_script(libxl__gc *gc) { @@ -913,7 +915,7 @@ static int libxl__build_device_model_args_new(libxl__gc *gc, const libxl_domain_config *guest_config, char ***args, char ***envs, const libxl__domain_build_state *state, - int *dm_state_fd) + int *dm_state_fd, int *dm_monitor_fd) { const libxl_domain_create_info *c_info = &guest_config->c_info; const libxl_domain_build_info *b_info = &guest_config->b_info; @@ -942,10 +944,58 @@ static int libxl__build_device_model_args_new(libxl__gc *gc, GCSPRINTF("%d", guest_domid), NULL); flexarray_append(dm_args, "-chardev"); - flexarray_append(dm_args, - GCSPRINTF("socket,id=libxl-cmd," - "path=%s/qmp-libxl-%d,server,nowait", - libxl__run_dir_path(), guest_domid)); + /* If we have to use dm_restrict, QEMU need to be new enough and will have + * the new interface where we can pre-open the QMP socket. */ + if (libxl_defbool_val(b_info->dm_restrict)) + { + int socket_fd = -1; + struct sockaddr_un un; + const char *socket_path; + + socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + *dm_monitor_fd = socket_fd; + if (socket_fd < 0) { + LOGED(ERROR, guest_domid, "Failed to create UNIX socket"); + return ERROR_FAIL; + } + + socket_path = GCSPRINTF("%s/qmp-libxl-%d", + libxl__run_dir_path(), guest_domid); + if (strlen(socket_path) > sizeof(un.sun_path)) { + LOGD(ERROR, guest_domid, "UNIX socket path '%s' is too long", + socket_path); + LOGD(DEBUG, guest_domid, "Path must be less than %zu bytes", + sizeof(un.sun_path)); + return ERROR_FAIL; + } + + if (unlink(socket_path) < 0 && errno != ENOENT) { + LOGED(ERROR, guest_domid, "Failed to unlink socket %s", socket_path); + return ERROR_FAIL; + } + + memset(&un, 0, sizeof(un)); + un.sun_family = AF_UNIX; + strncpy(un.sun_path, socket_path, sizeof(un.sun_path)); + if (bind(socket_fd, (struct sockaddr*) &un, sizeof(un)) < 0) { + LOGED(ERROR, guest_domid, "Failed to bind socket to %s", socket_path); + return ERROR_FAIL; + } + + if (listen(socket_fd, 1) < 0) { + LOGED(ERROR, guest_domid, "Failed to listen on socket"); + return ERROR_FAIL; + } + + flexarray_append(dm_args, + GCSPRINTF("socket,id=libxl-cmd,fd=%d,server,nowait", + socket_fd)); + } else { + flexarray_append(dm_args, + GCSPRINTF("socket,id=libxl-cmd," + "path=%s/qmp-libxl-%d,server,nowait", + libxl__run_dir_path(), guest_domid)); + } flexarray_append(dm_args, "-no-shutdown"); flexarray_append(dm_args, "-mon"); @@ -1722,7 +1772,8 @@ static int libxl__build_device_model_args(libxl__gc *gc, const libxl_domain_config *guest_config, char ***args, char ***envs, const libxl__domain_build_state *state, - int *dm_state_fd) + int *dm_state_fd, + int *dm_monitor_fd) /* dm_state_fd may be NULL iff caller knows we are using old stubdom * and therefore will be passing a filename rather than a fd. */ { @@ -1735,10 +1786,11 @@ static int libxl__build_device_model_args(libxl__gc *gc, case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: assert(dm_state_fd != NULL); assert(*dm_state_fd < 0); + assert(dm_monitor_fd != NULL); return libxl__build_device_model_args_new(gc, dm, guest_domid, guest_config, args, envs, - state, dm_state_fd); + state, dm_state_fd, dm_monitor_fd); default: LOGED(ERROR, guest_domid, "unknown device model version %d", guest_config->b_info.device_model_version); @@ -1958,7 +2010,7 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss) ret = libxl__build_device_model_args(gc, "stubdom-dm", guest_domid, guest_config, &args, NULL, - d_state, NULL); + d_state, NULL, NULL); if (ret) { ret = ERROR_FAIL; goto out; @@ -2244,6 +2296,7 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss) char **pass_stuff; const char *dm; int dm_state_fd = -1; + int dm_monitor_fd = -1; if (libxl_defbool_val(b_info->device_model_stubdomain)) { abort(); @@ -2261,7 +2314,8 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss) } rc = libxl__build_device_model_args(gc, dm, domid, guest_config, &args, &envs, state, - &dm_state_fd); + &dm_state_fd, + &dm_monitor_fd); if (rc) goto out; @@ -2359,6 +2413,7 @@ out_close: if (logfile_w >= 0) close(logfile_w); out: if (dm_state_fd >= 0) close(dm_state_fd); + if (dm_monitor_fd >= 0) close(dm_monitor_fd); if (rc) device_model_spawn_outcome(egc, dmss, rc); } -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |