diff mbox

[v2,2/8] virtio: enhance virtio_error messages

Message ID 20170713110237.6712-3-lprosek@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ladi Prosek July 13, 2017, 11:02 a.m. UTC
Output like "Virtqueue size exceeded" is not much useful in identifying the
culprit. This commit adds virtio device name (e.g. "virtio-input") and id
if set (e.g. "mouse0") to all virtio error messages to improve debuggability.

Some virtio devices (virtio-scsi, virtio-serial) insert a bus between the
proxy object and the virtio backends, so a helper function is added to walk
the object hierarchy and find the right proxy object to extract the id from.

Signed-off-by: Ladi Prosek <lprosek@redhat.com>
---
 hw/virtio/virtio.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

Comments

Stefan Hajnoczi July 13, 2017, 1:40 p.m. UTC | #1
On Thu, Jul 13, 2017 at 01:02:31PM +0200, Ladi Prosek wrote:
> +static const char *virtio_get_device_id(VirtIODevice *vdev)
> +{
> +    DeviceState *qdev = DEVICE(vdev);
> +    while (qdev) {
> +        /* Find the proxy object corresponding to the vdev backend */
> +        Object *prop = object_property_get_link(OBJECT(qdev),
> +                                                VIRTIO_PROP_BACKEND, NULL);
> +        if (prop == OBJECT(vdev)) {
> +            return qdev->id;
> +        }
> +        qdev = qdev->parent_bus->parent;
> +    }
> +    return NULL;
> +}
> +
>  void GCC_FMT_ATTR(2, 3) virtio_error(VirtIODevice *vdev, const char *fmt, ...)
>  {
>      va_list ap;
>  
> +    error_report_nolf("%s (id=%s): ", vdev->name, virtio_get_device_id(vdev));

virtio_get_device_id() can return NULL.  POSIX does not guarantee that
the printf(3) family functions handle "%s", NULL safely.  glibc prints
"(null)" but other libc implementations crash (e.g. Solaris).

http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html

Should the return NULL above have g_assert_not_reached()?  That would
communicate the assumption that we never reach return NULL and it might
silence static checkers like Coverity but I'm not sure.
Ladi Prosek July 13, 2017, 1:58 p.m. UTC | #2
On Thu, Jul 13, 2017 at 3:40 PM, Stefan Hajnoczi <stefanha@redhat.com> wrote:
> On Thu, Jul 13, 2017 at 01:02:31PM +0200, Ladi Prosek wrote:
>> +static const char *virtio_get_device_id(VirtIODevice *vdev)
>> +{
>> +    DeviceState *qdev = DEVICE(vdev);
>> +    while (qdev) {
>> +        /* Find the proxy object corresponding to the vdev backend */
>> +        Object *prop = object_property_get_link(OBJECT(qdev),
>> +                                                VIRTIO_PROP_BACKEND, NULL);
>> +        if (prop == OBJECT(vdev)) {
>> +            return qdev->id;
>> +        }
>> +        qdev = qdev->parent_bus->parent;
>> +    }
>> +    return NULL;
>> +}
>> +
>>  void GCC_FMT_ATTR(2, 3) virtio_error(VirtIODevice *vdev, const char *fmt, ...)
>>  {
>>      va_list ap;
>>
>> +    error_report_nolf("%s (id=%s): ", vdev->name, virtio_get_device_id(vdev));
>
> virtio_get_device_id() can return NULL.  POSIX does not guarantee that
> the printf(3) family functions handle "%s", NULL safely.  glibc prints
> "(null)" but other libc implementations crash (e.g. Solaris).
>
> http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
>
> Should the return NULL above have g_assert_not_reached()?  That would
> communicate the assumption that we never reach return NULL and it might
> silence static checkers like Coverity but I'm not sure.

virtio_get_device_id is expected to return NULL if the device has no
id assigned and I kind of liked the "(null)" output. I just failed to
realize that not all printf's will handle it. I'll definitely fix
this, thanks!
diff mbox

Patch

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 0e76a73..a98f681 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -31,6 +31,11 @@ 
  */
 #define VIRTIO_PCI_VRING_ALIGN         4096
 
+/*
+ * Name of the property linking proxy objects to virtio backend objects.
+ */
+#define VIRTIO_PROP_BACKEND            "virtio-backend"
+
 typedef struct VRingDesc
 {
     uint64_t addr;
@@ -2223,7 +2228,8 @@  void virtio_instance_init_common(Object *proxy_obj, void *data,
     DeviceState *vdev = data;
 
     object_initialize(vdev, vdev_size, vdev_name);
-    object_property_add_child(proxy_obj, "virtio-backend", OBJECT(vdev), NULL);
+    object_property_add_child(proxy_obj, VIRTIO_PROP_BACKEND, OBJECT(vdev),
+                              NULL);
     object_unref(OBJECT(vdev));
     qdev_alias_all_properties(vdev, proxy_obj);
 }
@@ -2443,12 +2449,29 @@  void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name)
     vdev->bus_name = g_strdup(bus_name);
 }
 
+static const char *virtio_get_device_id(VirtIODevice *vdev)
+{
+    DeviceState *qdev = DEVICE(vdev);
+    while (qdev) {
+        /* Find the proxy object corresponding to the vdev backend */
+        Object *prop = object_property_get_link(OBJECT(qdev),
+                                                VIRTIO_PROP_BACKEND, NULL);
+        if (prop == OBJECT(vdev)) {
+            return qdev->id;
+        }
+        qdev = qdev->parent_bus->parent;
+    }
+    return NULL;
+}
+
 void GCC_FMT_ATTR(2, 3) virtio_error(VirtIODevice *vdev, const char *fmt, ...)
 {
     va_list ap;
 
+    error_report_nolf("%s (id=%s): ", vdev->name, virtio_get_device_id(vdev));
+
     va_start(ap, fmt);
-    error_vreport_nolf(fmt, ap);
+    error_vprintf(fmt, ap);
     va_end(ap);
     error_printf("\n");