Commit 731b03642d0ac0365294c7b39713fede769a3f39

Authored by aliguori
1 parent 4c36ba32

monitor: Decouple terminals (Jan Kiszka)

Currently all registered (and activate) monitor terminals work in
broadcast mode: Everyone sees what someone else types on some other
terminal and what the monitor reports back. This model is broken when
you have a management monitor terminal that is automatically operated
and some other terminal used for independent guest inspection. Such
additional terminals can be multiplexed device channels or a gdb
frontend connected to QEMU's stub.

Therefore, this patch decouples the buffers and states of all monitor
terminals, allowing the user to operate them independently. It finally
starts to use the 'mon' parameter that was introduced earlier with the
API rework. It also defines the default monitor: the first instantance
that has the MONITOR_IS_DEFAULT flag set, and that is the monitor
created via the "-monitor" command line switch (or "vc" if none is
given).

As the patch requires to rework the monitor suspension interface, it
also takes the freedom to make it "truely" suspending (so far suspending
meant suppressing the prompt, but inputs were still processed).

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@6715 c046a42c-6fe2-441c-8c8c-71466251a162
migration-exec.c
... ... @@ -18,7 +18,6 @@
18 18 #include "migration.h"
19 19 #include "qemu-char.h"
20 20 #include "sysemu.h"
21   -#include "monitor.h"
22 21 #include "buffered_file.h"
23 22 #include "block.h"
24 23  
... ... @@ -55,7 +54,7 @@ static int exec_close(FdMigrationState *s)
55 54  
56 55 MigrationState *exec_start_outgoing_migration(const char *command,
57 56 int64_t bandwidth_limit,
58   - int async)
  57 + int detach)
