aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl/libxl_linux.c
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-05-29 16:36:50 +0100
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-05-29 16:36:50 +0100
commit38c65b140ef885c9868a5ff8f5963f7aa4b5e997 (patch)
treec6d4ec274d1b6c1d6a5f8f66de1130b148233c5e /tools/libxl/libxl_linux.c
parentda84f22a257fe46b60c5a9986255bf176bb4695b (diff)
downloadxen-38c65b140ef885c9868a5ff8f5963f7aa4b5e997.tar.gz
xen-38c65b140ef885c9868a5ff8f5963f7aa4b5e997.tar.bz2
xen-38c65b140ef885c9868a5ff8f5963f7aa4b5e997.zip
libxl: introduce libxl__alloc_vdev
Introduce libxl__alloc_vdev: find a spare virtual block device in the domain passed as argument. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> Committed-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'tools/libxl/libxl_linux.c')
-rw-r--r--tools/libxl/libxl_linux.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/tools/libxl/libxl_linux.c b/tools/libxl/libxl_linux.c
index 925248b8ff..0169b2ff0b 100644
--- a/tools/libxl/libxl_linux.c
+++ b/tools/libxl/libxl_linux.c
@@ -25,3 +25,55 @@ int libxl__try_phy_backend(mode_t st_mode)
return 1;
}
+
+#define EXT_SHIFT 28
+#define EXTENDED (1<<EXT_SHIFT)
+#define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED))
+#define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
+/* the size of the buffer to store the device name is 32 bytes to match the
+ * equivalent buffer in the Linux kernel code */
+#define BUFFER_SIZE 32
+
+/* 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. */
+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_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;
+}