From: Stefano Stabellini <stefano.stabell...@eu.citrix.com> We actually need to spawn a second QEMU if we want to run qemu as non-root, because the pv backends ought to run as root (or device hotplug may not work).
So in this case, start a second QEMU to provide PV backends in userspace to HVM guests. Use both dcs->dmss.pvqemu and dcs->dmss.dm to keep track of the starting QEMUs. Only proceed when both QEMUs have started. And, we only default to running QEMU as non-root if we are going to be able to run split qemus. In particular, it is not safe to run split qemus if they don't support the emulator_id option, because we need to split the xenstore paths too. Signed-off-by: Stefano Stabellini <stefano.stabell...@eu.citrix.com> Signed-off-by: Ian Jackson <ian.jack...@eu.citrix.com> --- v6: Split only if trying to run a qemu as non-root Reorganise changes to dm callbacks No more dcs in dmss Use min() to calculate worst rc Explicitly set unused fields of dmss.pvqemu to 0 Change error handling v3: use dcs->dmss.pvqemu to spawn the second QEMU keep track of the rc of both QEMUs before proceeding --- tools/libxl/libxl_create.c | 72 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index e67e402..59dfcd67 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -431,6 +431,8 @@ static int domcreate_setdefault_dm_user(libxl__gc *gc, int rc; const char *user; + const char *dm = libxl__domain_device_model(gc, b_info); + if (b_info->device_model_user) /* already set, good-oh */ return 0; @@ -440,6 +442,15 @@ static int domcreate_setdefault_dm_user(libxl__gc *gc, /* we're not going to run it anyway */ return 0; + if (!libxl__dm_supported(gc, dm, libxl__dm_support_check__emulator_id)) { + /* we don't want to run the pv backends as non-root because + * device hotplug will no longer work. */ + LOG(WARN, + "Device model does not support split PV backends, running it as root"); + user = "root"; + goto found; + } + user = GCSPRINTF("%s%d", LIBXL_QEMU_USER_BASE, domid); rc = dm_runas_helper(gc, user); @@ -802,6 +813,14 @@ static void remus_checkpoint_stream_done( /* Event callbacks, in this order: */ static void domcreate_dm_support_checked(libxl__egc *egc, libxl__dm_support_check_state *checking, int rc); + +static void domcreate_dm_local_split_pv_cb(libxl__egc *egc, + libxl__dm_spawn_state *dmss); +static void domcreate_dm_local_split_dm_cb(libxl__egc *egc, + libxl__dm_spawn_state *dmss); +static void domcreate_dm_local_split_cb(libxl__egc *egc, + libxl__domain_create_state *dcs); + static void domcreate_devmodel_started(libxl__egc *egc, libxl__dm_spawn_state *dmss); static void domcreate_bootloader_console_available(libxl__egc *egc, @@ -1044,6 +1063,9 @@ static void domcreate_dm_support_checked(libxl__egc *egc, /* convenience aliases */ libxl_domain_config *const d_config = dcs->guest_config; + const libxl_domain_build_info *b_info = &d_config->b_info; + libxl__domain_build_state *const b_state = &dcs->build_state; + const uint32_t domid = dcs->guest_domid; const int restore_fd = dcs->restore_fd; if (rc) goto out; @@ -1053,6 +1075,15 @@ static void domcreate_dm_support_checked(libxl__egc *egc, rc = domcreate_setdefault_dm_user(gc, dcs); if (rc) goto out; + /* run two qemus? */ + if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM && + !libxl_defbool_val(d_config->b_info.device_model_stubdomain) && + b_info->device_model_user && + strcmp(b_info->device_model_user, "root")) { + rc = libxl__dm_emuidmap_add(gc, domid, b_state, EMUID_SPLIT); + if (rc) goto out; + } + dcs->bl.ao = ao; libxl_device_disk *bootdisk = d_config->num_disks > 0 ? &d_config->disks[0] : NULL; @@ -1130,6 +1161,11 @@ static void domcreate_bootloader_done(libxl__egc *egc, dcs->dmss.dm.callback = domcreate_devmodel_started; dcs->dmss.callback = domcreate_devmodel_started; + dcs->dmss.pvqemu.spawn.ao = ao; + dcs->dmss.pvqemu.guest_domid = domid; + dcs->dmss.pvqemu.guest_config = 0; + dcs->dmss.pvqemu.build_state = 0; + if (restore_fd < 0 && dcs->domid_soft_reset == INVALID_DOMID) { rc = libxl__domain_build(gc, d_config, domid, state); domcreate_rebuild_done(egc, dcs, rc); @@ -1398,6 +1434,16 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev, if (libxl_defbool_val(d_config->b_info.device_model_stubdomain)) { libxl__spawn_stub_dm(egc, &dcs->dmss, EMUID_DM); } else { + if (state->emuidmap & (1u << EMUID_SPLIT)) { + dcs->dmss.dm.rc = 1; + dcs->dmss.dm.callback = domcreate_dm_local_split_dm_cb; + + dcs->dmss.pvqemu.rc = 1; /* +ve means in progress */ + dcs->dmss.pvqemu.callback = domcreate_dm_local_split_pv_cb; + + libxl__spawn_qdisk_backend(egc, &dcs->dmss.pvqemu); + } + libxl__spawn_local_dm(egc, &dcs->dmss.dm, EMUID_DM); } @@ -1455,6 +1501,32 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev, domcreate_complete(egc, dcs, ret); } +static void domcreate_dm_local_split_pv_cb(libxl__egc *egc, + libxl__dm_spawn_state *dmss) +{ + libxl__domain_create_state *dcs = CONTAINER_OF(dmss, *dcs, dmss.pvqemu); + domcreate_dm_local_split_cb(egc, dcs); +} + +static void domcreate_dm_local_split_dm_cb(libxl__egc *egc, + libxl__dm_spawn_state *dmss) +{ + libxl__domain_create_state *dcs = CONTAINER_OF(dmss, *dcs, dmss.dm); + domcreate_dm_local_split_cb(egc, dcs); +} + +static void domcreate_dm_local_split_cb(libxl__egc *egc, + libxl__domain_create_state *dcs) +{ + if (dcs->dmss.dm.rc > 0 || + dcs->dmss.pvqemu.rc > 0) + /* something is still in progress */ + return; + + dcs->dmss.dm.rc = min(dcs->dmss.dm.rc, dcs->dmss.pvqemu.rc); + domcreate_devmodel_started(egc, &dcs->dmss.dm); +} + static void domcreate_devmodel_started(libxl__egc *egc, libxl__dm_spawn_state *dmss) { -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel