Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- qapi-schema.json | 3 ++ qapi/trace.json | 65 ++++++++++++++++++++++++++++++++++++++++++++ qmp-commands.hx | 35 ++++++++++++++++++++++++ trace/Makefile.objs | 1 + trace/qmp.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+) create mode 100644 qapi/trace.json create mode 100644 trace/qmp.c
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..06c613c --- /dev/null +++ b/qapi/trace.json @@ -0,0 +1,65 @@ +# -*- mode: python -*- +# +# Copyright (C) 2011-2014 Lluís Vilanova <vilan...@ac.upc.edu> +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. + + +## +# @TraceEventState: +# +# State of a tracing event. +# +# @unavailable: The event is statically disabled. +# +# @disabled: The event is dynamically disabled. +# +# @enabled: The event is dynamically enabled. +# +# Since 2.2 +## +{ 'enum': 'TraceEventState', + 'data': ['unavailable', 'disabled', 'enabled'] } + +## +# @TraceEventInfo: +# +# Information of a tracing event. +# +# @name: Event name. +# @state: Tracing state. +# +# Since 2.2 +## +{ 'type': 'TraceEventInfo', + 'data': {'name': 'str', 'state': 'TraceEventState'} } + +## +# @trace-event-get-state: +# +# Query the state of events. +# +# @name: Event name pattern (case-sensitive glob). +# +# Returns: a list of @TraceEventInfo for the matching events +# +# Since 2.2 +## +{ 'command': 'trace-event-get-state', + 'data': {'name': 'str'}, + 'returns': ['TraceEventInfo'] } + +## +# @trace-event-set-state: +# +# Set the dynamic tracing state of events. +# +# @name: Event name pattern (case-sensitive glob). +# @enable: Whether to enable tracing. +# @ignore-unavailable: #optional Do not match unavailable events with @name. +# +# Since 2.2 +## +{ 'command': 'trace-event-set-state', + 'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool'} } diff --git a/qmp-commands.hx b/qmp-commands.hx index 4be4765..b605517 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3753,5 +3753,40 @@ 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. + +Example: + +-> { "execute": "trace-event-get-state", "arguments": { "name": "qemu_memalign" } } +<- { "return": [ { "name": "qemu_memalign", "state": "disabled" } ] } +EQMP + + { + .name = "trace-event-set-state", + .args_type = "name:s,enable:b,ignore-unavailable:b?", + .mhandler.cmd_new = qmp_marshal_input_trace_event_set_state, + }, +SQMP +trace-event-set-state +--------------------- + +Set the state of events. + +Example: + +-> { "execute": "trace-event-set-state", "arguments": { "name": "qemu_memalign", "enable": "true" } } +<- { "return": {} } 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/qmp.c b/trace/qmp.c new file mode 100644 index 0000000..0b19489 --- /dev/null +++ b/trace/qmp.c @@ -0,0 +1,75 @@ +/* + * QMP commands for tracing events. + * + * Copyright (C) 2014 Lluís Vilanova <vilan...@ac.upc.edu> + * + * 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" + + +TraceEventInfoList *qmp_trace_event_get_state(const char *name, Error **errp) +{ + TraceEventInfoList *events = NULL; + bool found = false; + TraceEvent *ev; + + ev = NULL; + while ((ev = trace_event_pattern(name, ev)) != NULL) { + TraceEventInfoList *elem = g_new(TraceEventInfoList, 1); + elem->value = g_new(TraceEventInfo, 1); + elem->value->name = g_strdup(trace_event_get_name(ev)); + if (!trace_event_get_state_static(ev)) { + elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE; + } else if (!trace_event_get_state_dynamic(ev)) { + elem->value->state = TRACE_EVENT_STATE_DISABLED; + } else { + elem->value->state = TRACE_EVENT_STATE_ENABLED; + } + elem->next = events; + events = elem; + found = true; + } + + if (!found && !trace_event_is_pattern(name)) { + error_setg(errp, "unknown event \"%s\"", name); + } + + return events; +} + +void qmp_trace_event_set_state(const char *name, bool enable, + bool has_ignore_unavailable, + bool ignore_unavailable, Error **errp) +{ + bool found = false; + TraceEvent *ev; + + /* Check all selected events are dynamic */ + ev = NULL; + while ((ev = trace_event_pattern(name, ev)) != NULL) { + found = true; + if (!(has_ignore_unavailable && ignore_unavailable) && + !trace_event_get_state_static(ev)) { + error_setg(errp, "cannot set dynamic tracing state for \"%s\"", + trace_event_get_name(ev)); + return; + } + } + if (!found && !trace_event_is_pattern(name)) { + error_setg(errp, "unknown event \"%s\"", name); + 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, enable); + } + } +}