Commit bb5fc20f7c1c65e95030da3629dd0d7a0cce38cd

Authored by aliguori
1 parent 9dd442b1

monitor: Rework modal password input (Jan Kiszka)

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>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6710 c046a42c-6fe2-441c-8c8c-71466251a162
@@ -430,11 +430,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, @@ -430,11 +430,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
430 } 430 }
431 } 431 }
432 432
433 - /* call the change callback */  
434 - bs->media_changed = 1;  
435 - if (bs->change_cb)  
436 - bs->change_cb(bs->change_opaque);  
437 - 433 + if (!bdrv_key_required(bs)) {
  434 + /* call the change callback */
  435 + bs->media_changed = 1;
  436 + if (bs->change_cb)
  437 + bs->change_cb(bs->change_opaque);
  438 + }
438 return 0; 439 return 0;
439 } 440 }
440 441
@@ -989,7 +990,15 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) @@ -989,7 +990,15 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
989 if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key) 990 if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
990 return -1; 991 return -1;
991 ret = bs->drv->bdrv_set_key(bs, key); 992 ret = bs->drv->bdrv_set_key(bs, key);
992 - bs->valid_key = (ret == 0); 993 + if (ret < 0) {
  994 + bs->valid_key = 0;
  995 + } else if (!bs->valid_key) {
  996 + bs->valid_key = 1;
  997 + /* call the change callback now, we skipped it on open */
  998 + bs->media_changed = 1;
  999 + if (bs->change_cb)
  1000 + bs->change_cb(bs->change_opaque);
  1001 + }
993 return ret; 1002 return ret;
994 } 1003 }
995 1004
console.h
@@ -304,7 +304,11 @@ void term_flush(void); @@ -304,7 +304,11 @@ void term_flush(void);
304 void term_print_help(void); 304 void term_print_help(void);
305 void monitor_suspend(void); 305 void monitor_suspend(void);
306 void monitor_resume(void); 306 void monitor_resume(void);
307 -int monitor_read_bdrv_key(BlockDriverState *bs); 307 +
  308 +#include "block.h"
  309 +void monitor_read_bdrv_key_start(BlockDriverState *bs,
  310 + BlockDriverCompletionFunc *completion_cb,
  311 + void *opaque);
308 312
309 /* readline.c */ 313 /* readline.c */
310 typedef void ReadLineFunc(void *opaque, const char *str); 314 typedef void ReadLineFunc(void *opaque, const char *str);
hw/usb-msd.c
@@ -514,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) @@ -514,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
514 qemu_free(s); 514 qemu_free(s);
515 } 515 }
516 516
517 -USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) 517 +USBDevice *usb_msd_init(const char *filename)
518 { 518 {
519 MSDState *s; 519 MSDState *s;
520 BlockDriverState *bdrv; 520 BlockDriverState *bdrv;
@@ -554,7 +554,6 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) @@ -554,7 +554,6 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
554 if (bdrv_open2(bdrv, filename, 0, drv) < 0) 554 if (bdrv_open2(bdrv, filename, 0, drv) < 0)
555 goto fail; 555 goto fail;
556 s->bs = bdrv; 556 s->bs = bdrv;
557 - *pbs = bdrv;  
558 557
559 s->dev.speed = USB_SPEED_FULL; 558 s->dev.speed = USB_SPEED_FULL;
560 s->dev.handle_packet = usb_generic_handle_packet; 559 s->dev.handle_packet = usb_generic_handle_packet;
@@ -574,3 +573,10 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) @@ -574,3 +573,10 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
574 qemu_free(s); 573 qemu_free(s);
575 return NULL; 574 return NULL;
576 } 575 }
  576 +
  577 +BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
  578 +{
  579 + MSDState *s = (MSDState *)dev;
  580 +
  581 + return s->bs;
  582 +}
hw/usb.h
@@ -253,7 +253,8 @@ USBDevice *usb_keyboard_init(void); @@ -253,7 +253,8 @@ USBDevice *usb_keyboard_init(void);
253 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *)); 253 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
254 254
255 /* usb-msd.c */ 255 /* usb-msd.c */
256 -USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs); 256 +USBDevice *usb_msd_init(const char *filename);
  257 +BlockDriverState *usb_msd_get_bdrv(USBDevice *dev);
257 258
258 /* usb-net.c */ 259 /* usb-net.c */
259 USBDevice *usb_net_init(NICInfo *nd); 260 USBDevice *usb_net_init(NICInfo *nd);
monitor.c
@@ -74,13 +74,18 @@ static const term_cmd_t info_cmds[]; @@ -74,13 +74,18 @@ static const term_cmd_t info_cmds[];
74 74
75 static uint8_t term_outbuf[1024]; 75 static uint8_t term_outbuf[1024];
76 static int term_outbuf_index; 76 static int term_outbuf_index;
  77 +static BlockDriverCompletionFunc *password_completion_cb;
  78 +static void *password_opaque;
