qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@siemens.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 12/17] monitor: Rework modal password input
Date: Sat, 07 Feb 2009 19:16:29 +0100	[thread overview]
Message-ID: <20090207181629.13667.13504.stgit@mchn012c.ww002.siemens.net> (raw)
In-Reply-To: <20090207181627.13667.9979.stgit@mchn012c.ww002.siemens.net>

Currently, waiting for the user to type in some password blocks the
whole VM because monitor_readline starts its own I/O loop. And this loop
also screws up reading passwords from virtual console.

Patch below fixes the shortcomings by using normal I/O processing also
for waiting on a password. To keep to modal property for the monitor
terminal, the command handler is temporarily replaced by a password
handler and a callback infrastructure is established to process the
result before switching back to command mode.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 block.c      |   21 ++++++++---
 hw/usb-msd.c |   10 ++++-
 hw/usb.h     |    3 +-
 monitor.c    |  111 ++++++++++++++++++++++++++++++++--------------------------
 monitor.h    |    4 ++
 vl.c         |   19 ++++++++--
 6 files changed, 105 insertions(+), 63 deletions(-)

diff --git a/block.c b/block.c
index 3481988..5a455e3 100644
--- a/block.c
+++ b/block.c
@@ -429,11 +429,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
         }
     }
 
-    /* call the change callback */
-    bs->media_changed = 1;
-    if (bs->change_cb)
-        bs->change_cb(bs->change_opaque);
-
+    if (!bdrv_key_required(bs)) {
+        /* call the change callback */
+        bs->media_changed = 1;
+        if (bs->change_cb)
+            bs->change_cb(bs->change_opaque);
+    }
     return 0;
 }
 
@@ -944,7 +945,15 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
         return -1;
     ret = bs->drv->bdrv_set_key(bs, key);
-    bs->valid_key = (ret == 0);
+    if (ret < 0) {
+        bs->valid_key = 0;
+    } else if (!bs->valid_key) {
+        bs->valid_key = 1;
+        /* call the change callback now, we skipped it on open */
+        bs->media_changed = 1;
+        if (bs->change_cb)
+            bs->change_cb(bs->change_opaque);
+    }
     return ret;
 }
 
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 2b0338d..1594bb0 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -514,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
     qemu_free(s);
 }
 
-USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
+USBDevice *usb_msd_init(const char *filename)
 {
     MSDState *s;
     BlockDriverState *bdrv;
@@ -554,7 +554,6 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
     if (bdrv_open2(bdrv, filename, 0, drv) < 0)
         goto fail;
     s->bs = bdrv;
-    *pbs = bdrv;
 
     s->dev.speed = USB_SPEED_FULL;
     s->dev.handle_packet = usb_generic_handle_packet;
@@ -574,3 +573,10 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
     qemu_free(s);
     return NULL;
 }
+
+BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
+{
+    MSDState *s = (MSDState *)dev;
+
+    return s->bs;
+}
diff --git a/hw/usb.h b/hw/usb.h
index 4cd832d..a5e0d44 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -253,7 +253,8 @@ USBDevice *usb_keyboard_init(void);
 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
 
 /* usb-msd.c */
-USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs);
+USBDevice *usb_msd_init(const char *filename);
+BlockDriverState *usb_msd_get_bdrv(USBDevice *dev);
 
 /* usb-net.c */
 USBDevice *usb_net_init(NICInfo *nd);
diff --git a/monitor.c b/monitor.c
index e187412..51e6d9f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -79,13 +79,18 @@ static const term_cmd_t info_cmds[];
 
 static uint8_t term_outbuf[1024];
 static int term_outbuf_index;
+static BlockDriverCompletionFunc *password_completion_cb;
+static void *password_opaque;
 
 static void monitor_start_input(void);
-static void monitor_readline(const char *prompt, int is_password,
-                             char *buf, int buf_size);
 
 static CPUState *mon_cpu = NULL;
 
