Commit f55e88f2 authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 6cf38cbf 0dfddbb5
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -695,12 +695,11 @@ static void nvme_parse_filename(const char *filename, QDict *options,
        unsigned long ns;
        const char *slash = strchr(tmp, '/');
        if (!slash) {
            qdict_put(options, NVME_BLOCK_OPT_DEVICE,
                      qstring_from_str(tmp));
            qdict_put_str(options, NVME_BLOCK_OPT_DEVICE, tmp);
            return;
        }
        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);
        namespace = slash + 1;
        if (*namespace && qemu_strtoul(namespace, NULL, 10, &ns)) {
@@ -708,8 +707,8 @@ static void nvme_parse_filename(const char *filename, QDict *options,
                       namespace);
            return;
        }
        qdict_put(options, NVME_BLOCK_OPT_NAMESPACE,
                  qstring_from_str(*namespace ? namespace : "1"));
        qdict_put_str(options, NVME_BLOCK_OPT_NAMESPACE,
                      *namespace ? namespace : "1");
    }
}

@@ -1082,7 +1081,7 @@ static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts)
                 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;
}

+1 −1
Original line number Diff line number Diff line
@@ -381,7 +381,7 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict)

        monitor_printf(mon, "%c CPU #%" PRId64 ":", active,
                       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);
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ extern Monitor *cur_mon;
#define MONITOR_USE_READLINE  0x02
#define MONITOR_USE_CONTROL   0x04
#define MONITOR_USE_PRETTY    0x08
#define MONITOR_USE_OOB       0x10

bool monitor_cur_is_qmp(void);

+1 −3
Original line number Diff line number Diff line
@@ -586,9 +586,7 @@ static gboolean qio_channel_websock_handshake_io(QIOChannel *ioc,
        return TRUE;
    }

    if (err) {
    error_propagate(&wioc->io_err, err);
    }

    trace_qio_channel_websock_handshake_reply(ioc);
    qio_channel_add_watch(
+81 −37
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include "net/slirp.h"
#include "chardev/char-fe.h"
#include "chardev/char-io.h"
#include "chardev/char-mux.h"
#include "ui/qemu-spice.h"
#include "sysemu/numa.h"
#include "monitor/monitor.h"
@@ -234,6 +235,22 @@ static struct {
    QEMUBH *qmp_respond_bh;
} 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 */
#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 gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
@@ -701,6 +750,8 @@ static void monitor_data_destroy(Monitor *mon)
    QDECREF(mon->outbuf);
    qemu_mutex_destroy(&mon->out_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_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);
    if (!cmd) {
        if (mon->qmp.commands == &qmp_cap_negotiation_commands) {
            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;
    }

@@ -4003,22 +4060,6 @@ static void monitor_qmp_respond(Monitor *mon, QObject *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
 * and objects inside it before return.
@@ -4027,7 +4068,6 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj)
{
    Monitor *mon, *old_mon;
    QObject *req, *rsp = NULL, *id;
    QDict *qdict = NULL;
    bool need_resume;

    req = req_obj->req;
@@ -4050,18 +4090,6 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj)

    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 */
    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,
                                            COMMAND_DROP_REASON_QUEUE_FULL,
                                            &error_abort);
            qobject_decref(id);
            qobject_decref(req);
            g_free(req_obj);
            qmp_request_free(req_obj);
            return;
        }
    }
@@ -4315,7 +4341,7 @@ static QObject *get_qmp_greeting(Monitor *mon)
            /* Monitors that are not using IOThread won't support OOB */
            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}}",
@@ -4342,6 +4368,7 @@ static void monitor_qmp_event(void *opaque, int event)
        mon_refcount++;
        break;
    case CHR_EVENT_CLOSED:
        monitor_qmp_cleanup_queues(mon);
        json_message_parser_destroy(&mon->qmp.parser);
        json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
        mon_refcount--;
@@ -4536,12 +4563,26 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
void monitor_init(Chardev *chr, int flags)
{
    Monitor *mon = g_malloc(sizeof(*mon));
    bool use_readline = flags & MONITOR_USE_READLINE;
    bool use_oob = flags & MONITOR_USE_OOB;

    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, false);
    monitor_data_init(mon, false, use_oob);

    qemu_chr_fe_init(&mon->chr, chr, &error_abort);
    mon->flags = flags;
    if (flags & MONITOR_USE_READLINE) {
    if (use_readline) {
        mon->rs = readline_init(monitor_readline_printf,
                                monitor_readline_flush,
                                mon,
@@ -4637,6 +4678,9 @@ QemuOptsList qemu_mon_opts = {
        },{
            .name = "pretty",
            .type = QEMU_OPT_BOOL,
        },{
            .name = "x-oob",
            .type = QEMU_OPT_BOOL,
        },
        { /* end of list */ }
    },
Loading