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

Submitted by Amit Shah on March 21, 2011, 1:09 p.m.

Details

Message ID 2d6c1ef40f3678ab47a4d14fb5dadaa486bfcda6.1300712809.git.amit.shah@redhat.com
State New
Headers show

Commit Message

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(-)

Comments

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 hide | download patch | download mbox

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;
 };