+static void monitor_read_password(ReadLineFunc *readline_func, void *opaque)
+{
+    readline_start("Password: ", 1, readline_func, opaque);
+}
+
 void monitor_flush(void)
 {
     MonitorTerm *term;
@@ -445,21 +450,29 @@ static void do_change_block(const char *device, const char *filename, const char
     if (eject_device(bs, 0) < 0)
         return;
     bdrv_open2(bs, filename, 0, drv);
-    monitor_read_bdrv_key(bs);
+    monitor_read_bdrv_key_start(bs, NULL, NULL);
+}
+
+static void change_vnc_password_cb(void *opaque, const char *password)
+{
+    if (vnc_display_password(NULL, password) < 0)
+        monitor_printf("could not set VNC server password\n");
+
+    monitor_start_input();
 }
 
 static void do_change_vnc(const char *target, const char *arg)
 {
     if (strcmp(target, "passwd") == 0 ||
 	strcmp(target, "password") == 0) {
-	char password[9];
 	if (arg) {
+            char password[9];
 	    strncpy(password, arg, sizeof(password));
 	    password[sizeof(password) - 1] = '\0';
-	} else
-	    monitor_readline("Password: ", 1, password, sizeof(password));
-	if (vnc_display_password(NULL, password) < 0)
-	    monitor_printf("could not set VNC server password\n");
+            change_vnc_password_cb(NULL, password);
+        } else {
+            monitor_read_password(change_vnc_password_cb, NULL);
+        }
     } else {
 	if (vnc_display_open(NULL, target) < 0)
 	    monitor_printf("could not start VNC server on %s\n", target);
@@ -506,15 +519,7 @@ static void do_stop(void)
     vm_stop(EXCP_INTERRUPT);
 }
 
-static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
-{
-    int *err = opaque;
-
-    if (bdrv_key_required(bs))
-        *err = monitor_read_bdrv_key(bs);
-    else
-        *err = 0;
-}
+static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
 
 static void do_cont(void)
 {
@@ -526,6 +531,23 @@ static void do_cont(void)
         vm_start();
 }
 
+static void bdrv_key_cb(void *opaque, int err)
+{
+    /* another key was set successfully, retry to continue */
+    if (!err)
+        do_cont();
+}
+
+static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+    int *err = opaque;
+
+    if (!*err && bdrv_key_required(bs)) {
+        *err = -EBUSY;
+        monitor_read_bdrv_key_start(bs, bdrv_key_cb, NULL);
+    }
+}
+
 #ifdef CONFIG_GDBSTUB
 static void do_gdbserver(const char *port)
 {
@@ -2858,45 +2880,36 @@ void monitor_init(CharDriverState *chr)
     readline_start("", 0, monitor_handle_command1, NULL);
 }
 
-/* XXX: use threads ? */
-/* modal monitor readline */
-static int monitor_readline_started;
-static char *monitor_readline_buf;
-static int monitor_readline_buf_size;
-
-static void monitor_readline_cb(void *opaque, const char *input)
+static void bdrv_password_cb(void *opaque, const char *password)
 {
-    pstrcpy(monitor_readline_buf, monitor_readline_buf_size, input);
-    monitor_readline_started = 0;
-}
+    BlockDriverState *bs = opaque;
+    int ret = 0;
 
-static void monitor_readline(const char *prompt, int is_password,
-                             char *buf, int buf_size)
-{
-    readline_start(prompt, is_password, monitor_readline_cb, NULL);
-    monitor_readline_buf = buf;
-    monitor_readline_buf_size = buf_size;
-    monitor_readline_started = 1;
-    while (monitor_readline_started) {
-        main_loop_wait(10);
+    if (bdrv_set_key(bs, password) != 0) {
+        monitor_printf("invalid password\n");
+        ret = -EPERM;
     }
+    if (password_completion_cb)
+        password_completion_cb(password_opaque, ret);
+
+    monitor_start_input();
 }
 
-int monitor_read_bdrv_key(BlockDriverState *bs)
+void monitor_read_bdrv_key_start(BlockDriverState *bs,
+                                 BlockDriverCompletionFunc *completion_cb,
+                                 void *opaque)
 {
-    char password[256];
-    int i;
-
-    if (!bdrv_is_encrypted(bs))
-        return 0;
+    if (!bdrv_key_required(bs)) {
+        if (completion_cb)
+            completion_cb(opaque, 0);
+        return;
+    }
 
     monitor_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
                    bdrv_get_encrypted_filename(bs));
-    for(i = 0; i < 3; i++) {
-        monitor_readline("Password: ", 1, password, sizeof(password));
-        if (bdrv_set_key(bs, password) == 0)
-            return 0;
-        monitor_printf("invalid password\n");
-    }
-    return -EPERM;
+
+    password_completion_cb = completion_cb;
+    password_opaque = opaque;
+
+    monitor_read_password(bdrv_password_cb, bs);
 }