77 79
78 static void monitor_start_input(void); 80 static void monitor_start_input(void);
79 -static void monitor_readline(const char *prompt, int is_password,  
80 - char *buf, int buf_size);  
81 81
82 static CPUState *mon_cpu = NULL; 82 static CPUState *mon_cpu = NULL;
83 83
  84 +static void monitor_read_password(ReadLineFunc *readline_func, void *opaque)
  85 +{
  86 + readline_start("Password: ", 1, readline_func, opaque);
  87 +}
  88 +
84 void term_flush(void) 89 void term_flush(void)
85 { 90 {
86 int i; 91 int i;
@@ -435,21 +440,29 @@ static void do_change_block(const char *device, const char *filename, const char @@ -435,21 +440,29 @@ static void do_change_block(const char *device, const char *filename, const char
435 if (eject_device(bs, 0) < 0) 440 if (eject_device(bs, 0) < 0)
436 return; 441 return;
437 bdrv_open2(bs, filename, 0, drv); 442 bdrv_open2(bs, filename, 0, drv);
438 - monitor_read_bdrv_key(bs); 443 + monitor_read_bdrv_key_start(bs, NULL, NULL);
  444 +}
  445 +
  446 +static void change_vnc_password_cb(void *opaque, const char *password)
  447 +{
  448 + if (vnc_display_password(NULL, password) < 0)
  449 + term_printf("could not set VNC server password\n");
  450 +
  451 + monitor_start_input();
439 } 452 }
440 453
441 static void do_change_vnc(const char *target, const char *arg) 454 static void do_change_vnc(const char *target, const char *arg)
442 { 455 {
443 if (strcmp(target, "passwd") == 0 || 456 if (strcmp(target, "passwd") == 0 ||
444 strcmp(target, "password") == 0) { 457 strcmp(target, "password") == 0) {
445 - char password[9];  
446 if (arg) { 458 if (arg) {
  459 + char password[9];
447 strncpy(password, arg, sizeof(password)); 460 strncpy(password, arg, sizeof(password));
448 password[sizeof(password) - 1] = '\0'; 461 password[sizeof(password) - 1] = '\0';
449 - } else  
450 - monitor_readline("Password: ", 1, password, sizeof(password));  
451 - if (vnc_display_password(NULL, password) < 0)  
452 - term_printf("could not set VNC server password\n"); 462 + change_vnc_password_cb(NULL, password);
  463 + } else {
  464 + monitor_read_password(change_vnc_password_cb, NULL);
  465 + }
453 } else { 466 } else {
454 if (vnc_display_open(NULL, target) < 0) 467 if (vnc_display_open(NULL, target) < 0)
455 term_printf("could not start VNC server on %s\n", target); 468 term_printf("could not start VNC server on %s\n", target);
@@ -496,15 +509,7 @@ static void do_stop(void) @@ -496,15 +509,7 @@ static void do_stop(void)
496 vm_stop(EXCP_INTERRUPT); 509 vm_stop(EXCP_INTERRUPT);
497 } 510 }
498 511
499 -static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)  
500 -{  
501 - int *err = opaque;  
502 -  
503 - if (bdrv_key_required(bs))  
504 - *err = monitor_read_bdrv_key(bs);  
505 - else  
506 - *err = 0;  
507 -} 512 +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
508 513
509 static void do_cont(void) 514 static void do_cont(void)
510 { 515 {
@@ -516,6 +521,23 @@ static void do_cont(void) @@ -516,6 +521,23 @@ static void do_cont(void)
516 vm_start(); 521 vm_start();
517 } 522 }
518 523
  524 +static void bdrv_key_cb(void *opaque, int err)
  525 +{
  526 + /* another key was set successfully, retry to continue */
  527 + if (!err)
  528 + do_cont();
  529 +}
  530 +
  531 +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
  532 +{
  533 + int *err = opaque;
  534 +
  535 + if (!*err && bdrv_key_required(bs)) {
  536 + *err = -EBUSY;
  537 + monitor_read_bdrv_key_start(bs, bdrv_key_cb, NULL);
  538 + }
  539 +}
  540 +
519 #ifdef CONFIG_GDBSTUB 541 #ifdef CONFIG_GDBSTUB
520 static void do_gdbserver(const char *port) 542 static void do_gdbserver(const char *port)
521 { 543 {
@@ -2835,7 +2857,7 @@ static void monitor_handle_command1(void *opaque, const char *cmdline) @@ -2835,7 +2857,7 @@ static void monitor_handle_command1(void *opaque, const char *cmdline)
2835 { 2857 {
2836 monitor_handle_command(cmdline); 2858 monitor_handle_command(cmdline);
2837 if (!monitor_suspended) 2859 if (!monitor_suspended)
2838 - monitor_start_input(); 2860 + readline_show_prompt();
2839 else 2861 else
2840 monitor_suspended = 2; 2862 monitor_suspended = 2;
2841 } 2863 }
@@ -2898,46 +2920,36 @@ void monitor_init(CharDriverState *hd, int show_banner) @@ -2898,46 +2920,36 @@ void monitor_init(CharDriverState *hd, int show_banner)
2898 readline_start("", 0, monitor_handle_command1, NULL); 2920 readline_start("", 0, monitor_handle_command1, NULL);
2899 } 2921 }
2900 2922
2901 -/* XXX: use threads ? */  
2902 -/* modal monitor readline */  
2903 -static int monitor_readline_started;  
2904 -static char *monitor_readline_buf;  
2905 -static int monitor_readline_buf_size;  
2906 -  
2907 -static void monitor_readline_cb(void *opaque, const char *input) 2923 +static void bdrv_password_cb(void *opaque, const char *password)
2908 { 2924 {
2909 - pstrcpy(monitor_readline_buf, monitor_readline_buf_size, input);  
2910 - monitor_readline_started = 0;  
2911 -} 2925 + BlockDriverState *bs = opaque;
  2926 + int ret = 0;
2912 2927
2913 -static void monitor_readline(const char *prompt, int is_password,  
2914 - char *buf, int buf_size)  
2915 -{  
2916 - readline_start(prompt, is_password, monitor_readline_cb, NULL);  
2917 - readline_show_prompt();  
2918 - monitor_readline_buf = buf;  
2919 - monitor_readline_buf_size = buf_size;  
2920 - monitor_readline_started = 1;  
2921 - while (monitor_readline_started) {  
2922 - main_loop_wait(10); 2928 + if (bdrv_set_key(bs, password) != 0) {
  2929 + term_printf("invalid password\n");
  2930 + ret = -EPERM;
2923 } 2931 }
  2932 + if (password_completion_cb)
  2933 + password_completion_cb(password_opaque, ret);
  2934 +
  2935 + monitor_start_input();
2924 } 2936 }
2925 2937
2926 -int monitor_read_bdrv_key(BlockDriverState *bs) 2938 +void monitor_read_bdrv_key_start(BlockDriverState *bs,
  2939 + BlockDriverCompletionFunc *completion_cb,
  2940 + void *opaque)
2927 { 2941 {
2928 - char password[256];  
2929 - int i;  
2930 -  
2931 - if (!bdrv_is_encrypted(bs))  
2932 - return 0; 2942 + if (!bdrv_key_required(bs)) {
  2943 + if (completion_cb)
  2944 + completion_cb(opaque, 0);
  2945 + return;
  2946 + }
2933 2947
2934 term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs), 2948 term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
2935 bdrv_get_encrypted_filename(bs)); 2949 bdrv_get_encrypted_filename(bs));
2936 - for(i = 0; i < 3; i++) {  
2937 - monitor_readline("Password: ", 1, password, sizeof(password));  
2938 - if (bdrv_set_key(bs, password) == 0)  
2939 - return 0;  
2940 - term_printf("invalid password\n");  
2941 - }  
2942 - return -EPERM; 2950 +
  2951 + password_completion_cb = completion_cb;
  2952 + password_opaque = opaque;
  2953 +
  2954 + monitor_read_password(bdrv_password_cb, bs);
2943 } 2955 }
@@ -2661,6 +2661,16 @@ int usb_device_add_dev(USBDevice *dev) @@ -2661,6 +2661,16 @@ int usb_device_add_dev(USBDevice *dev)
2661 return 0; 2661 return 0;
2662 } 2662 }
2663 2663
  2664 +static void usb_msd_password_cb(void *opaque, int err)
  2665 +{
  2666 + USBDevice *dev = opaque;
  2667 +
  2668 + if (!err)
  2669 + usb_device_add_dev(dev);
  2670 + else
  2671 + dev->handle_destroy(dev);
  2672 +}
  2673 +
