qapi patches for 2018-03-27, 2.12-rc1
- Marc-André Lureau: qmp-test: fix response leak - Eric Blake: tests: Silence false positive warning on generated test name - Laurent Vivier: 0/4 (partial) coccinelle: re-run scripts from scripst/coccinelle - Peter Xu: 0/8 Monitor: some oob related patches (fixes, new param, tests) - Satheesh Rajendran: hmp.c: Revert hmp_info_cpus output format change -----BEGIN PGP SIGNATURE----- Comment: Public key at http://people.redhat.com/eblake/eblake.gpg iQEcBAABCAAGBQJaumDMAAoJEKeha0olJ0NqY34IAJ1AJLZeqtb9HIPDrL/iydXQ qrMPxfz/fbcjMbomYvltvCYB3GMQw88YVtTuu2kS5aZsr6vLhpw2ZjGrb+a0llFM lF6oERg/6VmfQNaeqcHEzORIdG6/GEctxoWS07f+NgSrjdxNNHyU+i/LGvvA5K4m x7akPw3DZIF/oBLDlFgtl80KtOf8vQ8QitCIp2nsURQFLHvjVSoXHGUfhoiUUgNA 89rF62Repq9xZXSsFr+Jpp4/bPGxA717sixXSxFUDuTVIZGnffbt4wVxLi4TKSx1 1Ho6psPK3d82rQ9OeIc6CqulElLMPGn7aNwR1VR6ig0sB409K5PQJybJDqQD/C4= =ld/c -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ericb/tags/pull-qapi-2018-03-27-v2' into staging qapi patches for 2018-03-27, 2.12-rc1 - Marc-André Lureau: qmp-test: fix response leak - Eric Blake: tests: Silence false positive warning on generated test name - Laurent Vivier: 0/4 (partial) coccinelle: re-run scripts from scripst/coccinelle - Peter Xu: 0/8 Monitor: some oob related patches (fixes, new param, tests) - Satheesh Rajendran: hmp.c: Revert hmp_info_cpus output format change # gpg: Signature made Tue 27 Mar 2018 16:18:36 BST # gpg: using RSA key A7A16B4A2527436A # gpg: Good signature from "Eric Blake <eblake@redhat.com>" # gpg: aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" # gpg: aka "[jpeg image of size 6874]" # Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2 F3AA A7A1 6B4A 2527 436A * remotes/ericb/tags/pull-qapi-2018-03-27-v2: hmp.c: Revert hmp_info_cpus output format change tests: qmp-test: add test for new "x-oob" tests: Add parameter to qtest_init_without_qmp_handshake monitor: new parameter "x-oob" qmp: cleanup qmp queues properly tests: add oob-test for qapi-schema tests: let qapi-schema tests detect oob qapi: restrict allow-oob value to be "true" qmp: fix qmp_capabilities error regression qdict: remove useless cast error: Remove NULL checks on error_propagate() calls error: Strip trailing '\n' from error string arguments (again again) tests: Silence false positive warning on generated test name qmp-test: fix response leak Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						f55e88f2ab
					
				
							
								
								
									
										11
									
								
								block/nvme.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								block/nvme.c
									
									
									
									
									
								
							@ -695,12 +695,11 @@ static void nvme_parse_filename(const char *filename, QDict *options,
 | 
				
			|||||||
        unsigned long ns;
 | 
					        unsigned long ns;
 | 
				
			||||||
        const char *slash = strchr(tmp, '/');
 | 
					        const char *slash = strchr(tmp, '/');
 | 
				
			||||||
        if (!slash) {
 | 
					        if (!slash) {
 | 
				
			||||||
            qdict_put(options, NVME_BLOCK_OPT_DEVICE,
 | 
					            qdict_put_str(options, NVME_BLOCK_OPT_DEVICE, tmp);
 | 
				
			||||||
                      qstring_from_str(tmp));
 | 
					 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        device = g_strndup(tmp, slash - tmp);
 | 
					        device = g_strndup(tmp, slash - tmp);
 | 
				
			||||||
        qdict_put(options, NVME_BLOCK_OPT_DEVICE, qstring_from_str(device));
 | 
					        qdict_put_str(options, NVME_BLOCK_OPT_DEVICE, device);
 | 
				
			||||||
        g_free(device);
 | 
					        g_free(device);
 | 
				
			||||||
        namespace = slash + 1;
 | 
					        namespace = slash + 1;
 | 
				
			||||||
        if (*namespace && qemu_strtoul(namespace, NULL, 10, &ns)) {
 | 
					        if (*namespace && qemu_strtoul(namespace, NULL, 10, &ns)) {
 | 
				
			||||||
@ -708,8 +707,8 @@ static void nvme_parse_filename(const char *filename, QDict *options,
 | 
				
			|||||||
                       namespace);
 | 
					                       namespace);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        qdict_put(options, NVME_BLOCK_OPT_NAMESPACE,
 | 
					        qdict_put_str(options, NVME_BLOCK_OPT_NAMESPACE,
 | 
				
			||||||
                  qstring_from_str(*namespace ? namespace : "1"));
 | 
					                      *namespace ? namespace : "1");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1082,7 +1081,7 @@ static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts)
 | 
				
			|||||||
                 bs->drv->format_name);
 | 
					                 bs->drv->format_name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qdict_put(opts, "driver", qstring_from_str(bs->drv->format_name));
 | 
					    qdict_put_str(opts, "driver", bs->drv->format_name);
 | 
				
			||||||
    bs->full_open_options = opts;
 | 
					    bs->full_open_options = opts;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								hmp.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								hmp.c
									
									
									
									
									
								
							@ -381,7 +381,7 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        monitor_printf(mon, "%c CPU #%" PRId64 ":", active,
 | 
					        monitor_printf(mon, "%c CPU #%" PRId64 ":", active,
 | 
				
			||||||
                       cpu->value->cpu_index);
 | 
					                       cpu->value->cpu_index);
 | 
				
			||||||
        monitor_printf(mon, " thread-id=%" PRId64 "\n", cpu->value->thread_id);
 | 
					        monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qapi_free_CpuInfoFastList(cpu_list);
 | 
					    qapi_free_CpuInfoFastList(cpu_list);
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,7 @@ extern Monitor *cur_mon;
 | 
				
			|||||||
#define MONITOR_USE_READLINE  0x02
 | 
					#define MONITOR_USE_READLINE  0x02
 | 
				
			||||||
#define MONITOR_USE_CONTROL   0x04
 | 
					#define MONITOR_USE_CONTROL   0x04
 | 
				
			||||||
#define MONITOR_USE_PRETTY    0x08
 | 
					#define MONITOR_USE_PRETTY    0x08
 | 
				
			||||||
 | 
					#define MONITOR_USE_OOB       0x10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool monitor_cur_is_qmp(void);
 | 
					bool monitor_cur_is_qmp(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -586,9 +586,7 @@ static gboolean qio_channel_websock_handshake_io(QIOChannel *ioc,
 | 
				
			|||||||
        return TRUE;
 | 
					        return TRUE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (err) {
 | 
					    error_propagate(&wioc->io_err, err);
 | 
				
			||||||
        error_propagate(&wioc->io_err, err);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_qio_channel_websock_handshake_reply(ioc);
 | 
					    trace_qio_channel_websock_handshake_reply(ioc);
 | 
				
			||||||
    qio_channel_add_watch(
 | 
					    qio_channel_add_watch(
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										118
									
								
								monitor.c
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								monitor.c
									
									
									
									
									
								
							@ -36,6 +36,7 @@
 | 
				
			|||||||
#include "net/slirp.h"
 | 
					#include "net/slirp.h"
 | 
				
			||||||
#include "chardev/char-fe.h"
 | 
					#include "chardev/char-fe.h"
 | 
				
			||||||
#include "chardev/char-io.h"
 | 
					#include "chardev/char-io.h"
 | 
				
			||||||
 | 
					#include "chardev/char-mux.h"
 | 
				
			||||||
#include "ui/qemu-spice.h"
 | 
					#include "ui/qemu-spice.h"
 | 
				
			||||||
#include "sysemu/numa.h"
 | 
					#include "sysemu/numa.h"
 | 
				
			||||||
#include "monitor/monitor.h"
 | 
					#include "monitor/monitor.h"
 | 
				
			||||||
@ -234,6 +235,22 @@ static struct {
 | 
				
			|||||||
    QEMUBH *qmp_respond_bh;
 | 
					    QEMUBH *qmp_respond_bh;
 | 
				
			||||||
} mon_global;
 | 
					} mon_global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct QMPRequest {
 | 
				
			||||||
 | 
					    /* Owner of the request */
 | 
				
			||||||
 | 
					    Monitor *mon;
 | 
				
			||||||
 | 
					    /* "id" field of the request */
 | 
				
			||||||
 | 
					    QObject *id;
 | 
				
			||||||
 | 
					    /* Request object to be handled */
 | 
				
			||||||
 | 
					    QObject *req;
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Whether we need to resume the monitor afterward.  This flag is
 | 
				
			||||||
 | 
					     * used to emulate the old QMP server behavior that the current
 | 
				
			||||||
 | 
					     * command must be completed before execution of the next one.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    bool need_resume;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					typedef struct QMPRequest QMPRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* QMP checker flags */
 | 
					/* QMP checker flags */
 | 
				
			||||||
#define QMP_ACCEPT_UNKNOWNS 1
 | 
					#define QMP_ACCEPT_UNKNOWNS 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -310,6 +327,38 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void qmp_request_free(QMPRequest *req)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    qobject_decref(req->id);
 | 
				
			||||||
 | 
					    qobject_decref(req->req);
 | 
				
			||||||
 | 
					    g_free(req);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Must with the mon->qmp.qmp_queue_lock held */
 | 
				
			||||||
 | 
					static void monitor_qmp_cleanup_req_queue_locked(Monitor *mon)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    while (!g_queue_is_empty(mon->qmp.qmp_requests)) {
 | 
				
			||||||
 | 
					        qmp_request_free(g_queue_pop_head(mon->qmp.qmp_requests));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Must with the mon->qmp.qmp_queue_lock held */
 | 
				
			||||||
 | 
					static void monitor_qmp_cleanup_resp_queue_locked(Monitor *mon)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    while (!g_queue_is_empty(mon->qmp.qmp_responses)) {
 | 
				
			||||||
 | 
					        qobject_decref(g_queue_pop_head(mon->qmp.qmp_responses));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void monitor_qmp_cleanup_queues(Monitor *mon)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    qemu_mutex_lock(&mon->qmp.qmp_queue_lock);
 | 
				
			||||||
 | 
					    monitor_qmp_cleanup_req_queue_locked(mon);
 | 
				
			||||||
 | 
					    monitor_qmp_cleanup_resp_queue_locked(mon);
 | 
				
			||||||
 | 
					    qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void monitor_flush_locked(Monitor *mon);
 | 
					static void monitor_flush_locked(Monitor *mon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
 | 
					static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
 | 
				
			||||||
@ -701,6 +750,8 @@ static void monitor_data_destroy(Monitor *mon)
 | 
				
			|||||||
    QDECREF(mon->outbuf);
 | 
					    QDECREF(mon->outbuf);
 | 
				
			||||||
    qemu_mutex_destroy(&mon->out_lock);
 | 
					    qemu_mutex_destroy(&mon->out_lock);
 | 
				
			||||||
    qemu_mutex_destroy(&mon->qmp.qmp_queue_lock);
 | 
					    qemu_mutex_destroy(&mon->qmp.qmp_queue_lock);
 | 
				
			||||||
 | 
					    monitor_qmp_cleanup_req_queue_locked(mon);
 | 
				
			||||||
 | 
					    monitor_qmp_cleanup_resp_queue_locked(mon);
 | 
				
			||||||
    g_queue_free(mon->qmp.qmp_requests);
 | 
					    g_queue_free(mon->qmp.qmp_requests);
 | 
				
			||||||
    g_queue_free(mon->qmp.qmp_responses);
 | 
					    g_queue_free(mon->qmp.qmp_responses);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1203,8 +1254,14 @@ static bool qmp_cmd_oob_check(Monitor *mon, QDict *req, Error **errp)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    cmd = qmp_find_command(mon->qmp.commands, command);
 | 
					    cmd = qmp_find_command(mon->qmp.commands, command);
 | 
				
			||||||
    if (!cmd) {
 | 
					    if (!cmd) {
 | 
				
			||||||
        error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
 | 
					        if (mon->qmp.commands == &qmp_cap_negotiation_commands) {
 | 
				
			||||||
                  "The command %s has not been found", command);
 | 
					            error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
 | 
				
			||||||
 | 
					                      "Expecting capabilities negotiation "
 | 
				
			||||||
 | 
					                      "with 'qmp_capabilities'");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
 | 
				
			||||||
 | 
					                      "The command %s has not been found", command);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4003,22 +4060,6 @@ static void monitor_qmp_respond(Monitor *mon, QObject *rsp,
 | 
				
			|||||||
    qobject_decref(rsp);
 | 
					    qobject_decref(rsp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct QMPRequest {
 | 
					 | 
				
			||||||
    /* Owner of the request */
 | 
					 | 
				
			||||||
    Monitor *mon;
 | 
					 | 
				
			||||||
    /* "id" field of the request */
 | 
					 | 
				
			||||||
    QObject *id;
 | 
					 | 
				
			||||||
    /* Request object to be handled */
 | 
					 | 
				
			||||||
    QObject *req;
 | 
					 | 
				
			||||||
    /*
 | 
					 | 
				
			||||||
     * Whether we need to resume the monitor afterward.  This flag is
 | 
					 | 
				
			||||||
     * used to emulate the old QMP server behavior that the current
 | 
					 | 
				
			||||||
     * command must be completed before execution of the next one.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    bool need_resume;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
typedef struct QMPRequest QMPRequest;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Dispatch one single QMP request. The function will free the req_obj
 | 
					 * Dispatch one single QMP request. The function will free the req_obj
 | 
				
			||||||
 * and objects inside it before return.
 | 
					 * and objects inside it before return.
 | 
				
			||||||
@ -4027,7 +4068,6 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    Monitor *mon, *old_mon;
 | 
					    Monitor *mon, *old_mon;
 | 
				
			||||||
    QObject *req, *rsp = NULL, *id;
 | 
					    QObject *req, *rsp = NULL, *id;
 | 
				
			||||||
    QDict *qdict = NULL;
 | 
					 | 
				
			||||||
    bool need_resume;
 | 
					    bool need_resume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    req = req_obj->req;
 | 
					    req = req_obj->req;
 | 
				
			||||||
@ -4050,18 +4090,6 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    cur_mon = old_mon;
 | 
					    cur_mon = old_mon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (mon->qmp.commands == &qmp_cap_negotiation_commands) {
 | 
					 | 
				
			||||||
        qdict = qdict_get_qdict(qobject_to(QDict, rsp), "error");
 | 
					 | 
				
			||||||
        if (qdict
 | 
					 | 
				
			||||||
            && !g_strcmp0(qdict_get_try_str(qdict, "class"),
 | 
					 | 
				
			||||||
                    QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) {
 | 
					 | 
				
			||||||
            /* Provide a more useful error message */
 | 
					 | 
				
			||||||
            qdict_del(qdict, "desc");
 | 
					 | 
				
			||||||
            qdict_put_str(qdict, "desc", "Expecting capabilities negotiation"
 | 
					 | 
				
			||||||
                          " with 'qmp_capabilities'");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Respond if necessary */
 | 
					    /* Respond if necessary */
 | 
				
			||||||
    monitor_qmp_respond(mon, rsp, NULL, id);
 | 
					    monitor_qmp_respond(mon, rsp, NULL, id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4198,9 +4226,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
 | 
				
			|||||||
            qapi_event_send_command_dropped(id,
 | 
					            qapi_event_send_command_dropped(id,
 | 
				
			||||||
                                            COMMAND_DROP_REASON_QUEUE_FULL,
 | 
					                                            COMMAND_DROP_REASON_QUEUE_FULL,
 | 
				
			||||||
                                            &error_abort);
 | 
					                                            &error_abort);
 | 
				
			||||||
            qobject_decref(id);
 | 
					            qmp_request_free(req_obj);
 | 
				
			||||||
            qobject_decref(req);
 | 
					 | 
				
			||||||
            g_free(req_obj);
 | 
					 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -4315,7 +4341,7 @@ static QObject *get_qmp_greeting(Monitor *mon)
 | 
				
			|||||||
            /* Monitors that are not using IOThread won't support OOB */
 | 
					            /* Monitors that are not using IOThread won't support OOB */
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        qlist_append(cap_list, qstring_from_str(QMPCapability_str(cap)));
 | 
					        qlist_append_str(cap_list, QMPCapability_str(cap));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return qobject_from_jsonf("{'QMP': {'version': %p, 'capabilities': %p}}",
 | 
					    return qobject_from_jsonf("{'QMP': {'version': %p, 'capabilities': %p}}",
 | 
				
			||||||
@ -4342,6 +4368,7 @@ static void monitor_qmp_event(void *opaque, int event)
 | 
				
			|||||||
        mon_refcount++;
 | 
					        mon_refcount++;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case CHR_EVENT_CLOSED:
 | 
					    case CHR_EVENT_CLOSED:
 | 
				
			||||||
 | 
					        monitor_qmp_cleanup_queues(mon);
 | 
				
			||||||
        json_message_parser_destroy(&mon->qmp.parser);
 | 
					        json_message_parser_destroy(&mon->qmp.parser);
 | 
				
			||||||
        json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
 | 
					        json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
 | 
				
			||||||
        mon_refcount--;
 | 
					        mon_refcount--;
 | 
				
			||||||
@ -4536,12 +4563,26 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
 | 
				
			|||||||
void monitor_init(Chardev *chr, int flags)
 | 
					void monitor_init(Chardev *chr, int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Monitor *mon = g_malloc(sizeof(*mon));
 | 
					    Monitor *mon = g_malloc(sizeof(*mon));
 | 
				
			||||||
 | 
					    bool use_readline = flags & MONITOR_USE_READLINE;
 | 
				
			||||||
 | 
					    bool use_oob = flags & MONITOR_USE_OOB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monitor_data_init(mon, false, false);
 | 
					    if (use_oob) {
 | 
				
			||||||
 | 
					        if (CHARDEV_IS_MUX(chr)) {
 | 
				
			||||||
 | 
					            error_report("Monitor Out-Of-Band is not supported with "
 | 
				
			||||||
 | 
					                         "MUX typed chardev backend");
 | 
				
			||||||
 | 
					            exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (use_readline) {
 | 
				
			||||||
 | 
					            error_report("Monitor Out-Of-band is only supported by QMP");
 | 
				
			||||||
 | 
					            exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    monitor_data_init(mon, false, use_oob);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_fe_init(&mon->chr, chr, &error_abort);
 | 
					    qemu_chr_fe_init(&mon->chr, chr, &error_abort);
 | 
				
			||||||
    mon->flags = flags;
 | 
					    mon->flags = flags;
 | 
				
			||||||
    if (flags & MONITOR_USE_READLINE) {
 | 
					    if (use_readline) {
 | 
				
			||||||
        mon->rs = readline_init(monitor_readline_printf,
 | 
					        mon->rs = readline_init(monitor_readline_printf,
 | 
				
			||||||
                                monitor_readline_flush,
 | 
					                                monitor_readline_flush,
 | 
				
			||||||
                                mon,
 | 
					                                mon,
 | 
				
			||||||
@ -4637,6 +4678,9 @@ QemuOptsList qemu_mon_opts = {
 | 
				
			|||||||
        },{
 | 
					        },{
 | 
				
			||||||
            .name = "pretty",
 | 
					            .name = "pretty",
 | 
				
			||||||
            .type = QEMU_OPT_BOOL,
 | 
					            .type = QEMU_OPT_BOOL,
 | 
				
			||||||
 | 
					        },{
 | 
				
			||||||
 | 
					            .name = "x-oob",
 | 
				
			||||||
 | 
					            .type = QEMU_OPT_BOOL,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        { /* end of list */ }
 | 
					        { /* end of list */ }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
				
			|||||||
@ -872,7 +872,7 @@ def check_keys(expr_elem, meta, required, optional=[]):
 | 
				
			|||||||
            raise QAPISemError(info,
 | 
					            raise QAPISemError(info,
 | 
				
			||||||
                               "'%s' of %s '%s' should only use false value"
 | 
					                               "'%s' of %s '%s' should only use false value"
 | 
				
			||||||
                               % (key, meta, name))
 | 
					                               % (key, meta, name))
 | 
				
			||||||
        if key == 'boxed' and value is not True:
 | 
					        if (key == 'boxed' or key == 'allow-oob') and value is not True:
 | 
				
			||||||
            raise QAPISemError(info,
 | 
					            raise QAPISemError(info,
 | 
				
			||||||
                               "'%s' of %s '%s' should only use true value"
 | 
					                               "'%s' of %s '%s' should only use true value"
 | 
				
			||||||
                               % (key, meta, name))
 | 
					                               % (key, meta, name))
 | 
				
			||||||
 | 
				
			|||||||
@ -86,25 +86,25 @@ static void assert_hvf_ok(hv_return_t ret)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    switch (ret) {
 | 
					    switch (ret) {
 | 
				
			||||||
    case HV_ERROR:
 | 
					    case HV_ERROR:
 | 
				
			||||||
        error_report("Error: HV_ERROR\n");
 | 
					        error_report("Error: HV_ERROR");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case HV_BUSY:
 | 
					    case HV_BUSY:
 | 
				
			||||||
        error_report("Error: HV_BUSY\n");
 | 
					        error_report("Error: HV_BUSY");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case HV_BAD_ARGUMENT:
 | 
					    case HV_BAD_ARGUMENT:
 | 
				
			||||||
        error_report("Error: HV_BAD_ARGUMENT\n");
 | 
					        error_report("Error: HV_BAD_ARGUMENT");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case HV_NO_RESOURCES:
 | 
					    case HV_NO_RESOURCES:
 | 
				
			||||||
        error_report("Error: HV_NO_RESOURCES\n");
 | 
					        error_report("Error: HV_NO_RESOURCES");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case HV_NO_DEVICE:
 | 
					    case HV_NO_DEVICE:
 | 
				
			||||||
        error_report("Error: HV_NO_DEVICE\n");
 | 
					        error_report("Error: HV_NO_DEVICE");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case HV_UNSUPPORTED:
 | 
					    case HV_UNSUPPORTED:
 | 
				
			||||||
        error_report("Error: HV_UNSUPPORTED\n");
 | 
					        error_report("Error: HV_UNSUPPORTED");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        error_report("Unknown Error\n");
 | 
					        error_report("Unknown Error");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    abort();
 | 
					    abort();
 | 
				
			||||||
@ -191,7 +191,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
 | 
				
			|||||||
    if (mem) {
 | 
					    if (mem) {
 | 
				
			||||||
        mem->size = 0;
 | 
					        mem->size = 0;
 | 
				
			||||||
        if (do_hvf_set_memory(mem)) {
 | 
					        if (do_hvf_set_memory(mem)) {
 | 
				
			||||||
            error_report("Failed to reset overlapping slot\n");
 | 
					            error_report("Failed to reset overlapping slot");
 | 
				
			||||||
            abort();
 | 
					            abort();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -211,7 +211,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (x == hvf_state->num_slots) {
 | 
					    if (x == hvf_state->num_slots) {
 | 
				
			||||||
        error_report("No free slots\n");
 | 
					        error_report("No free slots");
 | 
				
			||||||
        abort();
 | 
					        abort();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -221,7 +221,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
 | 
				
			|||||||
    mem->region = area;
 | 
					    mem->region = area;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (do_hvf_set_memory(mem)) {
 | 
					    if (do_hvf_set_memory(mem)) {
 | 
				
			||||||
        error_report("Error registering new memory slot\n");
 | 
					        error_report("Error registering new memory slot");
 | 
				
			||||||
        abort();
 | 
					        abort();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -884,7 +884,7 @@ int hvf_vcpu_exec(CPUState *cpu)
 | 
				
			|||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                error_report("Unrecognized CR %d\n", cr);
 | 
					                error_report("Unrecognized CR %d", cr);
 | 
				
			||||||
                abort();
 | 
					                abort();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            RIP(env) += ins_len;
 | 
					            RIP(env) += ins_len;
 | 
				
			||||||
@ -930,7 +930,7 @@ int hvf_vcpu_exec(CPUState *cpu)
 | 
				
			|||||||
            env->error_code = 0;
 | 
					            env->error_code = 0;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            error_report("%llx: unhandled exit %llx\n", rip, exit_reason);
 | 
					            error_report("%llx: unhandled exit %llx", rip, exit_reason);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } while (ret == 0);
 | 
					    } while (ret == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -523,6 +523,7 @@ qapi-schema += missing-comma-object.json
 | 
				
			|||||||
qapi-schema += missing-type.json
 | 
					qapi-schema += missing-type.json
 | 
				
			||||||
qapi-schema += nested-struct-data.json
 | 
					qapi-schema += nested-struct-data.json
 | 
				
			||||||
qapi-schema += non-objects.json
 | 
					qapi-schema += non-objects.json
 | 
				
			||||||
 | 
					qapi-schema += oob-test.json
 | 
				
			||||||
qapi-schema += pragma-doc-required-crap.json
 | 
					qapi-schema += pragma-doc-required-crap.json
 | 
				
			||||||
qapi-schema += pragma-extra-junk.json
 | 
					qapi-schema += pragma-extra-junk.json
 | 
				
			||||||
qapi-schema += pragma-name-case-whitelist-crap.json
 | 
					qapi-schema += pragma-name-case-whitelist-crap.json
 | 
				
			||||||
 | 
				
			|||||||
@ -166,7 +166,8 @@ static const char *qtest_qemu_binary(void)
 | 
				
			|||||||
    return qemu_bin;
 | 
					    return qemu_bin;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
 | 
					QTestState *qtest_init_without_qmp_handshake(bool use_oob,
 | 
				
			||||||
 | 
					                                             const char *extra_args)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QTestState *s;
 | 
					    QTestState *s;
 | 
				
			||||||
    int sock, qmpsock, i;
 | 
					    int sock, qmpsock, i;
 | 
				
			||||||
@ -199,12 +200,13 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
 | 
				
			|||||||
        command = g_strdup_printf("exec %s "
 | 
					        command = g_strdup_printf("exec %s "
 | 
				
			||||||
                                  "-qtest unix:%s,nowait "
 | 
					                                  "-qtest unix:%s,nowait "
 | 
				
			||||||
                                  "-qtest-log %s "
 | 
					                                  "-qtest-log %s "
 | 
				
			||||||
                                  "-qmp unix:%s,nowait "
 | 
					                                  "-chardev socket,path=%s,nowait,id=char0 "
 | 
				
			||||||
 | 
					                                  "-mon chardev=char0,mode=control%s "
 | 
				
			||||||
                                  "-machine accel=qtest "
 | 
					                                  "-machine accel=qtest "
 | 
				
			||||||
                                  "-display none "
 | 
					                                  "-display none "
 | 
				
			||||||
                                  "%s", qemu_binary, socket_path,
 | 
					                                  "%s", qemu_binary, socket_path,
 | 
				
			||||||
                                  getenv("QTEST_LOG") ? "/dev/fd/2" : "/dev/null",
 | 
					                                  getenv("QTEST_LOG") ? "/dev/fd/2" : "/dev/null",
 | 
				
			||||||
                                  qmp_socket_path,
 | 
					                                  qmp_socket_path, use_oob ? ",x-oob=on" : "",
 | 
				
			||||||
                                  extra_args ?: "");
 | 
					                                  extra_args ?: "");
 | 
				
			||||||
        execlp("/bin/sh", "sh", "-c", command, NULL);
 | 
					        execlp("/bin/sh", "sh", "-c", command, NULL);
 | 
				
			||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
@ -239,7 +241,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
QTestState *qtest_init(const char *extra_args)
 | 
					QTestState *qtest_init(const char *extra_args)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QTestState *s = qtest_init_without_qmp_handshake(extra_args);
 | 
					    QTestState *s = qtest_init_without_qmp_handshake(false, extra_args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Read the QMP greeting and then do the handshake */
 | 
					    /* Read the QMP greeting and then do the handshake */
 | 
				
			||||||
    qtest_qmp_discard_response(s, "");
 | 
					    qtest_qmp_discard_response(s, "");
 | 
				
			||||||
 | 
				
			|||||||
@ -56,11 +56,14 @@ QTestState *qtest_init(const char *extra_args);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * qtest_init_without_qmp_handshake:
 | 
					 * qtest_init_without_qmp_handshake:
 | 
				
			||||||
 * @extra_args: other arguments to pass to QEMU.
 | 
					 * @use_oob: true to have the server advertise OOB support
 | 
				
			||||||
 | 
					 * @extra_args: other arguments to pass to QEMU.  CAUTION: these
 | 
				
			||||||
 | 
					 * arguments are subject to word splitting and shell evaluation.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns: #QTestState instance.
 | 
					 * Returns: #QTestState instance.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
QTestState *qtest_init_without_qmp_handshake(const char *extra_args);
 | 
					QTestState *qtest_init_without_qmp_handshake(bool use_oob,
 | 
				
			||||||
 | 
					                                             const char *extra_args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * qtest_quit:
 | 
					 * qtest_quit:
 | 
				
			||||||
 | 
				
			|||||||
@ -28,9 +28,9 @@ object q_obj_cmd-arg
 | 
				
			|||||||
    member arg2: str optional=True
 | 
					    member arg2: str optional=True
 | 
				
			||||||
    member arg3: bool optional=False
 | 
					    member arg3: bool optional=False
 | 
				
			||||||
command cmd q_obj_cmd-arg -> Object
 | 
					command cmd q_obj_cmd-arg -> Object
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
command cmd-boxed Object -> None
 | 
					command cmd-boxed Object -> None
 | 
				
			||||||
   gen=True success_response=True boxed=True
 | 
					   gen=True success_response=True boxed=True oob=False
 | 
				
			||||||
doc freeform
 | 
					doc freeform
 | 
				
			||||||
    body=
 | 
					    body=
 | 
				
			||||||
= Section
 | 
					= Section
 | 
				
			||||||
 | 
				
			|||||||
@ -5,4 +5,4 @@ module ident-with-escape.json
 | 
				
			|||||||
object q_obj_fooA-arg
 | 
					object q_obj_fooA-arg
 | 
				
			||||||
    member bar1: str optional=False
 | 
					    member bar1: str optional=False
 | 
				
			||||||
command fooA q_obj_fooA-arg -> None
 | 
					command fooA q_obj_fooA-arg -> None
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,6 @@ enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
 | 
				
			|||||||
    prefix QTYPE
 | 
					    prefix QTYPE
 | 
				
			||||||
module indented-expr.json
 | 
					module indented-expr.json
 | 
				
			||||||
command eins None -> None
 | 
					command eins None -> None
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
command zwei None -> None
 | 
					command zwei None -> None
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								tests/qapi-schema/oob-test.err
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/qapi-schema/oob-test.err
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					tests/qapi-schema/oob-test.json:2: 'allow-oob' of command 'oob-command-1' should only use true value
 | 
				
			||||||
							
								
								
									
										1
									
								
								tests/qapi-schema/oob-test.exit
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/qapi-schema/oob-test.exit
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					1
 | 
				
			||||||
							
								
								
									
										2
									
								
								tests/qapi-schema/oob-test.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/qapi-schema/oob-test.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					# Check against oob illegal value
 | 
				
			||||||
 | 
					{ 'command': 'oob-command-1', 'allow-oob': 'some-string' }
 | 
				
			||||||
							
								
								
									
										0
									
								
								tests/qapi-schema/oob-test.out
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/qapi-schema/oob-test.out
									
									
									
									
									
										Normal file
									
								
							@ -139,6 +139,9 @@
 | 
				
			|||||||
{ 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
 | 
					{ 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
 | 
				
			||||||
{ 'command': 'boxed-union', 'data': 'UserDefNativeListUnion', 'boxed': true }
 | 
					{ 'command': 'boxed-union', 'data': 'UserDefNativeListUnion', 'boxed': true }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Smoke test on Out-Of-Band
 | 
				
			||||||
 | 
					{ 'command': 'an-oob-command', 'allow-oob': true }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# For testing integer range flattening in opts-visitor. The following schema
 | 
					# For testing integer range flattening in opts-visitor. The following schema
 | 
				
			||||||
# corresponds to the option format:
 | 
					# corresponds to the option format:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@ object Empty1
 | 
				
			|||||||
object Empty2
 | 
					object Empty2
 | 
				
			||||||
    base Empty1
 | 
					    base Empty1
 | 
				
			||||||
command user_def_cmd0 Empty2 -> Empty2
 | 
					command user_def_cmd0 Empty2 -> Empty2
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
enum QEnumTwo ['value1', 'value2']
 | 
					enum QEnumTwo ['value1', 'value2']
 | 
				
			||||||
    prefix QENUM_TWO
 | 
					    prefix QENUM_TWO
 | 
				
			||||||
object UserDefOne
 | 
					object UserDefOne
 | 
				
			||||||
@ -143,29 +143,31 @@ object UserDefNativeListUnion
 | 
				
			|||||||
    case sizes: q_obj_sizeList-wrapper
 | 
					    case sizes: q_obj_sizeList-wrapper
 | 
				
			||||||
    case any: q_obj_anyList-wrapper
 | 
					    case any: q_obj_anyList-wrapper
 | 
				
			||||||
command user_def_cmd None -> None
 | 
					command user_def_cmd None -> None
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
object q_obj_user_def_cmd1-arg
 | 
					object q_obj_user_def_cmd1-arg
 | 
				
			||||||
    member ud1a: UserDefOne optional=False
 | 
					    member ud1a: UserDefOne optional=False
 | 
				
			||||||
command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
 | 
					command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
object q_obj_user_def_cmd2-arg
 | 
					object q_obj_user_def_cmd2-arg
 | 
				
			||||||
    member ud1a: UserDefOne optional=False
 | 
					    member ud1a: UserDefOne optional=False
 | 
				
			||||||
    member ud1b: UserDefOne optional=True
 | 
					    member ud1b: UserDefOne optional=True
 | 
				
			||||||
command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
 | 
					command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
object q_obj_guest-get-time-arg
 | 
					object q_obj_guest-get-time-arg
 | 
				
			||||||
    member a: int optional=False
 | 
					    member a: int optional=False
 | 
				
			||||||
    member b: int optional=True
 | 
					    member b: int optional=True
 | 
				
			||||||
command guest-get-time q_obj_guest-get-time-arg -> int
 | 
					command guest-get-time q_obj_guest-get-time-arg -> int
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
object q_obj_guest-sync-arg
 | 
					object q_obj_guest-sync-arg
 | 
				
			||||||
    member arg: any optional=False
 | 
					    member arg: any optional=False
 | 
				
			||||||
command guest-sync q_obj_guest-sync-arg -> any
 | 
					command guest-sync q_obj_guest-sync-arg -> any
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
command boxed-struct UserDefZero -> None
 | 
					command boxed-struct UserDefZero -> None
 | 
				
			||||||
   gen=True success_response=True boxed=True
 | 
					   gen=True success_response=True boxed=True oob=False
 | 
				
			||||||
command boxed-union UserDefNativeListUnion -> None
 | 
					command boxed-union UserDefNativeListUnion -> None
 | 
				
			||||||
   gen=True success_response=True boxed=True
 | 
					   gen=True success_response=True boxed=True oob=False
 | 
				
			||||||
 | 
					command an-oob-command None -> None
 | 
				
			||||||
 | 
					   gen=True success_response=True boxed=False oob=True
 | 
				
			||||||
object UserDefOptions
 | 
					object UserDefOptions
 | 
				
			||||||
    member i64: intList optional=True
 | 
					    member i64: intList optional=True
 | 
				
			||||||
    member u64: uint64List optional=True
 | 
					    member u64: uint64List optional=True
 | 
				
			||||||
@ -229,4 +231,4 @@ object q_obj___org.qemu_x-command-arg
 | 
				
			|||||||
    member c: __org.qemu_x-Union2 optional=False
 | 
					    member c: __org.qemu_x-Union2 optional=False
 | 
				
			||||||
    member d: __org.qemu_x-Alt optional=False
 | 
					    member d: __org.qemu_x-Alt optional=False
 | 
				
			||||||
command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
 | 
					command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
 | 
				
			||||||
   gen=True success_response=True boxed=False
 | 
					   gen=True success_response=True boxed=False oob=False
 | 
				
			||||||
 | 
				
			|||||||
@ -45,8 +45,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
 | 
				
			|||||||
                      gen, success_response, boxed, allow_oob):
 | 
					                      gen, success_response, boxed, allow_oob):
 | 
				
			||||||
        print('command %s %s -> %s' % \
 | 
					        print('command %s %s -> %s' % \
 | 
				
			||||||
              (name, arg_type and arg_type.name, ret_type and ret_type.name))
 | 
					              (name, arg_type and arg_type.name, ret_type and ret_type.name))
 | 
				
			||||||
        print('   gen=%s success_response=%s boxed=%s' % \
 | 
					        print('   gen=%s success_response=%s boxed=%s oob=%s' % \
 | 
				
			||||||
              (gen, success_response, boxed))
 | 
					              (gen, success_response, boxed, allow_oob))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def visit_event(self, name, info, arg_type, boxed):
 | 
					    def visit_event(self, name, info, arg_type, boxed):
 | 
				
			||||||
        print('event %s %s' % (name, arg_type and arg_type.name))
 | 
					        print('event %s %s' % (name, arg_type and arg_type.name))
 | 
				
			||||||
 | 
				
			|||||||
@ -81,7 +81,7 @@ static void test_qmp_protocol(void)
 | 
				
			|||||||
    QList *capabilities;
 | 
					    QList *capabilities;
 | 
				
			||||||
    QTestState *qts;
 | 
					    QTestState *qts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qts = qtest_init_without_qmp_handshake(common_args);
 | 
					    qts = qtest_init_without_qmp_handshake(false, common_args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Test greeting */
 | 
					    /* Test greeting */
 | 
				
			||||||
    resp = qtest_qmp_receive(qts);
 | 
					    resp = qtest_qmp_receive(qts);
 | 
				
			||||||
@ -90,6 +90,7 @@ static void test_qmp_protocol(void)
 | 
				
			|||||||
    test_version(qdict_get(q, "version"));
 | 
					    test_version(qdict_get(q, "version"));
 | 
				
			||||||
    capabilities = qdict_get_qlist(q, "capabilities");
 | 
					    capabilities = qdict_get_qlist(q, "capabilities");
 | 
				
			||||||
    g_assert(capabilities && qlist_empty(capabilities));
 | 
					    g_assert(capabilities && qlist_empty(capabilities));
 | 
				
			||||||
 | 
					    QDECREF(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Test valid command before handshake */
 | 
					    /* Test valid command before handshake */
 | 
				
			||||||
    resp = qtest_qmp(qts, "{ 'execute': 'query-version' }");
 | 
					    resp = qtest_qmp(qts, "{ 'execute': 'query-version' }");
 | 
				
			||||||
@ -134,6 +135,87 @@ static void test_qmp_protocol(void)
 | 
				
			|||||||
    qtest_quit(qts);
 | 
					    qtest_quit(qts);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Tests for Out-Of-Band support. */
 | 
				
			||||||
 | 
					static void test_qmp_oob(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QTestState *qts;
 | 
				
			||||||
 | 
					    QDict *resp, *q;
 | 
				
			||||||
 | 
					    int acks = 0;
 | 
				
			||||||
 | 
					    const QListEntry *entry;
 | 
				
			||||||
 | 
					    QList *capabilities;
 | 
				
			||||||
 | 
					    QString *qstr;
 | 
				
			||||||
 | 
					    const char *cmd_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qts = qtest_init_without_qmp_handshake(true, common_args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check the greeting message. */
 | 
				
			||||||
 | 
					    resp = qtest_qmp_receive(qts);
 | 
				
			||||||
 | 
					    q = qdict_get_qdict(resp, "QMP");
 | 
				
			||||||
 | 
					    g_assert(q);
 | 
				
			||||||
 | 
					    capabilities = qdict_get_qlist(q, "capabilities");
 | 
				
			||||||
 | 
					    g_assert(capabilities && !qlist_empty(capabilities));
 | 
				
			||||||
 | 
					    entry = qlist_first(capabilities);
 | 
				
			||||||
 | 
					    g_assert(entry);
 | 
				
			||||||
 | 
					    qstr = qobject_to(QString, entry->value);
 | 
				
			||||||
 | 
					    g_assert(qstr);
 | 
				
			||||||
 | 
					    g_assert_cmpstr(qstring_get_str(qstr), ==, "oob");
 | 
				
			||||||
 | 
					    QDECREF(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Try a fake capability, it should fail. */
 | 
				
			||||||
 | 
					    resp = qtest_qmp(qts,
 | 
				
			||||||
 | 
					                     "{ 'execute': 'qmp_capabilities', "
 | 
				
			||||||
 | 
					                     "  'arguments': { 'enable': [ 'cap-does-not-exist' ] } }");
 | 
				
			||||||
 | 
					    g_assert(qdict_haskey(resp, "error"));
 | 
				
			||||||
 | 
					    QDECREF(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Now, enable OOB in current QMP session, it should succeed. */
 | 
				
			||||||
 | 
					    resp = qtest_qmp(qts,
 | 
				
			||||||
 | 
					                     "{ 'execute': 'qmp_capabilities', "
 | 
				
			||||||
 | 
					                     "  'arguments': { 'enable': [ 'oob' ] } }");
 | 
				
			||||||
 | 
					    g_assert(qdict_haskey(resp, "return"));
 | 
				
			||||||
 | 
					    QDECREF(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Try any command that does not support OOB but with OOB flag. We
 | 
				
			||||||
 | 
					     * should get failure.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    resp = qtest_qmp(qts,
 | 
				
			||||||
 | 
					                     "{ 'execute': 'query-cpus',"
 | 
				
			||||||
 | 
					                     "  'control': { 'run-oob': true } }");
 | 
				
			||||||
 | 
					    g_assert(qdict_haskey(resp, "error"));
 | 
				
			||||||
 | 
					    QDECREF(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * First send the "x-oob-test" command with lock=true and
 | 
				
			||||||
 | 
					     * oob=false, it should hang the dispatcher and main thread;
 | 
				
			||||||
 | 
					     * later, we send another lock=false with oob=true to continue
 | 
				
			||||||
 | 
					     * that thread processing.  Finally we should receive replies from
 | 
				
			||||||
 | 
					     * both commands.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    qtest_async_qmp(qts,
 | 
				
			||||||
 | 
					                    "{ 'execute': 'x-oob-test',"
 | 
				
			||||||
 | 
					                    "  'arguments': { 'lock': true }, "
 | 
				
			||||||
 | 
					                    "  'id': 'lock-cmd'}");
 | 
				
			||||||
 | 
					    qtest_async_qmp(qts,
 | 
				
			||||||
 | 
					                    "{ 'execute': 'x-oob-test', "
 | 
				
			||||||
 | 
					                    "  'arguments': { 'lock': false }, "
 | 
				
			||||||
 | 
					                    "  'control': { 'run-oob': true }, "
 | 
				
			||||||
 | 
					                    "  'id': 'unlock-cmd' }");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Ignore all events.  Wait for 2 acks */
 | 
				
			||||||
 | 
					    while (acks < 2) {
 | 
				
			||||||
 | 
					        resp = qtest_qmp_receive(qts);
 | 
				
			||||||
 | 
					        cmd_id = qdict_get_str(resp, "id");
 | 
				
			||||||
 | 
					        if (!g_strcmp0(cmd_id, "lock-cmd") ||
 | 
				
			||||||
 | 
					            !g_strcmp0(cmd_id, "unlock-cmd")) {
 | 
				
			||||||
 | 
					            acks++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        QDECREF(resp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qtest_quit(qts);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int query_error_class(const char *cmd)
 | 
					static int query_error_class(const char *cmd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    static struct {
 | 
					    static struct {
 | 
				
			||||||
@ -318,6 +400,7 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
    g_test_init(&argc, &argv, NULL);
 | 
					    g_test_init(&argc, &argv, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_func("qmp/protocol", test_qmp_protocol);
 | 
					    qtest_add_func("qmp/protocol", test_qmp_protocol);
 | 
				
			||||||
 | 
					    qtest_add_func("qmp/oob", test_qmp_oob);
 | 
				
			||||||
    qmp_schema_init(&schema);
 | 
					    qmp_schema_init(&schema);
 | 
				
			||||||
    add_query_tests(&schema);
 | 
					    add_query_tests(&schema);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,10 @@ void qmp_user_def_cmd(Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void qmp_an_oob_command(Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Empty2 *qmp_user_def_cmd0(Error **errp)
 | 
					Empty2 *qmp_user_def_cmd0(Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return g_new0(Empty2, 1);
 | 
					    return g_new0(Empty2, 1);
 | 
				
			||||||
 | 
				
			|||||||
@ -1115,7 +1115,7 @@ static const SerializeOps visitors[] = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void add_visitor_type(const SerializeOps *ops)
 | 
					static void add_visitor_type(const SerializeOps *ops)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char testname_prefix[128];
 | 
					    char testname_prefix[32];
 | 
				
			||||||
    char testname[128];
 | 
					    char testname[128];
 | 
				
			||||||
    TestArgs *args;
 | 
					    TestArgs *args;
 | 
				
			||||||
    int i = 0;
 | 
					    int i = 0;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								vl.c
									
									
									
									
									
								
							@ -2404,6 +2404,11 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
 | 
				
			|||||||
    if (qemu_opt_get_bool(opts, "pretty", 0))
 | 
					    if (qemu_opt_get_bool(opts, "pretty", 0))
 | 
				
			||||||
        flags |= MONITOR_USE_PRETTY;
 | 
					        flags |= MONITOR_USE_PRETTY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* OOB is off by default */
 | 
				
			||||||
 | 
					    if (qemu_opt_get_bool(opts, "x-oob", 0)) {
 | 
				
			||||||
 | 
					        flags |= MONITOR_USE_OOB;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chardev = qemu_opt_get(opts, "chardev");
 | 
					    chardev = qemu_opt_get(opts, "chardev");
 | 
				
			||||||
    chr = qemu_chr_find(chardev);
 | 
					    chr = qemu_chr_find(chardev);
 | 
				
			||||||
    if (chr == NULL) {
 | 
					    if (chr == NULL) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user