Patchwork [7/7] char: Prevent multiple devices opening same chardev

login
register
mail settings
Submitter Amit Shah
Date March 21, 2011, 1:09 p.m.
Message ID <2d6c1ef40f3678ab47a4d14fb5dadaa486bfcda6.1300712809.git.amit.shah@redhat.com>
Download mbox | patch
Permalink /patch/87775/
State New
Headers show

Comments

Amit Shah - March 21, 2011, 1:09 p.m.
Prevent:

-chardev socket,path=/tmp/foo,server,nowait,id=c0 \
-device virtserialport,chardev=c0,id=vs0 \
-device virtserialport,chardev=c0,id=vs1

Reported-by: Mike Cao <bcao@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
---
 hw/qdev-properties.c |    7 ++++++-
 qemu-char.c          |    4 ++++
 qemu-char.h          |    1 +
 3 files changed, 11 insertions(+), 1 deletions(-)
Juan Quintela - March 23, 2011, 1:32 p.m.
Amit Shah <amit.shah@redhat.com> wrote:
> Prevent:
>
> -chardev socket,path=/tmp/foo,server,nowait,id=c0 \
> -device virtserialport,chardev=c0,id=vs0 \
> -device virtserialport,chardev=c0,id=vs1
>
> Reported-by: Mike Cao <bcao@redhat.com>
> Signed-off-by: Amit Shah <amit.shah@redhat.com>

> @@ -197,6 +197,10 @@ void qemu_chr_add_handlers(CharDriverState *s,
>                             IOEventHandler *fd_event,
>                             void *opaque)
>  {
> +    if (!opaque) {
> +        /* chr driver being released. */
> +        s->assigned = 0;
> +    }
>      s->chr_can_read = fd_can_read;
>      s->chr_read = fd_read;
>      s->chr_event = fd_event;

I preffer to decide that a handler is empty when fd_can_read/fd_read and
fd_event are all NULL, and don't take into account the opaque handler.

This covers the case where opaque is NULL because state is implicit on
the other functions.

Later, Juan.

Patch

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index a45b61e..1088a26 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -351,8 +351,13 @@  static int parse_chr(DeviceState *dev, Property *prop, const char *str)
     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
 
     *ptr = qemu_chr_find(str);
-    if (*ptr == NULL)
+    if (*ptr == NULL) {
         return -ENOENT;
+    }
+    if ((*ptr)->assigned) {
+        return -EEXIST;
+    }
+    (*ptr)->assigned = 1;
     return 0;
 }
 
diff --git a/qemu-char.c b/qemu-char.c
index cad35d7..c4557c3 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -197,6 +197,10 @@  void qemu_chr_add_handlers(CharDriverState *s,
                            IOEventHandler *fd_event,
                            void *opaque)
 {
+    if (!opaque) {
+        /* chr driver being released. */
+        s->assigned = 0;
+    }
     s->chr_can_read = fd_can_read;
     s->chr_read = fd_read;
     s->chr_event = fd_event;
diff --git a/qemu-char.h b/qemu-char.h
index 56d9954..fb96eef 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -70,6 +70,7 @@  struct CharDriverState {
     char *label;
     char *filename;
     int opened;
+    int assigned; /* chardev assigned to a device */
     QTAILQ_ENTRY(CharDriverState) next;
 };