qdev: remove baked in notion of aliases (v2)
Limit them to the device_add functionality. Device aliases were a hack based
on the fact that virtio was modeled the wrong way. The mechanism for aliasing
is very limited in that only one alias can exist for any device.
We have to support it for the purposes of compatibility but we only need to
support it in device_add so restrict it to that piece of code.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
v1 -> v2
- Use a table for aliases (Paolo)
diff --git a/hw/qdev.c b/hw/qdev.c
index 4f6c3a7..5830bef 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -61,14 +61,56 @@
return dc->props;
}
+/*
+ * Aliases were a bad idea from the start. Let's keep them
+ * from spreading further.
+ */
+typedef struct QDevAlias
+{
+ const char *typename;
+ const char *alias;
+} QDevAlias;
+
+static const QDevAlias qdev_alias_table[] = {
+ { "virtio-blk-pci", "virtio-blk" },
+ { "virtio-net-pci", "virtio-net" },
+ { "virtio-serial-pci", "virtio-serial" },
+ { "virtio-balloon-pci", "virtio-balloon" },
+ { "virtio-blk-s390", "virtio-blk" },
+ { "virtio-net-s390", "virtio-net" },
+ { "virtio-serial-s390", "virtio-serial" },
+ { "lsi53c895a", "lsi" },
+ { "ich9-ahci", "ahci" },
+ { }
+};
+
+static const char *qdev_class_get_alias(DeviceClass *dc)
+{
+ const char *typename = object_class_get_name(OBJECT_CLASS(dc));
+ int i;
+
+ for (i = 0; qdev_alias_table[i].typename; i++) {
+ if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
+ return qdev_alias_table[i].alias;
+ }
+ }
+
+ return NULL;
+}
+
+static bool qdev_class_has_alias(DeviceClass *dc)
+{
+ return (qdev_class_get_alias(dc) != NULL);
+}
+
const char *qdev_fw_name(DeviceState *dev)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
if (dc->fw_name) {
return dc->fw_name;
- } else if (dc->alias) {
- return dc->alias;
+ } else if (qdev_class_has_alias(dc)) {
+ return qdev_class_get_alias(dc);
}
return object_get_typename(OBJECT(dev));
@@ -161,8 +203,8 @@
if (dc->bus_info) {
error_printf(", bus %s", dc->bus_info->name);
}
- if (dc->alias) {
- error_printf(", alias \"%s\"", dc->alias);
+ if (qdev_class_has_alias(dc)) {
+ error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
}
if (dc->desc) {
error_printf(", desc \"%s\"", dc->desc);
@@ -188,6 +230,19 @@
return 0;
}
+static const char *find_typename_by_alias(const char *alias)
+{
+ int i;
+
+ for (i = 0; qdev_alias_table[i].alias; i++) {
+ if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
+ return qdev_alias_table[i].typename;
+ }
+ }
+
+ return NULL;
+}
+
int qdev_device_help(QemuOpts *opts)
{
const char *driver;
@@ -208,6 +263,15 @@
klass = object_class_by_name(driver);
if (!klass) {
+ const char *typename = find_typename_by_alias(driver);
+
+ if (typename) {
+ driver = typename;
+ klass = object_class_by_name(driver);
+ }
+ }
+
+ if (!klass) {
return 0;
}
info = DEVICE_CLASS(klass);
@@ -263,6 +327,7 @@
DeviceState *qdev_device_add(QemuOpts *opts)
{
+ ObjectClass *obj;
DeviceClass *k;
const char *driver, *path, *id;
DeviceState *qdev;
@@ -275,7 +340,22 @@
}
/* find driver */
- k = DEVICE_CLASS(object_class_by_name(driver));
+ obj = object_class_by_name(driver);
+ if (!obj) {
+ const char *typename = find_typename_by_alias(driver);
+
+ if (typename) {
+ driver = typename;
+ obj = object_class_by_name(driver);
+ }
+ }
+
+ if (!obj) {
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
+ return NULL;
+ }
+
+ k = DEVICE_CLASS(obj);
/* find bus */
path = qemu_opt_get(opts, "bus");
@@ -753,7 +833,8 @@
QTAILQ_FOREACH(dev, &bus->children, sibling) {
DeviceClass *dc = DEVICE_GET_CLASS(dev);
- if (dc->alias && strcmp(dc->alias, elem) == 0) {
+ if (qdev_class_has_alias(dc) &&
+ strcmp(qdev_class_get_alias(dc), elem) == 0) {
return dev;
}
}