#include "qemu/osdep.h"
+#include "qemu/option.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
#include "hw/hw.h"
XenQdiskVdevType type;
unsigned int disk;
unsigned int partition;
+ unsigned int number;
bool valid;
} XenQdiskVdev;
static char *xen_qdisk_get_name(XenBackend *dev, Error **errp)
{
XenQdiskBackend *d = XEN_QDISK_BACKEND(dev);
- XenQdiskVdev *vdev = &d->vdev;
- unsigned int number;
-
- switch (vdev->type) {
- case XEN_QDISK_VDEV_TYPE_DP:
- case XEN_QDISK_VDEV_TYPE_XVD:
- if (vdev->disk < (1 << 4) && vdev->partition < (1 << 4)) {
- number = (202 << 8) | (vdev->disk << 4) | vdev->partition;
- } else if (vdev->disk < (1 << 20) && vdev->partition < (1 << 8)) {
- number = (1 << 28) | (vdev ->disk << 8) | vdev->partition;
- } else {
- error_setg(errp, "cannot use xvd encoding for d%up%u",
- vdev->disk, vdev->partition);
- return NULL;
- }
- break;
- case XEN_QDISK_VDEV_TYPE_HD:
- if ((vdev->disk == 0 || vdev->disk == 1) &&
- vdev->partition < (1 << 4)) {
- number = (3 << 8) | (vdev->disk << 6) | vdev->partition;
- } else if ((vdev->disk == 2 || vdev->disk == 3) &&
- vdev->partition < (1 << 4)) {
- number = (22 << 8) | ((vdev->disk - 2) << 6) | vdev->partition;
- } else {
- error_setg(errp, "cannot use hd encoding for d%up%u",
- vdev->disk, vdev->partition);
- return NULL;
- }
- break;
-
- case XEN_QDISK_VDEV_TYPE_SD:
- if (vdev->disk < (1 << 4) && vdev->partition < (1 << 4)) {
- number = (8 << 8) | (vdev->disk << 4) | vdev->partition;
- } else {
- error_setg(errp, "cannot use sd encoding for d%up%u",
- vdev->disk, vdev->partition);
- return NULL;
- }
- break;
-
- default:
- error_setg(errp, "invalid type");
- return NULL;
- }
-
- return g_strdup_printf("%u", number);
+ return g_strdup_printf("%u", d->vdev.number);
}
static void xen_qdisk_bh(void *opaque)
info |= is_cdrom ? VDISK_CDROM : 0;
xenstore_backend_printf(dev, "info", "%u", info);
-
+
+ xenstore_frontend_printf(dev, "virtual-device", "%u", d->vdev.number);
xenstore_frontend_printf(dev, "device-type", "%s",
is_cdrom ? "cdrom" : "disk");
return disk;
}
-
+
static void xen_qdisk_set_vdev(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
vdev->partition = 0;
}
+ switch (vdev->type) {
+ case XEN_QDISK_VDEV_TYPE_DP:
+ case XEN_QDISK_VDEV_TYPE_XVD:
+ if (vdev->disk < (1 << 4) && vdev->partition < (1 << 4)) {
+ vdev->number = (202 << 8) | (vdev->disk << 4) |
+ vdev->partition;
+ } else if (vdev->disk < (1 << 20) && vdev->partition < (1 << 8)) {
+ vdev->number = (1 << 28) | (vdev ->disk << 8) |
+ vdev->partition;
+ } else {
+ goto invalid;
+ }
+ break;
+
+ case XEN_QDISK_VDEV_TYPE_HD:
+ if ((vdev->disk == 0 || vdev->disk == 1) &&
+ vdev->partition < (1 << 4)) {
+ vdev->number = (3 << 8) | (vdev->disk << 6) | vdev->partition;
+ } else if ((vdev->disk == 2 || vdev->disk == 3) &&
+ vdev->partition < (1 << 4)) {
+ vdev->number = (22 << 8) | ((vdev->disk - 2) << 6) |
+ vdev->partition;
+ } else {
+ goto invalid;
+ }
+ break;
+
+ case XEN_QDISK_VDEV_TYPE_SD:
+ if (vdev->disk < (1 << 4) && vdev->partition < (1 << 4)) {
+ vdev->number = (8 << 8) | (vdev->disk << 4) | vdev->partition;
+ } else {
+ goto invalid;
+ }
+ break;
+
+ default:
+ goto invalid;
+ }
+
g_free(str);
vdev->valid = true;
return;
invalid:
- error_setg(errp, "invalid vbd name");
+ error_setg(errp, "invalid virtual disk specifier");
g_free(str);
}
type_init(xen_qdisk_register_types)
-void xen_qdisk_backend_create(char *path)
+void xen_qdisk_backend_create(BusState *bus, struct xs_handle *xsh,
+ char *path)
{
+ char *params, *dev, *device_type, mode;
+ unsigned int discard_enable;
+ char *format = NULL;
+ char *file = NULL;
+ char *vdev = NULL;
+ char *media = NULL;
+ bool readonly = false;
+ char *optstr;
+ QemuOpts *opts;
+ DeviceState *qdisk;
+ BlockBackend *blk;
+
fprintf(stderr, "%s: %s\n", __func__, path);
+
+ if (xenstore_scanf(xsh, path, "params", "%ms", ¶ms) == 1) {
+ char **v = g_strsplit(params, ":", 2);
+
+ if (v[1] == NULL) {
+ file = g_strdup(v[0]);
+ } else {
+ if (strcmp(v[0], "aio") == 0) {
+ format = g_strdup("raw");
+ } else if (strcmp(v[0], "vhd") == 0) {
+ format = g_strdup("vpc");
+ } else {
+ format = g_strdup(v[0]);
+ }
+ file = g_strdup(v[1]);
+ }
+
+ g_strfreev(v);
+ free(params);
+ }
+
+ if (xenstore_scanf(xsh, path, "dev", "%ms", &dev) == 1) {
+ vdev = g_strdup(dev);
+ free(dev);
+ }
+
+ if (xenstore_scanf(xsh, path, "device-type", "%ms",
+ &device_type) == 1) {
+ media = g_strdup(device_type);
+ free(device_type);
+ }
+
+ if (xenstore_scanf(xsh, path, "mode", "%c", &mode) == 1 &&
+ mode != 'w') {
+ readonly = true;
+ }
+
+ if (xenstore_scanf(xsh, path, "discard-enable", "%u",
+ &discard_enable) != 1) {
+ discard_enable = 0;
+ }
+
+ if (!file || !vdev)
+ goto out;
+
+ optstr = g_strdup_printf("id=%s", vdev);
+ opts = drive_def(optstr);
+
+ qemu_opt_set(opts, "file", file, &error_abort);
+
+ if (media) {
+ qemu_opt_set(opts, "media", media, &error_abort);
+ }
+
+ if (format) {
+ qemu_opt_set(opts, "format", format, &error_abort);
+ }
+
+ qemu_opt_set_bool(opts, BDRV_OPT_CACHE_WB, true, &error_abort);
+ qemu_opt_set_bool(opts, BDRV_OPT_READ_ONLY, readonly, &error_abort);
+
+ drive_new(opts, IF_NONE);
+
+ qdisk = qdev_create(bus, TYPE_XEN_QDISK_BACKEND);
+ blk = blk_by_name(vdev);
+ qdev_prop_set_drive(qdisk, "drive", blk, &error_abort);
+ qdev_prop_set_string(qdisk, "vdev", vdev);
+ qdev_prop_set_bit(qdisk, "discard-enable", !!discard_enable);
+ qdev_init_nofail(qdisk);
+
+out:
+ g_free(format);
+ g_free(file);
+ g_free(media);
+ g_free(vdev);
+ g_free(optstr);
}
return rc;
}
+int xenstore_printf(struct xs_handle *xsh, char *node, const char *key,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int rc;
+
+ va_start(ap, fmt);
+ rc = xenstore_vprintf(xsh, node, key, fmt, ap);
+ va_end(ap);
+
+ return rc;
+}
+
+int xenstore_scanf(struct xs_handle *xsh, char *node, const char *key,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int rc;
+
+ va_start(ap, fmt);
+ rc = xenstore_vscanf(xsh, node, key, fmt, ap);
+ va_end(ap);
+
+ return rc;
+}
+
int xenstore_backend_printf(XenBackend *d, const char *key,
const char *fmt, ...)
{
k->bus_type = TYPE_XEN_BUS;
}
-static void xen_backend_compat_scan(const char *type,
+static void xen_backend_compat_scan(BusState *bus, const char *type,
XenBackendCreate create)
{
struct xs_handle *xsh;
path = g_strdup_printf("backend/%s/%u/%s", type, xen_domid,
backend[i]);
- create(path);
+ create(bus, xsh, path);
g_free(path);
}
void xen_bus_init(void)
{
DeviceState *dev = qdev_create(NULL, TYPE_XEN_BRIDGE);
-#if 0
- DeviceState *qdisk;
- QemuOpts *opts;
- BlockBackend *blk;
-#endif
XenBus *b;
qdev_init_nofail(dev);
/* Need a 'proper' way of getting current domid */
xen_backend_id = 0;
- xen_backend_compat_scan("qdisk", xen_qdisk_backend_create);
-
-#if 0
- opts = drive_def("id=extra");
- qemu_opt_set(opts, "file", "/root/disk.qcow2", &error_abort);
- qemu_opt_set(opts, "media", "disk", &error_abort);
- qemu_opt_set(opts, "format", "qcow2", &error_abort);
- qemu_opt_set_bool(opts, BDRV_OPT_CACHE_WB, true, &error_abort);
- qemu_opt_set_bool(opts, BDRV_OPT_READ_ONLY, false, &error_abort);
-
- drive_new(opts, IF_NONE);
-
- qdisk = qdev_create(BUS(b), "xen-qdisk");
- blk = blk_by_name("extra");
- qdev_prop_set_drive(qdisk, "drive", blk, &error_abort);
- qdev_prop_set_int32(qdisk, "disk", 1);
- qdev_init_nofail(qdisk);
-#endif
+ xen_backend_compat_scan(BUS(b), "qdisk", xen_qdisk_backend_create);
}
static const TypeInfo xen_bridge_type_info = {