Also removes old "trace-event", "trace-file" and "info trace-events" HMP commands.
Signed-off-by: Lluís Vilanova <[email protected]> --- monitor.c | 24 +++++++--------- qapi-schema.json | 3 ++ qapi/trace.json | 44 +++++++++++++++++++++++++++++ qmp-commands.hx | 27 ++++++++++++++++++ trace/Makefile.objs | 1 + trace/control.c | 13 --------- trace/control.h | 7 ----- trace/qmp.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 162 insertions(+), 34 deletions(-) create mode 100644 qapi/trace.json create mode 100644 trace/qmp.c diff --git a/monitor.c b/monitor.c index cdbaa60..0f605f5 100644 --- a/monitor.c +++ b/monitor.c @@ -887,19 +887,8 @@ static void do_trace_event_set_state(Monitor *mon, const QDict *qdict) const char *tp_name = qdict_get_str(qdict, "name"); bool new_state = qdict_get_bool(qdict, "option"); - bool found = false; - TraceEvent *ev = NULL; - while ((ev = trace_event_pattern(tp_name, ev)) != NULL) { - found = true; - if (!trace_event_get_state_static(ev)) { - monitor_printf(mon, "event \"%s\" is not traceable\n", tp_name); - } else { - trace_event_set_state_dynamic(ev, new_state); - } - } - if (!trace_event_is_pattern(tp_name) && !found) { - monitor_printf(mon, "unknown event name \"%s\"\n", tp_name); - } + /* TODO: should propagate QMP errors to HMP */ + qmp_trace_event_set_state(tp_name, new_state, true, true, NULL); } #ifdef CONFIG_TRACE_SIMPLE @@ -1079,7 +1068,14 @@ static void do_info_cpu_stats(Monitor *mon, const QDict *qdict) static void do_trace_print_events(Monitor *mon, const QDict *qdict) { - trace_print_events((FILE *)mon, &monitor_fprintf); + TraceEventStateList *events = qmp_trace_event_get_state("*", NULL); + TraceEventStateList *event; + for (event = events; event != NULL; event = event->next) { + monitor_printf(mon, "%s : state %u\n", + event->value->name, + event->value->sstatic && event->value->sdynamic); + } + qapi_free_TraceEventStateList(events); } static int client_migrate_info(Monitor *mon, const QDict *qdict, diff --git a/qapi-schema.json b/qapi-schema.json index 341f417..42b90df 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -11,6 +11,9 @@ # QAPI event definitions { 'include': 'qapi/event.json' } +# Tracing commands +{ 'include': 'qapi/trace.json' } + ## # LostTickPolicy: # diff --git a/qapi/trace.json b/qapi/trace.json new file mode 100644 index 0000000..6e6313d --- /dev/null +++ b/qapi/trace.json @@ -0,0 +1,44 @@ +# -*- mode: python -*- + +## +# @TraceEventState: +# +# State of a tracing event. +# +# @name: Event name. +# @sstatic: Static tracing state. +# @sdynamic: Dynamic tracing state. +# +# Since 2.2 +## +{ 'type': 'TraceEventState', + 'data': {'name': 'str', 'sstatic': 'bool', 'sdynamic': 'bool'} } + +## +# @trace-event-get-state: +# +# Query the state of events. +# +# @name: Event name pattern. +# +# Returns: @TraceEventState of the matched events +# +# Since 2.2 +## +{ 'command': 'trace-event-get-state', + 'data': {'name': 'str'}, + 'returns': ['TraceEventState'] } + +## +# @trace-event-set-state: +# +# Set the dynamic state of events. +# +# @name: Event name pattern. +# @state: Dynamic tracing state. +# @keepgoing: #optional Apply changes even if not all events can be changed. +# +# Since 2.2 +## +{ 'command': 'trace-event-set-state', + 'data': {'name': 'str', 'state': 'bool', '*keepgoing': 'bool'} } diff --git a/qmp-commands.hx b/qmp-commands.hx index 4be4765..443dd16 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3753,5 +3753,32 @@ Example: -> { "execute": "rtc-reset-reinjection" } <- { "return": {} } +EQMP + + { + .name = "trace-event-get-state", + .args_type = "name:s", + .mhandler.cmd_new = qmp_marshal_input_trace_event_get_state, + }, + +SQMP +trace-event-get-state +--------------------- + +Query the state of events. + +EQMP + + { + .name = "trace-event-set-state", + .args_type = "name:s,state:b,keepgoing:b?", + .mhandler.cmd_new = qmp_marshal_input_trace_event_set_state, + }, + +SQMP +trace-event-set-state +--------------------- + +Set the state of events. EQMP diff --git a/trace/Makefile.objs b/trace/Makefile.objs index 387f191..01b3718 100644 --- a/trace/Makefile.objs +++ b/trace/Makefile.objs @@ -145,3 +145,4 @@ util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o util-obj-$(CONFIG_TRACE_UST) += generated-ust.o util-obj-y += control.o util-obj-y += generated-tracers.o +util-obj-y += qmp.o diff --git a/trace/control.c b/trace/control.c index 9631a40..0d30801 100644 --- a/trace/control.c +++ b/trace/control.c @@ -85,19 +85,6 @@ TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev) return NULL; } -void trace_print_events(FILE *stream, fprintf_function stream_printf) -{ - TraceEventID i; - - for (i = 0; i < trace_event_count(); i++) { - TraceEvent *ev = trace_event_id(i); - stream_printf(stream, "%s [Event ID %u] : state %u\n", - trace_event_get_name(ev), i, - trace_event_get_state_static(ev) && - trace_event_get_state_dynamic(ev)); - } -} - static void trace_init_events(const char *fname) { Location loc; diff --git a/trace/control.h b/trace/control.h index e1ec033..da9bb6b 100644 --- a/trace/control.h +++ b/trace/control.h @@ -149,13 +149,6 @@ static void trace_event_set_state_dynamic(TraceEvent *ev, bool state); /** - * trace_print_events: - * - * Print the state of all events. - */ -void trace_print_events(FILE *stream, fprintf_function stream_printf); - -/** * trace_init_backends: * @events: Name of file with events to be enabled at startup; may be NULL. * Corresponds to commandline option "-trace events=...". diff --git a/trace/qmp.c b/trace/qmp.c new file mode 100644 index 0000000..d22d8fa --- /dev/null +++ b/trace/qmp.c @@ -0,0 +1,77 @@ +/* + * QMP commands for tracing events. + * + * Copyright (C) 2014 Lluís Vilanova <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/typedefs.h" +#include "qmp-commands.h" +#include "trace/control.h" + + +TraceEventStateList *qmp_trace_event_get_state(const char *name, Error **errp) +{ + TraceEventStateList dummy = {}; + TraceEventStateList *prev = &dummy; + + bool found = false; + TraceEvent *ev = NULL; + while ((ev = trace_event_pattern(name, ev)) != NULL) { + found = true; + TraceEventStateList *elem = g_malloc0(sizeof(*elem)); + elem->value = g_malloc0(sizeof(*elem->value)); + elem->value->name = g_strdup(trace_event_get_name(ev)); + elem->value->sstatic = trace_event_get_state_static(ev); + elem->value->sdynamic = trace_event_get_state_dynamic(ev); + prev->next = elem; + prev = elem; + } + if (!found && !trace_event_is_pattern(name)) { + error_setg(errp, "unknown event \"%s\"\n", name); + } + + return dummy.next; +} + +void qmp_trace_event_set_state(const char *name, bool state, bool has_keepgoing, + bool keepgoing, Error **errp) +{ + bool error = false; + bool found = false; + TraceEvent *ev = NULL; + + /* Check all selected events are dynamic */ + while ((ev = trace_event_pattern(name, ev)) != NULL) { + found = true; + if (!trace_event_get_state_static(ev)) { + error_setg(errp, "cannot set dynamic tracing state for \"%s\"\n", + trace_event_get_name(ev)); + if (!(has_keepgoing && keepgoing)) { + error = true; + } + break; + } + } + if (error) { + return; + } + if (!found && !trace_event_is_pattern(name)) { + error_setg(errp, "unknown event \"%s\"\n", name); + return; + } + + if (error) { + return; + } + + /* Apply changes */ + ev = NULL; + while ((ev = trace_event_pattern(name, ev)) != NULL) { + if (trace_event_get_state_static(ev)) { + trace_event_set_state_dynamic(ev, state); + } + } +}