diff --git a/monitor.h b/monitor.h
index ae79a68..4b35a25 100644
--- a/monitor.h
+++ b/monitor.h
@@ -8,7 +8,9 @@ void monitor_init(CharDriverState *chr);
 void monitor_suspend(void);
 void monitor_resume(void);
 
-int monitor_read_bdrv_key(BlockDriverState *bs);
+void monitor_read_bdrv_key_start(BlockDriverState *bs,
+                                 BlockDriverCompletionFunc *completion_cb,
+                                 void *opaque);
 
 void monitor_vprintf(const char *fmt, va_list ap);
 void monitor_printf(const char *fmt, ...)
diff --git a/vl.c b/vl.c
index 4b25080..f5b6171 100644
--- a/vl.c
+++ b/vl.c
@@ -2603,6 +2603,16 @@ int usb_device_add_dev(USBDevice *dev)
     return 0;
 }
 
+static void usb_msd_password_cb(void *opaque, int err)
+{
+    USBDevice *dev = opaque;
+
+    if (!err)
+        usb_device_add_dev(dev);
+    else
+        dev->handle_destroy(dev);
+}
+
 static int usb_device_add(const char *devname, int is_hotplug)
 {
     const char *p;
@@ -2622,14 +2632,15 @@ static int usb_device_add(const char *devname, int is_hotplug)
     } else if (strstart(devname, "disk:", &p)) {
         BlockDriverState *bs;
 
-        dev = usb_msd_init(p, &bs);
+        dev = usb_msd_init(p);
         if (!dev)
             return -1;
+        bs = usb_msd_get_bdrv(dev);
         if (bdrv_key_required(bs)) {
             autostart = 0;
-            if (is_hotplug && monitor_read_bdrv_key(bs) < 0) {
-                dev->handle_destroy(dev);
-                return -1;
+            if (is_hotplug) {
+                monitor_read_bdrv_key_start(bs, usb_msd_password_cb, dev);
+                return 0;
             }
         }
     } else if (!strcmp(devname, "wacom-tablet")) {

  parent reply	other threads:[~2009-02-07 18:25 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-07 18:16 [Qemu-devel] [PATCH 00/17] monitor rework Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 01/17] block: Polish error handling of brdv_open2 Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 09/17] monitor: Simplify password input mode Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 04/17] monitor: Report encrypted disks in snapshot mode Jan Kiszka
2009-02-09 14:47   ` Anthony Liguori
2009-02-09 15:35     ` [Qemu-devel] " Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 10/17] monitor: Rework terminal management Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 06/17] char-mux: Use separate input buffers Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 05/17] monitor: Don't change VNC server when disabled Jan Kiszka
2009-02-09 14:48   ` Anthony Liguori
2009-02-09 15:35     ` [Qemu-devel] " Jan Kiszka
2009-02-09 16:01       ` Anthony Liguori
2009-02-07 18:16 ` [Qemu-devel] [PATCH 08/17] monitor: Rework initial disk password retrieval Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 07/17] monitor: Introduce monitor.h and readline.h Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 02/17] block: Improve bdrv_iterate Jan Kiszka
2009-02-09 14:45   ` Anthony Liguori
2009-02-09 15:34     ` [Qemu-devel] " Jan Kiszka
2009-02-09 15:41       ` Anthony Liguori
2009-02-07 18:16 ` [Qemu-devel] [PATCH 03/17] block: Introduce bdrv_get_encrypted_filename Jan Kiszka
2009-02-07 18:16 ` Jan Kiszka [this message]
2009-02-07 18:16 ` [Qemu-devel] [PATCH 15/17] monitor: Improve mux'ed console experience Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 11/17] monitor: Drop banner hiding Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 13/17] monitor: Introduce ReadLineState Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 17/17] monitor: Pass-through for gdbstub Jan Kiszka
2009-02-07 18:16 ` [Qemu-devel] [PATCH 14/17] monitor: Decouple terminals Jan Kiszka
2009-02-09 15:16   ` Anthony Liguori
2009-02-09 15:40     ` Anthony Liguori
2009-02-09 15:45     ` [Qemu-devel] " Jan Kiszka
2009-02-09 15:55       ` Anthony Liguori
2009-02-07 18:16 ` [Qemu-devel] [PATCH 16/17] monitor: Introduce MONITOR_USE_READLINE flag Jan Kiszka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090207181629.13667.13504.stgit@mchn012c.ww002.siemens.net \
    --to=jan.kiszka@siemens.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).