#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qapi/visitor.h"
#include "hw/hw.h"
#include "hw/block/block.h"
#include "sysemu/blockdev.h"
#include "xen_blkif.h"
#include "trace.h"
+typedef enum XenVdevType {
+ XEN_VDEV_TYPE_XVD,
+ XEN_VDEV_TYPE_HD,
+ XEN_VDEV_TYPE_SD,
+ XEN_VDEV_TYPE__MAX
+} XenVdevType;
+
#define TYPE_XEN_QDISK_BACKEND "xen-qdisk"
#define XEN_QDISK_BACKEND(obj) \
OBJECT_CHECK(XenQdiskBackend, (obj), TYPE_XEN_QDISK_BACKEND)
typedef struct XenQdiskBackend {
XenBackend xendev;
+ XenVdevType type;
+ int disk;
+ unsigned int partition;
BlockConf conf;
bool discard_enable;
unsigned int max_ring_page_order;
BlockBackend *blk;
} XenQdiskBackend;
+static char *xen_qdisk_get_name(XenBackend *dev, Error **errp)
+{
+ XenQdiskBackend *d = XEN_QDISK_BACKEND(dev);
+ unsigned int number;
+
+ if (d->disk < 0) {
+ error_setg(errp, "invalid disk number (%d)", d->disk);
+ return NULL;
+ }
+
+ switch (d->type) {
+ case XEN_VDEV_TYPE_XVD:
+ if (d->disk < (1 << 4) && d->partition < (1 << 4)) {
+ number = (202 << 8) | (d->disk << 4) | d->partition;
+ } else if (d->disk < (1 << 20) && d->partition < (1 << 8)) {
+ number = (1 << 28) | (d ->disk << 8) | d->partition;
+ } else {
+ error_setg(errp, "cannot use xvd encoding for d%up%u", d->disk,
+ d->partition);
+ return NULL;
+ }
+ break;
+
+ case XEN_VDEV_TYPE_HD:
+ if ((d->disk == 0 || d->disk == 1) && d->partition < (1 << 4)) {
+ number = (3 << 8) | (d->disk << 6) | d->partition;
+ } else if ((d->disk == 2 || d->disk == 3) &&
+ d->partition < (1 << 4)) {
+ number = (22 << 8) | ((d->disk - 2) << 6) | d->partition;
+ } else {
+ error_setg(errp, "cannot use hd encoding for d%up%u", d->disk,
+ d->partition);
+ return NULL;
+ }
+ break;
+
+ case XEN_VDEV_TYPE_SD:
+ if (d->disk < (1 << 4) && d->partition < (1 << 4)) {
+ number = (8 << 8) | (d->disk << 4) | d->partition;
+ } else {
+ error_setg(errp, "cannot use sd encoding for d%up%u", d->disk,
+ d->partition);
+ return NULL;
+ }
+ break;
+
+ default:
+ error_setg(errp, "invalid type");
+ return NULL;
+ }
+
+ return g_strdup_printf("%u", number);
+}
+
static void xen_qdisk_realize(XenBackend *dev, Error **errp)
{
XenQdiskBackend *d = XEN_QDISK_BACKEND(dev);
blockdev_mark_auto_del(d->blk);
}
+static void xen_vdev_get_type(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ int *ptr = qdev_get_prop_ptr(dev, prop);
+
+ visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
+}
+
+static void xen_vdev_set_type(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ int *ptr = qdev_get_prop_ptr(dev, prop);
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
+}
+
+static void xen_vdev_set_default_value_enum(Object *obj,
+ const Property *prop)
+{
+ object_property_set_str(obj,
+ qapi_enum_lookup(prop->info->enum_table,
+ prop->defval.i),
+ prop->name, &error_abort);
+}
+
+static QEnumLookup xen_vdev_type_lookup = {
+ .array = (const char *const[]) {
+ "xvd",
+ "hd",
+ "sd",
+ },
+ .size = XEN_VDEV_TYPE__MAX,
+};
+
+const PropertyInfo xen_qdisk_prop_type = {
+ .name = "str",
+ .description = "xvd/hd/sd",
+ .enum_table = &xen_vdev_type_lookup,
+ .get = xen_vdev_get_type,
+ .set = xen_vdev_set_type,
+ .set_default_value = xen_vdev_set_default_value_enum,
+};
+
static Property xen_qdisk_props[] = {
+ DEFINE_PROP_SIGNED("vdev-type", XenQdiskBackend, type, 0,
+ xen_qdisk_prop_type, XenVdevType),
+ DEFINE_PROP_INT32("disk", XenQdiskBackend,
+ disk, -1),
+ DEFINE_PROP_UINT32("partition", XenQdiskBackend,
+ partition, 0),
DEFINE_BLOCK_PROPERTIES(XenQdiskBackend, conf),
DEFINE_PROP_BOOL("discard-enable", XenQdiskBackend, discard_enable,
false),
XenBackendClass *k = XEN_BACKEND_CLASS(klass);
k->device = "bar";
+ k->get_name = xen_qdisk_get_name;
k->realize = xen_qdisk_realize;
k->initialize = xen_qdisk_initialize;
k->disconnect = xen_qdisk_disconnect;
path = g_strdup_printf("%s/%s", node, key);
value = xs_read(xsh, XBT_NULL, path, NULL);
- rc = value ? vsscanf(value, fmt, ap) : -1;
+ rc = value ? vsscanf(value, fmt, ap) : EOF;
free(value);
g_free(path);
const char *type = object_get_typename(OBJECT(d));
Error *local_err = NULL;
- trace_xen_backend_realize(type, d->name);
-
if (d->frontend_id == DOMID_INVALID)
d->frontend_id = xen_domid;
return;
}
+ if (!dc->get_name)
+ {
+ error_setg(errp, "get_name method not implemented");
+ return;
+ }
+
+ d->name = dc->get_name(d, &local_err);
if (!d->name) {
- error_setg(errp, "invalid name");
+ error_propagate(errp, local_err);
+ error_prepend(errp, "failed to get backend name: ");
return;
}
+ trace_xen_backend_realize(type, d->name);
+
d->xsh = xs_open(0);
if (!d->xsh) {
error_setg(errp, "failed to open xenstore");
g_free(d->backend_path);
xs_close(d->xsh);
+
+ g_free(d->name);
}
static Property xen_backend_props[] = {
DEFINE_PROP_UINT16("frontend-id", XenBackend, frontend_id,
DOMID_INVALID),
- DEFINE_PROP_STRING("name", XenBackend, name),
DEFINE_PROP_END_OF_LIST()
};