2664 static int usb_device_add(const char *devname, int is_hotplug) 2674 static int usb_device_add(const char *devname, int is_hotplug)
2665 { 2675 {
2666 const char *p; 2676 const char *p;
@@ -2680,14 +2690,15 @@ static int usb_device_add(const char *devname, int is_hotplug) @@ -2680,14 +2690,15 @@ static int usb_device_add(const char *devname, int is_hotplug)
2680 } else if (strstart(devname, "disk:", &p)) { 2690 } else if (strstart(devname, "disk:", &p)) {
2681 BlockDriverState *bs; 2691 BlockDriverState *bs;
2682 2692
2683 - dev = usb_msd_init(p, &bs); 2693 + dev = usb_msd_init(p);
2684 if (!dev) 2694 if (!dev)
2685 return -1; 2695 return -1;
  2696 + bs = usb_msd_get_bdrv(dev);
2686 if (bdrv_key_required(bs)) { 2697 if (bdrv_key_required(bs)) {
2687 autostart = 0; 2698 autostart = 0;
2688 - if (is_hotplug && monitor_read_bdrv_key(bs) < 0) {  
2689 - dev->handle_destroy(dev);  
2690 - return -1; 2699 + if (is_hotplug) {
  2700 + monitor_read_bdrv_key_start(bs, usb_msd_password_cb, dev);
  2701 + return 0;
2691 } 2702 }
2692 } 2703 }
2693 } else if (!strcmp(devname, "wacom-tablet")) { 2704 } else if (!strcmp(devname, "wacom-tablet")) {