Monitor patches
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVbWZHAAoJEDhwtADrkYZTQ6oQAIv3FRNj0buUSwh8Gwx8NrxJ DHz/NgdtoRV/olk2ZPYSmKUooTdKFcH1XsR7oYBoznh2m/CgiQXGeJQ7tTTcrWAj hw4vt4Uq0bMGPNFYNOBgsVC5cejiZo53YfXybRBLAcUJvOlbnPVJ+g7ru8mg3qaC rX0ZI8Cu0QmQWsGXHuKArVRGSsc+CN4SbXWyI4WmMH3g9OzTVjKVDkZekcU3NbXj GZq1mJBeVUsDT6wzRLGXe3qxkDAhK9THLoRd999/aQDWSpvUabNtotyZew5JG5Ey WKkmhSZsi0RgJTuPUcf5i83QKrWVN8EaADn67J5GkrnYYVPLdWuk/PhRgFiiWlVk mHFxEVyfQL7neTbb8dcwcREHIaSSb4BBF4+dyFk5921Idxs3kzw/5l20SwNi6bQy y23Tq/tBvbsie89O1gdXipZm3pz9xM9/9FtODjGnnVO9zb9Fi9TAyMMi8RmiS15k YL649rCgk9cwKOlwsMLSUajXGq0G1cOzou7M5DeDOLw5db5YEMMZkcpmETKNLaXk DWiX1E1K6PsDHDQkAipi9lmP9izVmpfXS4EWNVLaVCP3ht27VHgsZx4TaAAr8AVD NdA4wq/GEcUMcJI+erJe3YxZgPofO+Ja8whwyqwhvLM4g6g8gQgy7PNKM+FodXY1 Z5+Ou90aprDpWjPIUHOv =ySet -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-monitor-2015-06-02' into staging Monitor patches # gpg: Signature made Tue Jun 2 09:16:07 2015 BST using RSA key ID EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" * remotes/armbru/tags/pull-monitor-2015-06-02: (21 commits) monitor: Change return type of monitor_cur_is_qmp() to bool monitor: Rename monitor_ctrl_mode() to monitor_is_qmp() monitor: Turn int command_mode into bool in_command_mode monitor: Drop do_qmp_capabilities()'s superfluous QMP check monitor: Unbox Monitor member mc and rename to qmp monitor: Rename monitor_control_read(), monitor_control_event() monitor: Rename handle_user_command() to handle_hmp_command() monitor: Limit QError use to command handlers monitor: Inline monitor_has_error() into its only caller monitor: Wean monitor_protocol_emitter() off mon->error monitor: Propagate errors through invalid_qmp_mode() monitor: Propagate errors through qmp_check_input_obj() monitor: Propagate errors through qmp_check_client_args() monitor: Drop unused "new" HMP command interface monitor: Use trad. command interface for HMP pcie_aer_inject_error monitor: Use traditional command interface for HMP device_add monitor: Use traditional command interface for HMP drive_del monitor: Convert client_migrate_info to QAPI monitor: Improve and document client_migrate_info protocol error monitor: Clean up after previous commit ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						a67bfbb9e4
					
				@ -2113,7 +2113,7 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
 | 
				
			|||||||
    aio_context_release(aio_context);
 | 
					    aio_context_release(aio_context);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 | 
					void hmp_drive_del(Monitor *mon, const QDict *qdict)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const char *id = qdict_get_str(qdict, "id");
 | 
					    const char *id = qdict_get_str(qdict, "id");
 | 
				
			||||||
    BlockBackend *blk;
 | 
					    BlockBackend *blk;
 | 
				
			||||||
