From: Roger Pau Monne Date: Thu, 31 Mar 2016 12:56:41 +0000 (+0200) Subject: libxl: properly use vdev vs local device X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~1361 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=955cfe3d23b4455946623772e88b89c6c739e0ab;p=xen.git libxl: properly use vdev vs local device The current code in libxl assumed that vdev is equal to local device, but this is only true for Linux systems. In other OSes the local device can use a nomenclature completely different from the virtual device one. Move the current libxl__devid_to_localdev Linux implementation out of the OS-specific file and rename it to libxl__devid_to_vdev, and then make sure local_device_attach_cb return the local device in the diskpath field. Signed-off-by: Roger Pau Monné Acked-by: Wei Liu --- diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 56179008bf..c884de91bf 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -3065,7 +3065,7 @@ static char * libxl__alloc_vdev(libxl__gc *gc, void *get_vdev_user, GCSPRINTF("%s/device/vbd/%d/backend", dompath, devid)) == NULL) { if (errno == ENOENT) - return libxl__devid_to_localdev(gc, devid); + return libxl__devid_to_vdev(gc, devid); else return NULL; } @@ -3202,7 +3202,7 @@ static void local_device_attach_cb(libxl__egc *egc, libxl__ao_device *aodev) { STATE_AO_GC(aodev->ao); libxl__disk_local_state *dls = CONTAINER_OF(aodev, *dls, aodev); - char *dev = NULL, *be_path = NULL; + char *be_path = NULL; int rc; libxl__device device; libxl_device_disk *disk = &dls->disk; @@ -3216,9 +3216,6 @@ static void local_device_attach_cb(libxl__egc *egc, libxl__ao_device *aodev) goto out; } - dev = GCSPRINTF("/dev/%s", disk->vdev); - LOG(DEBUG, "locally attaching disk %s", dev); - rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID, disk, &device); if (rc < 0) goto out; @@ -3227,8 +3224,9 @@ static void local_device_attach_cb(libxl__egc *egc, libxl__ao_device *aodev) if (rc < 0) goto out; - if (dev != NULL) - dls->diskpath = libxl__strdup(gc, dev); + dls->diskpath = GCSPRINTF("/dev/%s", + libxl__devid_to_localdev(gc, device.devid)); + LOG(DEBUG, "locally attached disk %s", dls->diskpath); dls->callback(egc, dls, 0); return; diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c index 38c121db31..dfdf860f84 100644 --- a/tools/libxl/libxl_device.c +++ b/tools/libxl/libxl_device.c @@ -459,6 +459,63 @@ int libxl__device_disk_dev_number(const char *virtpath, int *pdisk, return -1; } +static char *encode_disk_name(char *ptr, unsigned int n) +{ + if (n >= 26) + ptr = encode_disk_name(ptr, n / 26 - 1); + *ptr = 'a' + n % 26; + return ptr + 1; +} + +char *libxl__devid_to_vdev(libxl__gc *gc, int devid) +{ + unsigned int minor; + int offset; + int nr_parts; + char *ptr = NULL; +/* Same as in Linux. + * encode_disk_name might end up using up to 29 bytes (BUFFER_SIZE - 3) + * including the trailing \0. + * + * The code is safe because 26 raised to the power of 28 (that is the + * maximum offset that can be stored in the allocated buffer as a + * string) is far greater than UINT_MAX on 64 bits so offset cannot be + * big enough to exhaust the available bytes in ret. */ +#define BUFFER_SIZE 32 + char *ret = libxl__zalloc(gc, BUFFER_SIZE); + +#define EXT_SHIFT 28 +#define EXTENDED (1<= 26) - ptr = encode_disk_name(ptr, n / 26 - 1); - *ptr = 'a' + n % 26; - return ptr + 1; -} - char *libxl__devid_to_localdev(libxl__gc *gc, int devid) { - unsigned int minor; - int offset; - int nr_parts; - char *ptr = NULL; - char *ret = libxl__zalloc(gc, BUFFER_SIZE); - - if (!VDEV_IS_EXTENDED(devid)) { - minor = devid & 0xff; - nr_parts = 16; - } else { - minor = BLKIF_MINOR_EXT(devid); - nr_parts = 256; - } - offset = minor / nr_parts; - - strcpy(ret, "xvd"); - ptr = encode_disk_name(ret + 3, offset); - if (minor % nr_parts == 0) - *ptr = 0; - else - /* overflow cannot happen, thanks to the upper bound */ - snprintf(ptr, ret + 32 - ptr, - "%d", minor & (nr_parts - 1)); - return ret; + return libxl__devid_to_vdev(gc, devid); } /* Hotplug scripts helpers */