59 58 {
60 59 FdMigrationState *s;
61 60 FILE *f;
... ... @@ -89,14 +88,11 @@ MigrationState *exec_start_outgoing_migration(const char *command,
89 88 s->mig_state.release = migrate_fd_release;
90 89  
91 90 s->state = MIG_STATE_ACTIVE;
92   - s->detach = !async;
  91 + s->mon_resume = NULL;
93 92 s->bandwidth_limit = bandwidth_limit;
94 93  
95   - if (s->detach == 1) {
96   - dprintf("detaching from monitor\n");
97   - monitor_suspend(cur_mon);
98   - s->detach = 2;
99   - }
  94 + if (!detach)
  95 + migrate_fd_monitor_suspend(s);
100 96  
101 97 migrate_fd_connect(s);
102 98 return &s->mig_state;
... ...
migration-tcp.c
... ... @@ -16,7 +16,6 @@
16 16 #include "migration.h"
17 17 #include "qemu-char.h"
18 18 #include "sysemu.h"
19   -#include "monitor.h"
20 19 #include "buffered_file.h"
21 20 #include "block.h"
22 21  
... ... @@ -79,7 +78,7 @@ static void tcp_wait_for_connect(void *opaque)
79 78  
80 79 MigrationState *tcp_start_outgoing_migration(const char *host_port,
81 80 int64_t bandwidth_limit,
82   - int async)
  81 + int detach)
83 82 {
84 83 struct sockaddr_in addr;
85 84 FdMigrationState *s;
... ... @@ -98,7 +97,7 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
98 97 s->mig_state.release = migrate_fd_release;
99 98  
100 99 s->state = MIG_STATE_ACTIVE;
101   - s->detach = !async;
  100 + s->mon_resume = NULL;
102 101 s->bandwidth_limit = bandwidth_limit;
103 102 s->fd = socket(PF_INET, SOCK_STREAM, 0);
104 103 if (s->fd == -1) {
... ... @@ -108,11 +107,8 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
108 107  
109 108 socket_set_nonblock(s->fd);
110 109  
111   - if (s->detach == 1) {
112   - dprintf("detaching from monitor\n");
113   - monitor_suspend(cur_mon);
114   - s->detach = 2;
115   - }
  110 + if (!detach)
  111 + migrate_fd_monitor_suspend(s);
116 112  
117 113 do {
118 114 ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
... ...
migration.c
... ... @@ -125,6 +125,13 @@ void do_info_migrate(Monitor *mon)
125 125  
126 126 /* shared migration helpers */
127 127  
  128 +void migrate_fd_monitor_suspend(FdMigrationState *s)
  129 +{
  130 + s->mon_resume = cur_mon;
  131 + monitor_suspend(cur_mon);
  132 + dprintf("suspending monitor\n");
  133 +}
  134 +
128 135 void migrate_fd_error(FdMigrationState *s)
129 136 {
130 137 dprintf("setting error state\n");
... ... @@ -145,10 +152,8 @@ void migrate_fd_cleanup(FdMigrationState *s)
145 152 close(s->fd);
146 153  
147 154 /* Don't resume monitor until we've flushed all of the buffers */
148   - if (s->detach == 2) {
149   - monitor_resume(cur_mon);
150   - s->detach = 0;
151   - }
  155 + if (s->mon_resume)
  156 + monitor_resume(s->mon_resume);
152 157  
153 158 s->fd = -1;
154 159 }
... ...
migration.h
... ... @@ -39,7 +39,7 @@ struct FdMigrationState
39 39 int64_t bandwidth_limit;
40 40 QEMUFile *file;
41 41 int fd;
42   - int detach;
  42 + Monitor *mon_resume;
43 43 int state;
44 44 int (*get_error)(struct FdMigrationState*);
45 45 int (*close)(struct FdMigrationState*);
... ... @@ -69,6 +69,8 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
69 69 int64_t bandwidth_limit,
70 70 int detach);
71 71  
  72 +void migrate_fd_monitor_suspend(FdMigrationState *s);
  73 +
72 74 void migrate_fd_error(FdMigrationState *s);
73 75  
74 76 void migrate_fd_cleanup(FdMigrationState *s);
... ...
monitor.c
... ... @@ -69,6 +69,14 @@ typedef struct mon_cmd_t {
69 69  
70 70 struct Monitor {
71 71 CharDriverState *chr;
  72 + int flags;
  73 + int suspend_cnt;
  74 + uint8_t outbuf[1024];
  75 + int outbuf_index;
  76 + ReadLineState *rs;
  77 + CPUState *mon_cpu;
  78 + BlockDriverCompletionFunc *password_completion_cb;
  79 + void *password_opaque;
72 80 LIST_ENTRY(Monitor) entry;
73 81 };
74 82  
... ... @@ -77,34 +85,30 @@ static LIST_HEAD(mon_list, Monitor) mon_list;
77 85 static const mon_cmd_t mon_cmds[];
78 86 static const mon_cmd_t info_cmds[];
79 87  
80   -static uint8_t term_outbuf[1024];
81   -static int term_outbuf_index;
82   -static BlockDriverCompletionFunc *password_completion_cb;
83   -static void *password_opaque;
84   -ReadLineState *rs;
85   -
86 88 Monitor *cur_mon = NULL;
87 89  
88   -static void monitor_start_input(void);
  90 +static void monitor_command_cb(Monitor *mon, const char *cmdline,
  91 + void *opaque);
89 92  
90   -static CPUState *mon_cpu = NULL;
  93 +static void monitor_read_command(Monitor *mon, int show_prompt)
  94 +{
  95 + readline_start(mon->rs, "(qemu) ", 0, monitor_command_cb, NULL);
  96 + if (show_prompt)
  97 + readline_show_prompt(mon->rs);
  98 +}
91 99  
92 100 static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
93 101 void *opaque)
94 102 {
95   - readline_start(rs, "Password: ", 1, readline_func, opaque);
  103 + readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
  104 + /* prompt is printed on return from the command handler */
96 105 }
97 106  
98 107 void monitor_flush(Monitor *mon)
99 108 {
100   - Monitor *m;
101   -
102   - if (term_outbuf_index > 0) {
103   - LIST_FOREACH(m, &mon_list, entry) {
104   - if (m->chr->focus == 0)
105   - qemu_chr_write(m->chr, term_outbuf, term_outbuf_index);
106   - }
107   - term_outbuf_index = 0;
  109 + if (mon && mon->outbuf_index != 0 && mon->chr->focus == 0) {
  110 + qemu_chr_write(mon->chr, mon->outbuf, mon->outbuf_index);
  111 + mon->outbuf_index = 0;
108 112 }
109 113 }
110 114  
... ... @@ -112,15 +116,19 @@ void monitor_flush(Monitor *mon)
112 116 static void monitor_puts(Monitor *mon, const char *str)
113 117 {
114 118 char c;
  119 +
  120 + if (!mon)
  121 + return;
  122 +
115 123 for(;;) {
116 124 c = *str++;
117 125 if (c == '\0')
118 126 break;
119 127 if (c == '\n')
120   - term_outbuf[term_outbuf_index++] = '\r';
121   - term_outbuf[term_outbuf_index++] = c;
122   - if (term_outbuf_index >= (sizeof(term_outbuf) - 1) ||
123   - c == '\n')
  128 + mon->outbuf[mon->outbuf_index++] = '\r';
  129 + mon->outbuf[mon->outbuf_index++] = c;
  130 + if (mon->outbuf_index >= (sizeof(mon->outbuf) - 1)
  131 + || c == '\n')
124 132 monitor_flush(mon);
125 133 }
126 134 }
... ... @@ -291,7 +299,7 @@ static int mon_set_cpu(int cpu_index)
291 299  
292 300 for(env = first_cpu; env != NULL; env = env->next_cpu) {
293 301 if (env->cpu_index == cpu_index) {
294   - mon_cpu = env;
  302 + cur_mon->mon_cpu = env;
295 303 return 0;
296 304 }
297 305 }
... ... @@ -300,10 +308,10 @@ static int mon_set_cpu(int cpu_index)
300 308  
301 309 static CPUState *mon_get_cpu(void)
302 310 {
303   - if (!mon_cpu) {
  311 + if (!cur_mon->mon_cpu) {
304 312 mon_set_cpu(0);
305 313 }
306   - return mon_cpu;
  314 + return cur_mon->mon_cpu;
307 315 }
308 316  
309 317 static void do_info_registers(Monitor *mon)
... ... @@ -330,7 +338,7 @@ static void do_info_cpus(Monitor *mon)
330 338  
331 339 for(env = first_cpu; env != NULL; env = env->next_cpu) {
332 340 monitor_printf(mon, "%c CPU #%d:",
333   - (env == mon_cpu) ? '*' : ' ',
  341 + (env == mon->mon_cpu) ? '*' : ' ',
334 342 env->cpu_index);
335 343 #if defined(TARGET_I386)
336 344 monitor_printf(mon, " pc=0x" TARGET_FMT_lx,
... ... @@ -367,7 +375,7 @@ static void do_info_history(Monitor *mon)
367 375  
368 376 i = 0;
369 377 for(;;) {
370   - str = readline_get_history(rs, i);
  378 + str = readline_get_history(mon->rs, i);
371 379 if (!str)
372 380 break;
373 381 monitor_printf(mon, "%d: '%s'\n", i, str);
... ... @@ -451,7 +459,7 @@ static void change_vnc_password_cb(Monitor *mon, const char *password,
451 459 if (vnc_display_password(NULL, password) < 0)
452 460 monitor_printf(mon, "could not set VNC server password\n");
453 461  
454   - monitor_start_input();
  462 + monitor_read_command(mon, 1);
455 463 }
456 464  
457 465 static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
... ... @@ -2688,7 +2696,7 @@ static void cmd_completion(const char *name, const char *list)
2688 2696 memcpy(cmd, pstart, len);
2689 2697 cmd[len] = '\0';
2690 2698 if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
2691   - readline_add_completion(rs, cmd);
  2699 + readline_add_completion(cur_mon->rs, cmd);
2692 2700 }
2693 2701 if (*p == '\0')
2694 2702 break;
... ... @@ -2741,7 +2749,7 @@ static void file_completion(const char *input)
2741 2749 stat(file, &sb);
2742 2750 if(S_ISDIR(sb.st_mode))
2743 2751 pstrcat(file, sizeof(file), "/");
2744   - readline_add_completion(rs, file);
  2752 + readline_add_completion(cur_mon->rs, file);
2745 2753 }
2746 2754 }
2747 2755 closedir(ffs);
... ... @@ -2754,7 +2762,7 @@ static void block_completion_it(void *opaque, BlockDriverState *bs)
2754 2762  
2755 2763 if (input[0] == '\0' ||
2756 2764 !strncmp(name, (char *)input, strlen(input))) {
2757   - readline_add_completion(rs, name);
  2765 + readline_add_completion(cur_mon->rs, name);
2758 2766 }
2759 2767 }
2760 2768  
... ... @@ -2814,7 +2822,7 @@ static void monitor_find_completion(const char *cmdline)
2814 2822 cmdname = "";
2815 2823 else
2816 2824 cmdname = args[0];
2817   - readline_set_completion_index(rs, strlen(cmdname));
  2825 + readline_set_completion_index(cur_mon->rs, strlen(cmdname));
2818 2826 for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
2819 2827 cmd_completion(cmdname, cmd->name);
2820 2828 }
... ... @@ -2838,23 +2846,23 @@ static void monitor_find_completion(const char *cmdline)
2838 2846 switch(*ptype) {
2839 2847 case 'F':
2840 2848 /* file completion */
2841   - readline_set_completion_index(rs, strlen(str));
  2849 + readline_set_completion_index(cur_mon->rs, strlen(str));
2842 2850 file_completion(str);
2843 2851 break;
2844 2852 case 'B':
2845 2853 /* block device name completion */
2846   - readline_set_completion_index(rs, strlen(str));
  2854 + readline_set_completion_index(cur_mon->rs, strlen(str));
2847 2855 bdrv_iterate(block_completion_it, (void *)str);
2848 2856 break;
2849 2857 case 's':
2850 2858 /* XXX: more generic ? */
2851 2859 if (!strcmp(cmd->name, "info")) {
2852   - readline_set_completion_index(rs, strlen(str));
  2860 + readline_set_completion_index(cur_mon->rs, strlen(str));
2853 2861 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
2854 2862 cmd_completion(str, cmd->name);
2855 2863 }
2856 2864 } else if (!strcmp(cmd->name, "sendkey")) {
2857   - readline_set_completion_index(rs, strlen(str));
  2865 + readline_set_completion_index(cur_mon->rs, strlen(str));
2858 2866 for(key = key_defs; key->name != NULL; key++) {
2859 2867 cmd_completion(str, key->name);
2860 2868 }
... ... @@ -2868,49 +2876,45 @@ static void monitor_find_completion(const char *cmdline)
2868 2876 qemu_free(args[i]);
2869 2877 }
2870 2878  
2871   -static int term_can_read(void *opaque)
  2879 +static int monitor_can_read(void *opaque)
2872 2880 {
2873   - return 128;
  2881 + Monitor *mon = opaque;
  2882 +
  2883 + return (mon->suspend_cnt == 0) ? 128 : 0;
2874 2884 }
2875 2885  
2876   -static void term_read(void *opaque, const uint8_t *buf, int size)
  2886 +static void monitor_read(void *opaque, const uint8_t *buf, int size)
2877 2887 {
  2888 + Monitor *old_mon = cur_mon;
2878 2889 int i;
2879 2890  
2880   - for(i = 0; i < size; i++)
2881   - readline_handle_byte(rs, buf[i]);
2882   -}
  2891 + cur_mon = opaque;
  2892 +
  2893 + for (i = 0; i < size; i++)
  2894 + readline_handle_byte(cur_mon->rs, buf[i]);
2883 2895  
2884   -static int monitor_suspended;
  2896 + cur_mon = old_mon;
  2897 +}
2885 2898  
2886 2899 static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
2887 2900 {
  2901 + monitor_suspend(mon);
2888 2902 monitor_handle_command(mon, cmdline);
2889   - if (!monitor_suspended)
2890   - readline_show_prompt(rs);
2891   - else
2892   - monitor_suspended = 2;
  2903 + monitor_resume(mon);
2893 2904 }
2894 2905  
2895 2906 void monitor_suspend(Monitor *mon)
2896 2907 {
2897   - monitor_suspended = 1;
  2908 + mon->suspend_cnt++;
2898 2909 }
2899 2910  
2900 2911 void monitor_resume(Monitor *mon)
2901 2912 {
2902   - if (monitor_suspended == 2)
2903   - monitor_start_input();
2904   - monitor_suspended = 0;
  2913 + if (--mon->suspend_cnt == 0)
  2914 + readline_show_prompt(mon->rs);
2905 2915 }
2906 2916  
2907   -static void monitor_start_input(void)
2908   -{
2909   - readline_start(rs, "(qemu) ", 0, monitor_command_cb, NULL);
2910   - readline_show_prompt(rs);
2911   -}
2912   -
2913   -static void term_event(void *opaque, int event)
  2917 +static void monitor_event(void *opaque, int event)
2914 2918 {
2915 2919 Monitor *mon = opaque;
2916 2920  
... ... @@ -2919,13 +2923,12 @@ static void term_event(void *opaque, int event)
2919 2923  
2920 2924 monitor_printf(mon, "QEMU %s monitor - type 'help' for more information\n",
2921 2925 QEMU_VERSION);
2922   - monitor_start_input();
  2926 + readline_show_prompt(mon->rs);
2923 2927 }
2924 2928  
2925   -static int is_first_init = 1;
2926   -
2927   -void monitor_init(CharDriverState *chr)
  2929 +void monitor_init(CharDriverState *chr, int flags)
2928 2930 {
  2931 + static int is_first_init = 1;
2929 2932 Monitor *mon;
2930 2933  
2931 2934 if (is_first_init) {
... ... @@ -2936,15 +2939,16 @@ void monitor_init(CharDriverState *chr)
2936 2939 mon = qemu_mallocz(sizeof(*mon));
2937 2940  
2938 2941 mon->chr = chr;
2939   - rs = readline_init(mon, monitor_find_completion);
  2942 + mon->flags = flags;
  2943 + mon->rs = readline_init(mon, monitor_find_completion);
  2944 + monitor_read_command(mon, 0);
2940 2945  
2941   - qemu_chr_add_handlers(chr, term_can_read, term_read, term_event, mon);
  2946 + qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event,
  2947 + mon);
2942 2948  
2943 2949 LIST_INSERT_HEAD(&mon_list, mon, entry);
2944   - if (!cur_mon)
  2950 + if (!cur_mon || (flags & MONITOR_IS_DEFAULT))
2945 2951 cur_mon = mon;
2946   -
2947   - readline_start(rs, "", 0, monitor_command_cb, NULL);
2948 2952 }
2949 2953  
2950 2954 static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
... ... @@ -2956,10 +2960,10 @@ static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
2956 2960 monitor_printf(mon, "invalid password\n");
2957 2961 ret = -EPERM;
2958 2962 }
2959   - if (password_completion_cb)
2960   - password_completion_cb(password_opaque, ret);
  2963 + if (mon->password_completion_cb)
  2964 + mon->password_completion_cb(mon->password_opaque, ret);
2961 2965  
2962   - monitor_start_input();
  2966 + monitor_read_command(mon, 1);
2963 2967 }
2964 2968  
2965 2969 void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
... ... @@ -2975,8 +2979,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
2975 2979 monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
2976 2980 bdrv_get_encrypted_filename(bs));
2977 2981  
2978   - password_completion_cb = completion_cb;
2979   - password_opaque = opaque;
  2982 + mon->password_completion_cb = completion_cb;
  2983 + mon->password_opaque = opaque;