@ -2124,14 +2124,14 @@ int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 | 
				
			|||||||
    blk = blk_by_name(id);
 | 
					    blk = blk_by_name(id);
 | 
				
			||||||
    if (!blk) {
 | 
					    if (!blk) {
 | 
				
			||||||
        error_report("Device '%s' not found", id);
 | 
					        error_report("Device '%s' not found", id);
 | 
				
			||||||
        return -1;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    bs = blk_bs(blk);
 | 
					    bs = blk_bs(blk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!blk_legacy_dinfo(blk)) {
 | 
					    if (!blk_legacy_dinfo(blk)) {
 | 
				
			||||||
        error_report("Deleting device added with blockdev-add"
 | 
					        error_report("Deleting device added with blockdev-add"
 | 
				
			||||||
                     " is not supported");
 | 
					                     " is not supported");
 | 
				
			||||||
        return -1;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    aio_context = bdrv_get_aio_context(bs);
 | 
					    aio_context = bdrv_get_aio_context(bs);
 | 
				
			||||||
@ -2140,7 +2140,7 @@ int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 | 
				
			|||||||
    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
 | 
					    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
 | 
				
			||||||
        error_report_err(local_err);
 | 
					        error_report_err(local_err);
 | 
				
			||||||
        aio_context_release(aio_context);
 | 
					        aio_context_release(aio_context);
 | 
				
			||||||
        return -1;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* quiesce block driver; prevent further io */
 | 
					    /* quiesce block driver; prevent further io */
 | 
				
			||||||
@ -2163,7 +2163,6 @@ int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    aio_context_release(aio_context);
 | 
					    aio_context_release(aio_context);
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void qmp_block_resize(bool has_device, const char *device,
 | 
					void qmp_block_resize(bool has_device, const char *device,
 | 
				
			||||||
 | 
				
			|||||||
@ -178,8 +178,7 @@ ETEXI
 | 
				
			|||||||
        .args_type  = "id:B",
 | 
					        .args_type  = "id:B",
 | 
				
			||||||
        .params     = "device",
 | 
					        .params     = "device",
 | 
				
			||||||
        .help       = "remove host block device",
 | 
					        .help       = "remove host block device",
 | 
				
			||||||
        .user_print = monitor_user_noop,
 | 
					        .mhandler.cmd = hmp_drive_del,
 | 
				
			||||||
        .mhandler.cmd_new = hmp_drive_del,
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
STEXI
 | 
					STEXI
 | 
				
			||||||
@ -654,8 +653,7 @@ ETEXI
 | 
				
			|||||||
        .args_type  = "device:O",
 | 
					        .args_type  = "device:O",
 | 
				
			||||||
        .params     = "driver[,prop=value][,...]",
 | 
					        .params     = "driver[,prop=value][,...]",
 | 
				
			||||||
        .help       = "add device, like -device on the command line",
 | 
					        .help       = "add device, like -device on the command line",
 | 
				
			||||||
        .user_print = monitor_user_noop,
 | 
					        .mhandler.cmd = hmp_device_add,
 | 
				
			||||||
        .mhandler.cmd_new = do_device_add,
 | 
					 | 
				
			||||||
        .command_completion = device_add_completion,
 | 
					        .command_completion = device_add_completion,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1011,17 +1009,16 @@ ETEXI
 | 
				
			|||||||
        .name       = "client_migrate_info",
 | 
					        .name       = "client_migrate_info",
 | 
				
			||||||
        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
 | 
					        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
 | 
				
			||||||
        .params     = "protocol hostname port tls-port cert-subject",
 | 
					        .params     = "protocol hostname port tls-port cert-subject",
 | 
				
			||||||
        .help       = "send migration info to spice/vnc client",
 | 
					        .help       = "set migration information for remote display",
 | 
				
			||||||
        .user_print = monitor_user_noop,
 | 
					        .mhandler.cmd = hmp_client_migrate_info,
 | 
				
			||||||
        .mhandler.cmd_new = client_migrate_info,
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
STEXI
 | 
					STEXI
 | 
				
			||||||
@item client_migrate_info @var{protocol} @var{hostname} @var{port} @var{tls-port} @var{cert-subject}
 | 
					@item client_migrate_info @var{protocol} @var{hostname} @var{port} @var{tls-port} @var{cert-subject}
 | 
				
			||||||
@findex client_migrate_info
 | 
					@findex client_migrate_info
 | 
				
			||||||
Set the spice/vnc connection info for the migration target.  The spice/vnc
 | 
					Set migration information for remote display.  This makes the server
 | 
				
			||||||
server will ask the spice/vnc client to automatically reconnect using the
 | 
					ask the client to automatically reconnect using the new parameters
 | 
				
			||||||
new parameters (if specified) once the vm migration finished successfully.
 | 
					once migration finished successfully.  Only implemented for SPICE.
 | 
				
			||||||
ETEXI
 | 
					ETEXI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -1186,8 +1183,7 @@ ETEXI
 | 
				
			|||||||
                      "<error_status> = error string or 32bit\n\t\t\t"
 | 
					                      "<error_status> = error string or 32bit\n\t\t\t"
 | 
				
			||||||
                      "<tlb header> = 32bit x 4\n\t\t\t"
 | 
					                      "<tlb header> = 32bit x 4\n\t\t\t"
 | 
				
			||||||
                      "<tlb header prefix> = 32bit x 4",
 | 
					                      "<tlb header prefix> = 32bit x 4",
 | 
				
			||||||
        .user_print  = pcie_aer_inject_error_print,
 | 
					        .mhandler.cmd = hmp_pcie_aer_inject_error,
 | 
				
			||||||
        .mhandler.cmd_new = hmp_pcie_aer_inject_error,
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
STEXI
 | 
					STEXI
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										23
									
								
								hmp.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								hmp.c
									
									
									
									
									
								
							@ -22,6 +22,7 @@
 | 
				
			|||||||
#include "qmp-commands.h"
 | 
					#include "qmp-commands.h"
 | 
				
			||||||
#include "qemu/sockets.h"
 | 
					#include "qemu/sockets.h"
 | 
				
			||||||
#include "monitor/monitor.h"
 | 
					#include "monitor/monitor.h"
 | 
				
			||||||
 | 
					#include "monitor/qdev.h"
 | 
				
			||||||
#include "qapi/opts-visitor.h"
 | 
					#include "qapi/opts-visitor.h"
 | 
				
			||||||
#include "qapi/string-output-visitor.h"
 | 
					#include "qapi/string-output-visitor.h"
 | 
				
			||||||
#include "qapi-visit.h"
 | 
					#include "qapi-visit.h"
 | 
				
			||||||
@ -1250,6 +1251,23 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void hmp_client_migrate_info(Monitor *mon, const QDict *qdict)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Error *err = NULL;
 | 
				
			||||||
 | 
					    const char *protocol = qdict_get_str(qdict, "protocol");
 | 
				
			||||||
 | 
					    const char *hostname = qdict_get_str(qdict, "hostname");
 | 
				
			||||||
 | 
					    bool has_port        = qdict_haskey(qdict, "port");
 | 
				
			||||||
 | 
					    int port             = qdict_get_try_int(qdict, "port", -1);
 | 
				
			||||||
 | 
					    bool has_tls_port    = qdict_haskey(qdict, "tls-port");
 | 
				
			||||||
 | 
					    int tls_port         = qdict_get_try_int(qdict, "tls-port", -1);
 | 
				
			||||||
 | 
					    const char *cert_subject = qdict_get_try_str(qdict, "cert-subject");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qmp_client_migrate_info(protocol, hostname,
 | 
				
			||||||
 | 
					                            has_port, port, has_tls_port, tls_port,
 | 
				
			||||||
 | 
					                            !!cert_subject, cert_subject, &err);
 | 
				
			||||||
 | 
					    hmp_handle_error(mon, &err);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void hmp_set_password(Monitor *mon, const QDict *qdict)
 | 
					void hmp_set_password(Monitor *mon, const QDict *qdict)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const char *protocol  = qdict_get_str(qdict, "protocol");
 | 
					    const char *protocol  = qdict_get_str(qdict, "protocol");
 | 
				
			||||||
@ -1482,6 +1500,11 @@ void hmp_migrate(Monitor *mon, const QDict *qdict)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void hmp_device_add(Monitor *mon, const QDict *qdict)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    do_device_add(mon, qdict, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void hmp_device_del(Monitor *mon, const QDict *qdict)
 | 
					void hmp_device_del(Monitor *mon, const QDict *qdict)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const char *id = qdict_get_str(qdict, "id");
 | 
					    const char *id = qdict_get_str(qdict, "id");
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								hmp.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								hmp.h
									
									
									
									
									
								
							@ -67,6 +67,7 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
 | 
				
			|||||||
void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict);
 | 
					void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
 | 
					void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict);
 | 
					void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
 | 
					void hmp_client_migrate_info(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_set_password(Monitor *mon, const QDict *qdict);
 | 
					void hmp_set_password(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_expire_password(Monitor *mon, const QDict *qdict);
 | 
					void hmp_expire_password(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_eject(Monitor *mon, const QDict *qdict);
 | 
					void hmp_eject(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
@ -79,6 +80,7 @@ void hmp_block_job_pause(Monitor *mon, const QDict *qdict);
 | 
				
			|||||||
void hmp_block_job_resume(Monitor *mon, const QDict *qdict);
 | 
					void hmp_block_job_resume(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_block_job_complete(Monitor *mon, const QDict *qdict);
 | 
					void hmp_block_job_complete(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_migrate(Monitor *mon, const QDict *qdict);
 | 
					void hmp_migrate(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
 | 
					void hmp_device_add(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_device_del(Monitor *mon, const QDict *qdict);
 | 
					void hmp_device_del(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
 | 
					void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
void hmp_netdev_add(Monitor *mon, const QDict *qdict);
 | 
					void hmp_netdev_add(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
 | 
				
			|||||||
@ -29,19 +29,7 @@ PciInfoList *qmp_query_pci(Error **errp)
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pci_error_message(Monitor *mon)
 | 
					void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    monitor_printf(mon, "PCI devices not supported\n");
 | 
					    monitor_printf(mon, "PCI devices not supported\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
int hmp_pcie_aer_inject_error(Monitor *mon,
 | 
					 | 
				
			||||||
                             const QDict *qdict, QObject **ret_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    pci_error_message(mon);
 | 
					 | 
				
			||||||
    return -ENOSYS;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    pci_error_message(mon);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -815,21 +815,6 @@ const VMStateDescription vmstate_pcie_aer_log = {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    QDict *qdict;
 | 
					 | 
				
			||||||
    int devfn;
 | 
					 | 
				
			||||||
    assert(qobject_type(data) == QTYPE_QDICT);
 | 
					 | 
				
			||||||
    qdict = qobject_to_qdict(data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    devfn = (int)qdict_get_int(qdict, "devfn");
 | 
					 | 
				
			||||||
    monitor_printf(mon, "OK id: %s root bus: %s, bus: %x devfn: %x.%x\n",
 | 
					 | 
				
			||||||
                   qdict_get_str(qdict, "id"),
 | 
					 | 
				
			||||||
                   qdict_get_str(qdict, "root_bus"),
 | 
					 | 
				
			||||||
                   (int) qdict_get_int(qdict, "bus"),
 | 
					 | 
				
			||||||
                   PCI_SLOT(devfn), PCI_FUNC(devfn));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct PCIEAERErrorName {
 | 
					typedef struct PCIEAERErrorName {
 | 
				
			||||||
    const char *name;
 | 
					    const char *name;
 | 
				
			||||||
    uint32_t val;
 | 
					    uint32_t val;
 | 
				
			||||||
@ -962,8 +947,8 @@ static int pcie_aer_parse_error_string(const char *error_name,
 | 
				
			|||||||
    return -EINVAL;
 | 
					    return -EINVAL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int hmp_pcie_aer_inject_error(Monitor *mon,
 | 
					static int do_pcie_aer_inject_error(Monitor *mon,
 | 
				
			||||||
                             const QDict *qdict, QObject **ret_data)
 | 
					                                    const QDict *qdict, QObject **ret_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const char *id = qdict_get_str(qdict, "id");
 | 
					    const char *id = qdict_get_str(qdict, "id");
 | 
				
			||||||
    const char *error_name;
 | 
					    const char *error_name;
 | 
				
			||||||
@ -1035,3 +1020,23 @@ int hmp_pcie_aer_inject_error(Monitor *mon,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QObject *data;
 | 
				
			||||||
 | 
					    int devfn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (do_pcie_aer_inject_error(mon, qdict, &data) < 0) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(qobject_type(data) == QTYPE_QDICT);
 | 
				
			||||||
 | 
					    qdict = qobject_to_qdict(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    devfn = (int)qdict_get_int(qdict, "devfn");
 | 
				
			||||||
 | 
					    monitor_printf(mon, "OK id: %s root bus: %s, bus: %x devfn: %x.%x\n",
 | 
				
			||||||
 | 
					                   qdict_get_str(qdict, "id"),
 | 
				
			||||||
 | 
					                   qdict_get_str(qdict, "root_bus"),
 | 
				
			||||||
 | 
					                   (int) qdict_get_int(qdict, "bus"),
 | 
				
			||||||
 | 
					                   PCI_SLOT(devfn), PCI_FUNC(devfn));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,10 +16,7 @@ extern Monitor *default_mon;
 | 
				
			|||||||
#define MONITOR_USE_CONTROL   0x04
 | 
					#define MONITOR_USE_CONTROL   0x04
 | 
				
			||||||
#define MONITOR_USE_PRETTY    0x08
 | 
					#define MONITOR_USE_PRETTY    0x08
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* flags for monitor commands */
 | 
					bool monitor_cur_is_qmp(void);
 | 
				
			||||||
#define MONITOR_CMD_ASYNC       0x0001
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int monitor_cur_is_qmp(void);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void monitor_init(CharDriverState *chr, int flags);
 | 
					void monitor_init(CharDriverState *chr, int flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -43,8 +40,6 @@ void monitor_flush(Monitor *mon);
 | 
				
			|||||||
int monitor_set_cpu(int cpu_index);
 | 
					int monitor_set_cpu(int cpu_index);
 | 
				
			||||||
int monitor_get_cpu_index(void);
 | 
					int monitor_get_cpu_index(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void (MonitorCompletion)(void *opaque, QObject *ret_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void monitor_set_error(Monitor *mon, QError *qerror);
 | 
					void monitor_set_error(Monitor *mon, QError *qerror);
 | 
				
			||||||
void monitor_read_command(Monitor *mon, int show_prompt);
 | 
					void monitor_read_command(Monitor *mon, int show_prompt);
 | 
				
			||||||
int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
 | 
					int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
 | 
				
			||||||
 | 
				
			|||||||
@ -66,5 +66,5 @@ DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type);
 | 
				
			|||||||
void qmp_change_blockdev(const char *device, const char *filename,
 | 
					void qmp_change_blockdev(const char *device, const char *filename,
 | 
				
			||||||
                         const char *format, Error **errp);
 | 
					                         const char *format, Error **errp);
 | 
				
			||||||
void hmp_commit(Monitor *mon, const QDict *qdict);
 | 
					void hmp_commit(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
int hmp_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 | 
					void hmp_drive_del(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -161,9 +161,7 @@ extern unsigned int nb_prom_envs;
 | 
				
			|||||||
void hmp_drive_add(Monitor *mon, const QDict *qdict);
 | 
					void hmp_drive_add(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* pcie aer error injection */
 | 
					/* pcie aer error injection */
 | 
				
			||||||
void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
 | 
					void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
int hmp_pcie_aer_inject_error(Monitor *mon,
 | 
					 | 
				
			||||||
                             const QDict *qdict, QObject **ret_data);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* serial ports */
 | 
					/* serial ports */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										397
									
								
								monitor.c
									
									
									
									
									
								
							
							
						
						
									
										397
									
								
								monitor.c
									
									
									
									
									
								
							@ -118,25 +118,15 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct MonitorCompletionData MonitorCompletionData;
 | 
					 | 
				
			||||||
struct MonitorCompletionData {
 | 
					 | 
				
			||||||
    Monitor *mon;
 | 
					 | 
				
			||||||
    void (*user_print)(Monitor *mon, const QObject *data);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct mon_cmd_t {
 | 
					typedef struct mon_cmd_t {
 | 
				
			||||||
    const char *name;
 | 
					    const char *name;
 | 
				
			||||||
    const char *args_type;
 | 
					    const char *args_type;
 | 
				
			||||||
    const char *params;
 | 
					    const char *params;
 | 
				
			||||||
    const char *help;
 | 
					    const char *help;
 | 
				
			||||||
    void (*user_print)(Monitor *mon, const QObject *data);
 | 
					 | 
				
			||||||
    union {
 | 
					    union {
 | 
				
			||||||
        void (*cmd)(Monitor *mon, const QDict *qdict);
 | 
					        void (*cmd)(Monitor *mon, const QDict *qdict);
 | 
				
			||||||
        int  (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
 | 
					        int  (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
 | 
				
			||||||
        int  (*cmd_async)(Monitor *mon, const QDict *params,
 | 
					 | 
				
			||||||
                          MonitorCompletion *cb, void *opaque);
 | 
					 | 
				
			||||||
    } mhandler;
 | 
					    } mhandler;
 | 
				
			||||||
    int flags;
 | 
					 | 
				
			||||||
    /* @sub_table is a list of 2nd level of commands. If it do not exist,
 | 
					    /* @sub_table is a list of 2nd level of commands. If it do not exist,
 | 
				
			||||||
     * mhandler should be used. If it exist, sub_table[?].mhandler should be
 | 
					     * mhandler should be used. If it exist, sub_table[?].mhandler should be
 | 
				
			||||||
     * used, and mhandler of 1st level plays the role of help function.
 | 
					     * used, and mhandler of 1st level plays the role of help function.
 | 
				
			||||||
@ -171,11 +161,16 @@ struct MonFdset {
 | 
				
			|||||||
    QLIST_ENTRY(MonFdset) next;
 | 
					    QLIST_ENTRY(MonFdset) next;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct MonitorControl {
 | 
					typedef struct {
 | 
				
			||||||
    QObject *id;
 | 
					    QObject *id;
 | 
				
			||||||
    JSONMessageParser parser;
 | 
					    JSONMessageParser parser;
 | 
				
			||||||
    int command_mode;
 | 
					    /*
 | 
				
			||||||
} MonitorControl;
 | 
					     * When a client connects, we're in capabilities negotiation mode.
 | 
				
			||||||
 | 
					     * When command qmp_capabilities succeeds, we go into command
 | 
				
			||||||
 | 
					     * mode.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    bool in_command_mode;       /* are we in command mode? */
 | 
				
			||||||
 | 
					} MonitorQMP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * To prevent flooding clients, events can be throttled. The
 | 
					 * To prevent flooding clients, events can be throttled. The
 | 
				
			||||||
@ -205,7 +200,7 @@ struct Monitor {
 | 
				
			|||||||
    int mux_out;
 | 
					    int mux_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ReadLineState *rs;
 | 
					    ReadLineState *rs;
 | 
				
			||||||
    MonitorControl *mc;
 | 
					    MonitorQMP qmp;
 | 
				
			||||||
    CPUState *mon_cpu;
 | 
					    CPUState *mon_cpu;
 | 
				
			||||||
    BlockCompletionFunc *password_completion_cb;
 | 
					    BlockCompletionFunc *password_completion_cb;
 | 
				
			||||||
    void *password_opaque;
 | 
					    void *password_opaque;
 | 
				
			||||||
@ -236,21 +231,20 @@ Monitor *default_mon;
 | 
				
			|||||||
static void monitor_command_cb(void *opaque, const char *cmdline,
 | 
					static void monitor_command_cb(void *opaque, const char *cmdline,
 | 
				
			||||||
                               void *readline_opaque);
 | 
					                               void *readline_opaque);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int qmp_cmd_mode(const Monitor *mon)
 | 
					/**
 | 
				
			||||||
{
 | 
					 * Is @mon a QMP monitor?
 | 
				
			||||||
    return (mon->mc ? mon->mc->command_mode : 0);
 | 
					 */
 | 
				
			||||||
}
 | 
					static inline bool monitor_is_qmp(const Monitor *mon)
 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Return true if in control mode, false otherwise */
 | 
					 | 
				
			||||||
static inline int monitor_ctrl_mode(const Monitor *mon)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return (mon->flags & MONITOR_USE_CONTROL);
 | 
					    return (mon->flags & MONITOR_USE_CONTROL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Return non-zero iff we have a current monitor, and it is in QMP mode.  */
 | 
					/**
 | 
				
			||||||
int monitor_cur_is_qmp(void)
 | 
					 * Is the current monitor, if any, a QMP monitor?
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool monitor_cur_is_qmp(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return cur_mon && monitor_ctrl_mode(cur_mon);
 | 
					    return cur_mon && monitor_is_qmp(cur_mon);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void monitor_read_command(Monitor *mon, int show_prompt)
 | 
					void monitor_read_command(Monitor *mon, int show_prompt)
 | 
				
			||||||
@ -360,7 +354,7 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
 | 
				
			|||||||
    if (!mon)
 | 
					    if (!mon)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (monitor_ctrl_mode(mon)) {
 | 
					    if (monitor_is_qmp(mon)) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -387,23 +381,6 @@ static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream,
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void monitor_user_noop(Monitor *mon, const QObject *data) { }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int handler_is_qobject(const mon_cmd_t *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return cmd->user_print != NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline bool handler_is_async(const mon_cmd_t *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return cmd->flags & MONITOR_CMD_ASYNC;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int monitor_has_error(const Monitor *mon)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return mon->error != NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void monitor_json_emitter(Monitor *mon, const QObject *data)
 | 
					static void monitor_json_emitter(Monitor *mon, const QObject *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QString *json;
 | 
					    QString *json;
 | 
				
			||||||
@ -418,24 +395,25 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data)
 | 
				
			|||||||
    QDECREF(json);
 | 
					    QDECREF(json);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static QDict *build_qmp_error_dict(const QError *err)
 | 
					static QDict *build_qmp_error_dict(Error *err)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QObject *obj;
 | 
					    QObject *obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %p } }",
 | 
					    obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %s } }",
 | 
				
			||||||
                             ErrorClass_lookup[err->err_class],
 | 
					                             ErrorClass_lookup[error_get_class(err)],
 | 
				
			||||||
                             qerror_human(err));
 | 
					                             error_get_pretty(err));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return qobject_to_qdict(obj);
 | 
					    return qobject_to_qdict(obj);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void monitor_protocol_emitter(Monitor *mon, QObject *data)
 | 
					static void monitor_protocol_emitter(Monitor *mon, QObject *data,
 | 
				
			||||||
 | 
					                                     Error *err)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QDict *qmp;
 | 
					    QDict *qmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_monitor_protocol_emitter(mon);
 | 
					    trace_monitor_protocol_emitter(mon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!monitor_has_error(mon)) {
 | 
					    if (!err) {
 | 
				
			||||||
        /* success response */
 | 
					        /* success response */
 | 
				
			||||||
        qmp = qdict_new();
 | 
					        qmp = qdict_new();
 | 
				
			||||||
        if (data) {
 | 
					        if (data) {
 | 
				
			||||||
@ -447,14 +425,12 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        /* error response */
 | 
					        /* error response */
 | 
				
			||||||
        qmp = build_qmp_error_dict(mon->error);
 | 
					        qmp = build_qmp_error_dict(err);
 | 
				
			||||||
        QDECREF(mon->error);
 | 
					 | 
				
			||||||
        mon->error = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (mon->mc->id) {
 | 
					    if (mon->qmp.id) {
 | 
				
			||||||
        qdict_put_obj(qmp, "id", mon->mc->id);
 | 
					        qdict_put_obj(qmp, "id", mon->qmp.id);
 | 
				
			||||||
        mon->mc->id = NULL;
 | 
					        mon->qmp.id = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monitor_json_emitter(mon, QOBJECT(qmp));
 | 
					    monitor_json_emitter(mon, QOBJECT(qmp));
 | 
				
			||||||
@ -474,7 +450,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QObject *data)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    trace_monitor_protocol_event_emit(event, data);
 | 
					    trace_monitor_protocol_event_emit(event, data);
 | 
				
			||||||
    QLIST_FOREACH(mon, &mon_list, entry) {
 | 
					    QLIST_FOREACH(mon, &mon_list, entry) {
 | 
				
			||||||
        if (monitor_ctrl_mode(mon) && qmp_cmd_mode(mon)) {
 | 
					        if (monitor_is_qmp(mon) && mon->qmp.in_command_mode) {
 | 
				
			||||||
            monitor_json_emitter(mon, data);
 | 
					            monitor_json_emitter(mon, data);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -594,15 +570,11 @@ static void monitor_qapi_event_init(void)
 | 
				
			|||||||
static int do_qmp_capabilities(Monitor *mon, const QDict *params,
 | 
					static int do_qmp_capabilities(Monitor *mon, const QDict *params,
 | 
				
			||||||
                               QObject **ret_data)
 | 
					                               QObject **ret_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Will setup QMP capabilities in the future */
 | 
					    mon->qmp.in_command_mode = true;
 | 
				
			||||||
    if (monitor_ctrl_mode(mon)) {
 | 
					 | 
				
			||||||
        mon->mc->command_mode = 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_user_command(Monitor *mon, const char *cmdline);
 | 
					static void handle_hmp_command(Monitor *mon, const char *cmdline);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void monitor_data_init(Monitor *mon)
 | 
					static void monitor_data_init(Monitor *mon)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -641,7 +613,7 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handle_user_command(&hmp, command_line);
 | 
					    handle_hmp_command(&hmp, command_line);
 | 
				
			||||||
    cur_mon = old_mon;
 | 
					    cur_mon = old_mon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_mutex_lock(&hmp.out_lock);
 | 
					    qemu_mutex_lock(&hmp.out_lock);
 | 
				
			||||||
@ -917,45 +889,6 @@ static void hmp_trace_file(Monitor *mon, const QDict *qdict)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void user_monitor_complete(void *opaque, QObject *ret_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    MonitorCompletionData *data = (MonitorCompletionData *)opaque; 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (ret_data) {
 | 
					 | 
				
			||||||
        data->user_print(data->mon, ret_data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    monitor_resume(data->mon);
 | 
					 | 
				
			||||||
    g_free(data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void qmp_monitor_complete(void *opaque, QObject *ret_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    monitor_protocol_emitter(opaque, ret_data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int qmp_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd,
 | 
					 | 
				
			||||||
                                 const QDict *params)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return cmd->mhandler.cmd_async(mon, params, qmp_monitor_complete, mon);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd,
 | 
					 | 
				
			||||||
                                   const QDict *params)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    MonitorCompletionData *cb_data = g_malloc(sizeof(*cb_data));
 | 
					 | 
				
			||||||
    cb_data->mon = mon;
 | 
					 | 
				
			||||||
    cb_data->user_print = cmd->user_print;
 | 
					 | 
				
			||||||
    monitor_suspend(mon);
 | 
					 | 
				
			||||||
    ret = cmd->mhandler.cmd_async(mon, params,
 | 
					 | 
				
			||||||
                                  user_monitor_complete, cb_data);
 | 
					 | 
				
			||||||
    if (ret < 0) {
 | 
					 | 
				
			||||||
        monitor_resume(mon);
 | 
					 | 
				
			||||||
        g_free(cb_data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void hmp_info_help(Monitor *mon, const QDict *qdict)
 | 
					static void hmp_info_help(Monitor *mon, const QDict *qdict)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    help_cmd(mon, "info");
 | 
					    help_cmd(mon, "info");
 | 
				
			||||||
@ -1085,39 +1018,33 @@ static void hmp_info_trace_events(Monitor *mon, const QDict *qdict)
 | 
				
			|||||||
    qapi_free_TraceEventInfoList(events);
 | 
					    qapi_free_TraceEventInfoList(events);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int client_migrate_info(Monitor *mon, const QDict *qdict,
 | 
					void qmp_client_migrate_info(const char *protocol, const char *hostname,
 | 
				
			||||||
                               QObject **ret_data)
 | 
					                             bool has_port, int64_t port,
 | 
				
			||||||
 | 
					                             bool has_tls_port, int64_t tls_port,
 | 
				
			||||||
 | 
					                             bool has_cert_subject, const char *cert_subject,
 | 
				
			||||||
 | 
					                             Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const char *protocol = qdict_get_str(qdict, "protocol");
 | 
					 | 
				
			||||||
    const char *hostname = qdict_get_str(qdict, "hostname");
 | 
					 | 
				
			||||||
    const char *subject  = qdict_get_try_str(qdict, "cert-subject");
 | 
					 | 
				
			||||||
    int port             = qdict_get_try_int(qdict, "port", -1);
 | 
					 | 
				
			||||||
    int tls_port         = qdict_get_try_int(qdict, "tls-port", -1);
 | 
					 | 
				
			||||||
    Error *err = NULL;
 | 
					 | 
				
			||||||
    int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (strcmp(protocol, "spice") == 0) {
 | 
					    if (strcmp(protocol, "spice") == 0) {
 | 
				
			||||||
        if (!qemu_using_spice(&err)) {
 | 
					        if (!qemu_using_spice(errp)) {
 | 
				
			||||||
            qerror_report_err(err);
 | 
					            return;
 | 
				
			||||||
            error_free(err);
 | 
					 | 
				
			||||||
            return -1;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (port == -1 && tls_port == -1) {
 | 
					        if (!has_port && !has_tls_port) {
 | 
				
			||||||
            qerror_report(QERR_MISSING_PARAMETER, "port/tls-port");
 | 
					            error_set(errp, QERR_MISSING_PARAMETER, "port/tls-port");
 | 
				
			||||||
            return -1;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ret = qemu_spice_migrate_info(hostname, port, tls_port, subject);
 | 
					        if (qemu_spice_migrate_info(hostname,
 | 
				
			||||||
        if (ret != 0) {
 | 
					                                    has_port ? port : -1,
 | 
				
			||||||
            qerror_report(QERR_UNDEFINED_ERROR);
 | 
					                                    has_tls_port ? tls_port : -1,
 | 
				
			||||||
            return -1;
 | 
					                                    cert_subject)) {
 | 
				
			||||||
 | 
					            error_set(errp, QERR_UNDEFINED_ERROR);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return 0;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qerror_report(QERR_INVALID_PARAMETER, "protocol");
 | 
					    error_set(errp, QERR_INVALID_PARAMETER_VALUE, "protocol", "spice");
 | 
				
			||||||
    return -1;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void hmp_logfile(Monitor *mon, const QDict *qdict)
 | 
					static void hmp_logfile(Monitor *mon, const QDict *qdict)
 | 
				
			||||||
@ -4098,19 +4025,7 @@ void monitor_set_error(Monitor *mon, QError *qerror)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret)
 | 
					static void handle_hmp_command(Monitor *mon, const char *cmdline)
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (ret && !monitor_has_error(mon)) {
 | 
					 | 
				
			||||||
        /*
 | 
					 | 
				
			||||||
         * If it returns failure, it must have passed on error.
 | 
					 | 
				
			||||||
         *
 | 
					 | 
				
			||||||
         * Action: Report an internal error to the client if in QMP.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        qerror_report(QERR_UNDEFINED_ERROR);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void handle_user_command(Monitor *mon, const char *cmdline)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QDict *qdict;
 | 
					    QDict *qdict;
 | 
				
			||||||
    const mon_cmd_t *cmd;
 | 
					    const mon_cmd_t *cmd;
 | 
				
			||||||
@ -4118,26 +4033,10 @@ static void handle_user_command(Monitor *mon, const char *cmdline)
 | 
				
			|||||||
    qdict = qdict_new();
 | 
					    qdict = qdict_new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cmd = monitor_parse_command(mon, cmdline, 0, mon->cmd_table, qdict);
 | 
					    cmd = monitor_parse_command(mon, cmdline, 0, mon->cmd_table, qdict);
 | 
				
			||||||
    if (!cmd)
 | 
					    if (cmd) {
 | 
				
			||||||
        goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (handler_is_async(cmd)) {
 | 
					 | 
				
			||||||
        user_async_cmd_handler(mon, cmd, qdict);
 | 
					 | 
				
			||||||
    } else if (handler_is_qobject(cmd)) {
 | 
					 | 
				
			||||||
        QObject *data = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* XXX: ignores the error code */
 | 
					 | 
				
			||||||
        cmd->mhandler.cmd_new(mon, qdict, &data);
 | 
					 | 
				
			||||||
        assert(!monitor_has_error(mon));
 | 
					 | 
				
			||||||
        if (data) {
 | 
					 | 
				
			||||||
            cmd->user_print(mon, data);
 | 
					 | 
				
			||||||
            qobject_decref(data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        cmd->mhandler.cmd(mon, qdict);
 | 
					        cmd->mhandler.cmd(mon, qdict);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
    QDECREF(qdict);
 | 
					    QDECREF(qdict);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4803,19 +4702,21 @@ static int monitor_can_read(void *opaque)
 | 
				
			|||||||
    return (mon->suspend_cnt == 0) ? 1 : 0;
 | 
					    return (mon->suspend_cnt == 0) ? 1 : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd)
 | 
					static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd,
 | 
				
			||||||
 | 
					                             Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bool is_cap = cmd->mhandler.cmd_new == do_qmp_capabilities;
 | 
					    bool is_cap = cmd->mhandler.cmd_new == do_qmp_capabilities;
 | 
				
			||||||
    if (is_cap && qmp_cmd_mode(mon)) {
 | 
					
 | 
				
			||||||
        qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND,
 | 
					    if (is_cap && mon->qmp.in_command_mode) {
 | 
				
			||||||
                      "Capabilities negotiation is already complete, command "
 | 
					        error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
 | 
				
			||||||
                      "'%s' ignored", cmd->name);
 | 
					                  "Capabilities negotiation is already complete, command "
 | 
				
			||||||
 | 
					                  "'%s' ignored", cmd->name);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!is_cap && !qmp_cmd_mode(mon)) {
 | 
					    if (!is_cap && !mon->qmp.in_command_mode) {
 | 
				
			||||||
        qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND,
 | 
					        error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
 | 
				
			||||||
                      "Expecting capabilities negotiation with "
 | 
					                  "Expecting capabilities negotiation with "
 | 
				
			||||||
                      "'qmp_capabilities' before command '%s'", cmd->name);
 | 
					                  "'qmp_capabilities' before command '%s'", cmd->name);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
@ -4831,8 +4732,9 @@ static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd)
 | 
				
			|||||||
 *               the QMP_ACCEPT_UNKNOWNS flag is set, then the
 | 
					 *               the QMP_ACCEPT_UNKNOWNS flag is set, then the
 | 
				
			||||||
 *               checking is skipped for it.
 | 
					 *               checking is skipped for it.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int check_client_args_type(const QDict *client_args,
 | 
					static void check_client_args_type(const QDict *client_args,
 | 
				
			||||||
                                  const QDict *cmd_args, int flags)
 | 
					                                   const QDict *cmd_args, int flags,
 | 
				
			||||||
 | 
					                                   Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const QDictEntry *ent;
 | 
					    const QDictEntry *ent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4849,8 +4751,8 @@ static int check_client_args_type(const QDict *client_args,
 | 
				
			|||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            /* client arg doesn't exist */
 | 
					            /* client arg doesn't exist */
 | 
				
			||||||
            qerror_report(QERR_INVALID_PARAMETER, client_arg_name);
 | 
					            error_set(errp, QERR_INVALID_PARAMETER, client_arg_name);
 | 
				
			||||||
            return -1;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        arg_type = qobject_to_qstring(obj);
 | 
					        arg_type = qobject_to_qstring(obj);
 | 
				
			||||||
@ -4862,9 +4764,9 @@ static int check_client_args_type(const QDict *client_args,
 | 
				
			|||||||
        case 'B':
 | 
					        case 'B':
 | 
				
			||||||
        case 's':
 | 
					        case 's':
 | 
				
			||||||
            if (qobject_type(client_arg) != QTYPE_QSTRING) {
 | 
					            if (qobject_type(client_arg) != QTYPE_QSTRING) {
 | 
				
			||||||
                qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
 | 
					                error_set(errp, QERR_INVALID_PARAMETER_TYPE,
 | 
				
			||||||
                              "string");
 | 
					                          client_arg_name, "string");
 | 
				
			||||||
                return -1;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
        case 'i':
 | 
					        case 'i':
 | 
				
			||||||
@ -4872,25 +4774,25 @@ static int check_client_args_type(const QDict *client_args,
 | 
				
			|||||||
        case 'M':
 | 
					        case 'M':
 | 
				
			||||||
        case 'o':
 | 
					        case 'o':
 | 
				
			||||||
            if (qobject_type(client_arg) != QTYPE_QINT) {
 | 
					            if (qobject_type(client_arg) != QTYPE_QINT) {
 | 
				
			||||||
                qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
 | 
					                error_set(errp, QERR_INVALID_PARAMETER_TYPE,
 | 
				
			||||||
                              "int");
 | 
					                          client_arg_name, "int");
 | 
				
			||||||
                return -1; 
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 'T':
 | 
					        case 'T':
 | 
				
			||||||
            if (qobject_type(client_arg) != QTYPE_QINT &&
 | 
					            if (qobject_type(client_arg) != QTYPE_QINT &&
 | 
				
			||||||
                qobject_type(client_arg) != QTYPE_QFLOAT) {
 | 
					                qobject_type(client_arg) != QTYPE_QFLOAT) {
 | 
				
			||||||
                qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
 | 
					                error_set(errp, QERR_INVALID_PARAMETER_TYPE,
 | 
				
			||||||
                              "number");
 | 
					                          client_arg_name, "number");
 | 
				
			||||||
               return -1; 
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 'b':
 | 
					        case 'b':
 | 
				
			||||||
        case '-':
 | 
					        case '-':
 | 
				
			||||||
            if (qobject_type(client_arg) != QTYPE_QBOOL) {
 | 
					            if (qobject_type(client_arg) != QTYPE_QBOOL) {
 | 
				
			||||||
                qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
 | 
					                error_set(errp, QERR_INVALID_PARAMETER_TYPE,
 | 
				
			||||||
                              "bool");
 | 
					                          client_arg_name, "bool");
 | 
				
			||||||
               return -1; 
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 'O':
 | 
					        case 'O':
 | 
				
			||||||
@ -4909,16 +4811,15 @@ static int check_client_args_type(const QDict *client_args,
 | 
				
			|||||||
            abort();
 | 
					            abort();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * - Check if the client has passed all mandatory args
 | 
					 * - Check if the client has passed all mandatory args
 | 
				
			||||||
 * - Set special flags for argument validation
 | 
					 * - Set special flags for argument validation
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int check_mandatory_args(const QDict *cmd_args,
 | 
					static void check_mandatory_args(const QDict *cmd_args,
 | 
				
			||||||
                                const QDict *client_args, int *flags)
 | 
					                                 const QDict *client_args, int *flags,
 | 
				
			||||||
 | 
					                                 Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const QDictEntry *ent;
 | 
					    const QDictEntry *ent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4933,12 +4834,10 @@ static int check_mandatory_args(const QDict *cmd_args,
 | 
				
			|||||||
        } else if (qstring_get_str(type)[0] != '-' &&
 | 
					        } else if (qstring_get_str(type)[0] != '-' &&
 | 
				
			||||||
                   qstring_get_str(type)[1] != '?' &&
 | 
					                   qstring_get_str(type)[1] != '?' &&
 | 
				
			||||||
                   !qdict_haskey(client_args, cmd_arg_name)) {
 | 
					                   !qdict_haskey(client_args, cmd_arg_name)) {
 | 
				
			||||||
            qerror_report(QERR_MISSING_PARAMETER, cmd_arg_name);
 | 
					            error_set(errp, QERR_MISSING_PARAMETER, cmd_arg_name);
 | 
				
			||||||
            return -1;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static QDict *qdict_from_args_type(const char *args_type)
 | 
					static QDict *qdict_from_args_type(const char *args_type)
 | 
				
			||||||
@ -4994,24 +4893,26 @@ out:
 | 
				
			|||||||
 * 3. Each argument provided by the client must have the type expected
 | 
					 * 3. Each argument provided by the client must have the type expected
 | 
				
			||||||
 *    by the command
 | 
					 *    by the command
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args)
 | 
					static void qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args,
 | 
				
			||||||
 | 
					                                  Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int flags, err;
 | 
					    Error *err = NULL;
 | 
				
			||||||
 | 
					    int flags;
 | 
				
			||||||
    QDict *cmd_args;
 | 
					    QDict *cmd_args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cmd_args = qdict_from_args_type(cmd->args_type);
 | 
					    cmd_args = qdict_from_args_type(cmd->args_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flags = 0;
 | 
					    flags = 0;
 | 
				
			||||||
    err = check_mandatory_args(cmd_args, client_args, &flags);
 | 
					    check_mandatory_args(cmd_args, client_args, &flags, &err);
 | 
				
			||||||
    if (err) {
 | 
					    if (err) {
 | 
				
			||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    err = check_client_args_type(client_args, cmd_args, flags);
 | 
					    check_client_args_type(client_args, cmd_args, flags, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
 | 
					    error_propagate(errp, err);
 | 
				
			||||||
    QDECREF(cmd_args);
 | 
					    QDECREF(cmd_args);
 | 
				
			||||||
    return err;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@ -5024,14 +4925,14 @@ out:
 | 
				
			|||||||
 * 5. If the "id" key exists, it can be anything (ie. json-value)
 | 
					 * 5. If the "id" key exists, it can be anything (ie. json-value)
 | 
				
			||||||
 * 6. Any argument not listed above is considered invalid
 | 
					 * 6. Any argument not listed above is considered invalid
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static QDict *qmp_check_input_obj(QObject *input_obj)
 | 
					static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const QDictEntry *ent;
 | 
					    const QDictEntry *ent;
 | 
				
			||||||
    int has_exec_key = 0;
 | 
					    int has_exec_key = 0;
 | 
				
			||||||
    QDict *input_dict;
 | 
					    QDict *input_dict;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (qobject_type(input_obj) != QTYPE_QDICT) {
 | 
					    if (qobject_type(input_obj) != QTYPE_QDICT) {
 | 
				
			||||||
        qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "object");
 | 
					        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "object");
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5043,81 +4944,68 @@ static QDict *qmp_check_input_obj(QObject *input_obj)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (!strcmp(arg_name, "execute")) {
 | 
					        if (!strcmp(arg_name, "execute")) {
 | 
				
			||||||
            if (qobject_type(arg_obj) != QTYPE_QSTRING) {
 | 
					            if (qobject_type(arg_obj) != QTYPE_QSTRING) {
 | 
				
			||||||
                qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
 | 
					                error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
 | 
				
			||||||
                              "string");
 | 
					                          "execute", "string");
 | 
				
			||||||
                return NULL;
 | 
					                return NULL;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            has_exec_key = 1;
 | 
					            has_exec_key = 1;
 | 
				
			||||||
        } else if (!strcmp(arg_name, "arguments")) {
 | 
					        } else if (!strcmp(arg_name, "arguments")) {
 | 
				
			||||||
            if (qobject_type(arg_obj) != QTYPE_QDICT) {
 | 
					            if (qobject_type(arg_obj) != QTYPE_QDICT) {
 | 
				
			||||||
                qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "arguments",
 | 
					                error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER,
 | 
				
			||||||
                              "object");
 | 
					                          "arguments", "object");
 | 
				
			||||||
                return NULL;
 | 
					                return NULL;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else if (!strcmp(arg_name, "id")) {
 | 
					 | 
				
			||||||
            /* FIXME: check duplicated IDs for async commands */
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            qerror_report(QERR_QMP_EXTRA_MEMBER, arg_name);
 | 
					            error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
 | 
				
			||||||
            return NULL;
 | 
					            return NULL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!has_exec_key) {
 | 
					    if (!has_exec_key) {
 | 
				
			||||||
        qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute");
 | 
					        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return input_dict;
 | 
					    return input_dict;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd,
 | 
					 | 
				
			||||||
                         const QDict *params)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int ret;
 | 
					 | 
				
			||||||
    QObject *data = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ret = cmd->mhandler.cmd_new(mon, params, &data);
 | 
					 | 
				
			||||||
    handler_audit(mon, cmd, ret);
 | 
					 | 
				
			||||||
    monitor_protocol_emitter(mon, data);
 | 
					 | 
				
			||||||
    qobject_decref(data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
 | 
					static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int err;
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
    QObject *obj;
 | 
					    QObject *obj, *data;
 | 
				
			||||||
    QDict *input, *args;
 | 
					    QDict *input, *args;
 | 
				
			||||||
    const mon_cmd_t *cmd;
 | 
					    const mon_cmd_t *cmd;
 | 
				
			||||||
    const char *cmd_name;
 | 
					    const char *cmd_name;
 | 
				
			||||||
    Monitor *mon = cur_mon;
 | 
					    Monitor *mon = cur_mon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    args = input = NULL;
 | 
					    args = input = NULL;
 | 
				
			||||||
 | 
					    data = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    obj = json_parser_parse(tokens, NULL);
 | 
					    obj = json_parser_parse(tokens, NULL);
 | 
				
			||||||
    if (!obj) {
 | 
					    if (!obj) {
 | 
				
			||||||
        // FIXME: should be triggered in json_parser_parse()
 | 
					        // FIXME: should be triggered in json_parser_parse()
 | 
				
			||||||
        qerror_report(QERR_JSON_PARSING);
 | 
					        error_set(&local_err, QERR_JSON_PARSING);
 | 
				
			||||||
        goto err_out;
 | 
					        goto err_out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    input = qmp_check_input_obj(obj);
 | 
					    input = qmp_check_input_obj(obj, &local_err);
 | 
				
			||||||
    if (!input) {
 | 
					    if (!input) {
 | 
				
			||||||
        qobject_decref(obj);
 | 
					        qobject_decref(obj);
 | 
				
			||||||
        goto err_out;
 | 
					        goto err_out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mon->mc->id = qdict_get(input, "id");
 | 
					    mon->qmp.id = qdict_get(input, "id");
 | 
				
			||||||
    qobject_incref(mon->mc->id);
 | 
					    qobject_incref(mon->qmp.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cmd_name = qdict_get_str(input, "execute");
 | 
					    cmd_name = qdict_get_str(input, "execute");
 | 
				
			||||||
    trace_handle_qmp_command(mon, cmd_name);
 | 
					    trace_handle_qmp_command(mon, cmd_name);
 | 
				
			||||||
    cmd = qmp_find_cmd(cmd_name);
 | 
					    cmd = qmp_find_cmd(cmd_name);
 | 
				
			||||||
    if (!cmd) {
 | 
					    if (!cmd) {
 | 
				
			||||||
        qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND,
 | 
					        error_set(&local_err, ERROR_CLASS_COMMAND_NOT_FOUND,
 | 
				
			||||||
                      "The command %s has not been found", cmd_name);
 | 
					                  "The command %s has not been found", cmd_name);
 | 
				
			||||||
        goto err_out;
 | 
					        goto err_out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (invalid_qmp_mode(mon, cmd)) {
 | 
					    if (invalid_qmp_mode(mon, cmd, &local_err)) {
 | 
				
			||||||
        goto err_out;
 | 
					        goto err_out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5129,40 +5017,39 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
 | 
				
			|||||||
        QINCREF(args);
 | 
					        QINCREF(args);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    err = qmp_check_client_args(cmd, args);
 | 
					    qmp_check_client_args(cmd, args, &local_err);
 | 
				
			||||||
    if (err < 0) {
 | 
					    if (local_err) {
 | 
				
			||||||
        goto err_out;
 | 
					        goto err_out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (handler_is_async(cmd)) {
 | 
					    if (cmd->mhandler.cmd_new(mon, args, &data)) {
 | 
				
			||||||
        err = qmp_async_cmd_handler(mon, cmd, args);
 | 
					        /* Command failed... */
 | 
				
			||||||
        if (err) {
 | 
					        if (!mon->error) {
 | 
				
			||||||
            /* emit the error response */
 | 
					            /* ... without setting an error, so make one up */
 | 
				
			||||||
            goto err_out;
 | 
					            error_set(&local_err, QERR_UNDEFINED_ERROR);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    }
 | 
				
			||||||
        qmp_call_cmd(mon, cmd, args);
 | 
					    if (mon->error) {
 | 
				
			||||||
 | 
					        error_set(&local_err, mon->error->err_class, "%s",
 | 
				
			||||||
 | 
					                  mon->error->err_msg);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
err_out:
 | 
					err_out:
 | 
				
			||||||
    monitor_protocol_emitter(mon, NULL);
 | 
					    monitor_protocol_emitter(mon, data, local_err);
 | 
				
			||||||
out:
 | 
					    qobject_decref(data);
 | 
				
			||||||
 | 
					    QDECREF(mon->error);
 | 
				
			||||||
 | 
					    mon->error = NULL;
 | 
				
			||||||
    QDECREF(input);
 | 
					    QDECREF(input);
 | 
				
			||||||
    QDECREF(args);
 | 
					    QDECREF(args);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			||||||
 * monitor_control_read(): Read and handle QMP input
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void monitor_control_read(void *opaque, const uint8_t *buf, int size)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Monitor *old_mon = cur_mon;
 | 
					    Monitor *old_mon = cur_mon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cur_mon = opaque;
 | 
					    cur_mon = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    json_message_parser_feed(&cur_mon->mc->parser, (const char *) buf, size);
 | 
					    json_message_parser_feed(&cur_mon->qmp.parser, (const char *) buf, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cur_mon = old_mon;
 | 
					    cur_mon = old_mon;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -5181,7 +5068,7 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			|||||||
        if (size == 0 || buf[size - 1] != 0)
 | 
					        if (size == 0 || buf[size - 1] != 0)
 | 
				
			||||||
            monitor_printf(cur_mon, "corrupted command\n");
 | 
					            monitor_printf(cur_mon, "corrupted command\n");
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            handle_user_command(cur_mon, (char *)buf);
 | 
					            handle_hmp_command(cur_mon, (char *)buf);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cur_mon = old_mon;
 | 
					    cur_mon = old_mon;
 | 
				
			||||||
@ -5193,7 +5080,7 @@ static void monitor_command_cb(void *opaque, const char *cmdline,
 | 
				
			|||||||
    Monitor *mon = opaque;
 | 
					    Monitor *mon = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monitor_suspend(mon);
 | 
					    monitor_suspend(mon);
 | 
				
			||||||
    handle_user_command(mon, cmdline);
 | 
					    handle_hmp_command(mon, cmdline);
 | 
				
			||||||
    monitor_resume(mon);
 | 
					    monitor_resume(mon);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5221,25 +5108,22 @@ static QObject *get_qmp_greeting(void)
 | 
				
			|||||||
    return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': []}}",ver);
 | 
					    return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': []}}",ver);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					static void monitor_qmp_event(void *opaque, int event)
 | 
				
			||||||
 * monitor_control_event(): Print QMP gretting
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void monitor_control_event(void *opaque, int event)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QObject *data;
 | 
					    QObject *data;
 | 
				
			||||||
    Monitor *mon = opaque;
 | 
					    Monitor *mon = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (event) {
 | 
					    switch (event) {
 | 
				
			||||||
    case CHR_EVENT_OPENED:
 | 
					    case CHR_EVENT_OPENED:
 | 
				
			||||||
        mon->mc->command_mode = 0;
 | 
					        mon->qmp.in_command_mode = false;
 | 
				
			||||||
        data = get_qmp_greeting();
 | 
					        data = get_qmp_greeting();
 | 
				
			||||||
        monitor_json_emitter(mon, data);
 | 
					        monitor_json_emitter(mon, data);
 | 
				
			||||||
        qobject_decref(data);
 | 
					        qobject_decref(data);
 | 
				
			||||||
        mon_refcount++;
 | 
					        mon_refcount++;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case CHR_EVENT_CLOSED:
 | 
					    case CHR_EVENT_CLOSED:
 | 
				
			||||||
        json_message_parser_destroy(&mon->mc->parser);
 | 
					        json_message_parser_destroy(&mon->qmp.parser);
 | 
				
			||||||
        json_message_parser_init(&mon->mc->parser, handle_qmp_command);
 | 
					        json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
 | 
				
			||||||
        mon_refcount--;
 | 
					        mon_refcount--;
 | 
				
			||||||
        monitor_fdsets_cleanup();
 | 
					        monitor_fdsets_cleanup();
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -5371,14 +5255,11 @@ void monitor_init(CharDriverState *chr, int flags)
 | 
				
			|||||||
        monitor_read_command(mon, 0);
 | 
					        monitor_read_command(mon, 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (monitor_ctrl_mode(mon)) {
 | 
					    if (monitor_is_qmp(mon)) {
 | 
				
			||||||
        mon->mc = g_malloc0(sizeof(MonitorControl));
 | 
					        qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read,
 | 
				
			||||||
        /* Control mode requires special handlers */
 | 
					                              monitor_qmp_event, mon);
 | 
				
			||||||
        qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
 | 
					 | 
				
			||||||
                              monitor_control_event, mon);
 | 
					 | 
				
			||||||
        qemu_chr_fe_set_echo(chr, true);
 | 
					        qemu_chr_fe_set_echo(chr, true);
 | 
				
			||||||
 | 
					        json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
 | 
				
			||||||
        json_message_parser_init(&mon->mc->parser, handle_qmp_command);
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
 | 
					        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
 | 
				
			||||||
                              monitor_event, mon);
 | 
					                              monitor_event, mon);
 | 
				
			||||||
 | 
				
			|||||||
@ -637,6 +637,25 @@
 | 
				
			|||||||
{ 'command': 'query-migrate-parameters',
 | 
					{ 'command': 'query-migrate-parameters',
 | 
				
			||||||
  'returns': 'MigrationParameters' }
 | 
					  'returns': 'MigrationParameters' }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					# @client_migrate_info
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Set migration information for remote display.  This makes the server
 | 
				
			||||||
 | 
					# ask the client to automatically reconnect using the new parameters
 | 
				
			||||||
 | 
					# once migration finished successfully.  Only implemented for SPICE.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# @protocol:     must be "spice"
 | 
				
			||||||
 | 
					# @hostname:     migration target hostname
 | 
				
			||||||
 | 
					# @port:         #optional spice tcp port for plaintext channels
 | 
				
			||||||
 | 
					# @tls-port:     #optional spice tcp port for tls-secured channels
 | 
				
			||||||
 | 
					# @cert-subject: #optional server certificate subject
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Since: 0.14.0
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					{ 'command': 'client_migrate_info',
 | 
				
			||||||
 | 
					  'data': { 'protocol': 'str', 'hostname': 'str', '*port': 'int',
 | 
				
			||||||
 | 
					            '*tls-port': 'int', '*cert-subject': 'str' } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
# @MouseInfo:
 | 
					# @MouseInfo:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
				
			|||||||
@ -784,23 +784,23 @@ EQMP
 | 
				
			|||||||
        .name       = "client_migrate_info",
 | 
					        .name       = "client_migrate_info",
 | 
				
			||||||
        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
 | 
					        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
 | 
				
			||||||
        .params     = "protocol hostname port tls-port cert-subject",
 | 
					        .params     = "protocol hostname port tls-port cert-subject",
 | 
				
			||||||
        .help       = "send migration info to spice/vnc client",
 | 
					        .help       = "set migration information for remote display",
 | 
				
			||||||
        .mhandler.cmd_new = client_migrate_info,
 | 
					        .mhandler.cmd_new = qmp_marshal_input_client_migrate_info,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SQMP
 | 
					SQMP
 | 
				
			||||||
client_migrate_info
 | 
					client_migrate_info
 | 
				
			||||||
------------------
 | 
					-------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Set the spice/vnc connection info for the migration target.  The spice/vnc
 | 
					Set migration information for remote display.  This makes the server
 | 
				
			||||||
server will ask the spice/vnc client to automatically reconnect using the
 | 
					ask the client to automatically reconnect using the new parameters
 | 
				
			||||||
new parameters (if specified) once the vm migration finished successfully.
 | 
					once migration finished successfully.  Only implemented for SPICE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Arguments:
 | 
					Arguments:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- "protocol":     protocol: "spice" or "vnc" (json-string)
 | 
					- "protocol":     must be "spice" (json-string)
 | 
				
			||||||
- "hostname":     migration target hostname (json-string)
 | 
					- "hostname":     migration target hostname (json-string)
 | 
				
			||||||
- "port":         spice/vnc tcp port for plaintext channels (json-int, optional)
 | 
					- "port":         spice tcp port for plaintext channels (json-int, optional)
 | 
				
			||||||
- "tls-port":     spice tcp port for tls-secured channels (json-int, optional)
 | 
					- "tls-port":     spice tcp port for tls-secured channels (json-int, optional)
 | 
				
			||||||
- "cert-subject": server certificate subject (json-string, optional)
 | 
					- "cert-subject": server certificate subject (json-string, optional)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
#include "qemu-common.h"
 | 
					#include "qemu-common.h"
 | 
				
			||||||
#include "monitor/monitor.h"
 | 
					#include "monitor/monitor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int monitor_cur_is_qmp(void)
 | 
					bool monitor_cur_is_qmp(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return 0;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user