qom: use object_resolve_path_type for links
authorPaolo Bonzini <pbonzini@redhat.com>
Thu, 2 Feb 2012 11:37:53 +0000 (12:37 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 7 Feb 2012 12:52:41 +0000 (13:52 +0100)
This allows to restrict partial matches to objects of the expected
type.  It will let people use bare names to reference drives
even though their name might be the same as a device's (e.g.
-drive id=hd0,if=none,... -device ...,drive=hd0,id=hd0).

As a useful byproduct, this fixes a problem with links of interface
type.  When a link property's type is an interface, the code expects
the implementation object (not the parent object) to be stored in the
variable.  The parent object does not contain the right vtable.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
qerror.c
qerror.h
qom/object.c

index 3d179c87ea83ad78a17d115e012507d85eb528f4..8e6efafe00d488313a1b377bf8784c8a935f1ec6 100644 (file)
--- a/qerror.c
+++ b/qerror.c
@@ -47,6 +47,10 @@ static const QErrorStringTable qerror_table[] = {
         .error_fmt = QERR_ADD_CLIENT_FAILED,
         .desc      = "Could not add client",
     },
+    {
+        .error_fmt = QERR_AMBIGUOUS_PATH,
+        .desc      = "Path '%(path)' does not uniquely identify a %(object)"
+    },
     {
         .error_fmt = QERR_BAD_BUS_FOR_DEVICE,
         .desc      = "Device '%(device)' can't go on a %(bad_bus_type) bus",
index 8c36ddb7e100c44d11ce43fd4adf98f44ad21f1a..e8718bfbabd06bcfd46b8c84f12b681e13abe942 100644 (file)
--- a/qerror.h
+++ b/qerror.h
@@ -54,6 +54,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_ADD_CLIENT_FAILED \
     "{ 'class': 'AddClientFailed', 'data': {} }"
 
+#define QERR_AMBIGUOUS_PATH \
+    "{ 'class': 'AmbiguousPath', 'data': { 'path': %s } }"
+
 #define QERR_BAD_BUS_FOR_DEVICE \
     "{ 'class': 'BadBusForDevice', 'data': { 'device': %s, 'bad_bus_type': %s } }"
 
index ea0efc662ac5d92d6bfbe185c29e79c67ef23dc3..2bd15b81b2c61dea64e39cd979b8403151b428c9 100644 (file)
@@ -840,6 +840,7 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
     bool ambiguous = false;
     const char *type;
     char *path;
+    gchar *target_type;
 
     type = object_property_get_type(obj, name, NULL);
 
@@ -847,28 +848,30 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
 
     if (*child) {
         object_unref(*child);
+        *child = NULL;
     }
 
     if (strcmp(path, "") != 0) {
         Object *target;
 
-        target = object_resolve_path(path, &ambiguous);
-        if (target) {
-            /* Go from link<FOO> to FOO.  */
-            gchar *target_type = g_strndup(&type[5], strlen(type) - 6);
-            if (object_dynamic_cast(target, target_type)) {
-                object_ref(target);
-                *child = target;
-            } else {
-                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
-            }
+        /* Go from link<FOO> to FOO.  */
+        target_type = g_strndup(&type[5], strlen(type) - 6);
+        target = object_resolve_path_type(path, target_type, &ambiguous);
 
-            g_free(target_type);
+        if (ambiguous) {
+            error_set(errp, QERR_AMBIGUOUS_PATH, path);
+        } else if (target) {
+            object_ref(target);
+            *child = target;
         } else {
-            error_set(errp, QERR_DEVICE_NOT_FOUND, path);
+            target = object_resolve_path(path, &ambiguous);
+            if (target || ambiguous) {
+                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
+            } else {
+                error_set(errp, QERR_DEVICE_NOT_FOUND, path);
+            }
         }
-    } else {
-        *child = NULL;
+        g_free(target_type);
     }
 
     g_free(path);