2980 2984  
2981 2985 monitor_read_password(mon, bdrv_password_cb, bs);
2982 2986 }
... ...
monitor.h
... ... @@ -7,7 +7,10 @@
7 7  
8 8 extern Monitor *cur_mon;
9 9  
10   -void monitor_init(CharDriverState *chr);
  10 +/* flags for monitor_init */
  11 +#define MONITOR_IS_DEFAULT 0x01
  12 +
  13 +void monitor_init(CharDriverState *chr, int flags);
11 14  
12 15 void monitor_suspend(Monitor *mon);
13 16 void monitor_resume(Monitor *mon);
... ...
qemu-char.c
... ... @@ -2123,7 +2123,7 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i
2123 2123 chr = qemu_chr_open(label, p, NULL);
2124 2124 if (chr) {
2125 2125 chr = qemu_chr_open_mux(chr);
2126   - monitor_init(chr);
  2126 + monitor_init(chr, 0);
2127 2127 } else {
2128 2128 printf("Unable to open driver: %s\n", p);
2129 2129 }
... ...
... ... @@ -5684,7 +5684,7 @@ int main(int argc, char **argv, char **envp)
5684 5684 qemu_chr_initial_reset();
5685 5685  
5686 5686 if (monitor_device && monitor_hd)
5687   - monitor_init(monitor_hd);
  5687 + monitor_init(monitor_hd, MONITOR_IS_DEFAULT);
5688 5688  
5689 5689 for(i = 0; i < MAX_SERIAL_PORTS; i++) {
5690 5690 const char *devname = serial_devices[i];
... ...