From 982e4ef9ec7dd86e5a3bd114190c28d487839d97 Mon Sep 17 00:00:00 2001 From: George Dunlap Date: Thu, 24 Mar 2016 17:18:34 +0000 Subject: [PATCH] libxl: Allow local access for block devices with hotplug scripts pygrub and qemuu need to be able to access a VM's disks locally in order to be able to pull out the kernel and provide emulated disk access, respectively. This can be done either by accessing the local disk directly, or by plugging the target disk into dom0 to allow access. Unfortunately, while the plugging machinery works for pygrub, it does not yet work for qemuu; this means that at the moment, disks with hotplug scripts or disks with non-dom0 backends cannot be provided as emulated devices to HVM domains. Fortunately, disks using hotplug scripts created in dom0 do create a block device as part of set-up, which can be accessed locally; and if they use block-common.sh:write_dev, this path will be written to physical-device-path. Modify libxl__device_disk_setdefault() to be able to fish this path out of xenstore and pass it to the caller. Unfortunately, at the time pygrub runs, the devices have not yet been set up. Rather than try to stash the domid somewhere to pass, we just pass INVALID_DOMID. This allows qemuu to emulate block devices created with custom hotplug scripts. Signed-off-by: George Dunlap Acked-by: Ian Jackson Tested-by: George Dunlap --- tools/libxl/libxl.c | 43 +++++++++++++++++++++++++++++++----- tools/libxl/libxl_dm.c | 4 ++-- tools/libxl/libxl_internal.h | 3 ++- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index c46c2ec1fd..75f00beeae 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -2317,7 +2317,7 @@ int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk) } int libxl__device_from_disk(libxl__gc *gc, uint32_t domid, - libxl_device_disk *disk, + const libxl_device_disk *disk, libxl__device *device) { int devid; @@ -3070,8 +3070,9 @@ static char * libxl__alloc_vdev(libxl__gc *gc, void *get_vdev_user, /* Callbacks */ char *libxl__device_disk_find_local_path(libxl__gc *gc, - const libxl_device_disk *disk, - bool qdisk_direct) + libxl_domid guest_domid, + const libxl_device_disk *disk, + bool qdisk_direct) { char *path = NULL; @@ -3100,6 +3101,38 @@ char *libxl__device_disk_find_local_path(libxl__gc *gc, path = libxl__strdup(gc, disk->pdev_path); LOG(DEBUG, "Directly accessing local QDISK target %s", path); goto out; + } + + /* + * If the format isn't raw and / or we're using a script, then see + * if the script has written a path to the "cooked" node + */ + if (disk->script && guest_domid != INVALID_DOMID) { + libxl__device device; + char *be_path, *pdpath; + int rc; + + LOG(DEBUG, + "Run from a script; checking for physical-device-path (vdev %s)", + disk->vdev); + + rc = libxl__device_from_disk(gc, guest_domid, disk, &device); + if (rc < 0) + goto out; + + be_path = libxl__device_backend_path(gc, &device); + + pdpath = libxl__sprintf(gc, "%s/physical-device-path", be_path); + + LOG(DEBUG, "Attempting to read node %s", pdpath); + path = libxl__xs_read(gc, XBT_NULL, pdpath); + + if (path) + LOG(DEBUG, "Accessing cooked block device %s", path); + else + LOG(DEBUG, "No physical-device-path, can't access locally."); + + goto out; } out: @@ -3126,7 +3159,8 @@ void libxl__device_disk_local_initiate_attach(libxl__egc *egc, LOG(DEBUG, "Trying to find local path"); - dls->diskpath = libxl__device_disk_find_local_path(gc, in_disk, false); + dls->diskpath = libxl__device_disk_find_local_path(gc, INVALID_DOMID, + in_disk, false); if (dls->diskpath) { LOG(DEBUG, "Local path found, executing callback."); dls->callback(egc, dls, 0); @@ -3142,7 +3176,6 @@ void libxl__device_disk_local_initiate_attach(libxl__egc *egc, rc = libxl__device_disk_setdefault(gc, disk); if (rc) goto out; - /* If we can't find a local path, attach it */ libxl__prepare_ao_device(ao, &dls->aodev); dls->aodev.callback = local_device_attach_cb; device_disk_add(egc, LIBXL_TOOLSTACK_DOMID, disk, &dls->aodev, diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index 2a3d0326b7..5b79aa279f 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -1353,8 +1353,8 @@ static int libxl__build_device_model_args_new(libxl__gc *gc, target_path = libxl__blktap_devpath(gc, disks[i].pdev_path, disks[i].format); else - target_path = libxl__device_disk_find_local_path(gc, - &disks[i], true); + target_path = libxl__device_disk_find_local_path(gc, + guest_domid, &disks[i], true); if (!target_path) { LOG(WARN, "No way to get local access disk to image: %s\n" diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index c87c42ae6e..7df2711500 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1714,7 +1714,7 @@ _hidden char *libxl__blktap_devpath(libxl__gc *gc, _hidden int libxl__device_destroy_tapdisk(libxl__gc *gc, const char *params); _hidden int libxl__device_from_disk(libxl__gc *gc, uint32_t domid, - libxl_device_disk *disk, + const libxl_device_disk *disk, libxl__device *device); /* Calls poll() again - useful to check whether a signaled condition @@ -2720,6 +2720,7 @@ static inline void libxl__device_disk_local_init(libxl__disk_local_state *dls) * See if we can find a way to access a disk locally */ _hidden char * libxl__device_disk_find_local_path(libxl__gc *gc, + libxl_domid guest_domid, const libxl_device_disk *disk, bool qdisk_direct); -- 2.30.2