[libvirt] [PATCH v2 4/8] qemu_driver: add support to perf event
Daniel P. Berrange
berrange at redhat.com
Tue Dec 8 10:57:22 UTC 2015
On Mon, Dec 07, 2015 at 03:53:55PM +0800, Qiaowei Ren wrote:
> This patch implement the internal driver API for perf event into
> qemu driver.
>
> In addition, this patch extend virDomainListGetStats API to get
> the statistics for perf event. To do so, we add a
> 'VIR_DOMAIN_STATS_PERF' enum to causes reporting of all previously
> enabled perf events.
>
> Signed-off-by: Qiaowei Ren <qiaowei.ren at intel.com>
> ---
> include/libvirt/libvirt-domain.h | 1 +
> src/qemu/qemu_domain.h | 3 +
> src/qemu/qemu_driver.c | 147 +++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_process.c | 7 ++
> 4 files changed, 158 insertions(+)
>
> diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
> index cc1b29b..4f29f54 100644
> --- a/include/libvirt/libvirt-domain.h
> +++ b/include/libvirt/libvirt-domain.h
> @@ -1771,6 +1771,7 @@ typedef enum {
> VIR_DOMAIN_STATS_VCPU = (1 << 3), /* return domain virtual CPU info */
> VIR_DOMAIN_STATS_INTERFACE = (1 << 4), /* return domain interfaces info */
> VIR_DOMAIN_STATS_BLOCK = (1 << 5), /* return domain block info */
> + VIR_DOMAIN_STATS_PERF = (1 << 6), /* return domain perf event info */
> } virDomainStatsTypes;
>
> typedef enum {
> diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
> index 14892fd..080498e 100644
> --- a/src/qemu/qemu_domain.h
> +++ b/src/qemu/qemu_domain.h
> @@ -26,6 +26,7 @@
>
> # include "virthread.h"
> # include "vircgroup.h"
> +# include "virperf.h"
> # include "domain_addr.h"
> # include "domain_conf.h"
> # include "snapshot_conf.h"
> @@ -191,6 +192,8 @@ struct _qemuDomainObjPrivate {
>
> virCgroupPtr cgroup;
>
> + virPerfPtr perf;
> +
> virCond unplugFinished; /* signals that unpluggingDevice was unplugged */
> const char *unpluggingDevice; /* alias of the device that is being unplugged */
> char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index ae1d8e7..53f5089 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -98,6 +98,7 @@
> #include "virhostdev.h"
> #include "domain_capabilities.h"
> #include "vircgroup.h"
> +#include "virperf.h"
> #include "virnuma.h"
> #include "dirname.h"
> #include "network/bridge_driver.h"
> @@ -10249,6 +10250,86 @@ qemuDomainGetNumaParameters(virDomainPtr dom,
> }
>
> static int
> +qemuDomainSetPerfEvents(virDomainPtr dom,
> + virTypedParameterPtr params,
> + int nparams)
> +{
> + size_t i;
> + virDomainObjPtr vm = NULL;
> + qemuDomainObjPrivatePtr priv;
> + int ret = -1;
> + virPerfEventType type;
> + bool enabled;
> +
> + if (virTypedParamsValidate(params, nparams, VIR_PERF_PARAMETERS) < 0)
> + return -1;
Nit-pick - indented one spec too far
> +
> + if (!(vm = qemuDomObjFromDomain(dom)))
> + return -1;
> +
> + priv = vm->privateData;
> +
> + if (virDomainSetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
> + goto cleanup;
> +
> + for (i = 0; i < nparams; i++) {
> + virTypedParameterPtr param = ¶ms[i];
> + enabled = params->value.b;
> + type = virPerfEventTypeFromString(param->field);
> +
> + if (!enabled && virPerfEventDisable(priv->perf, type))
> + goto cleanup;
> + if (enabled && virPerfEventEnable(priv->perf, type, vm->pid))
> + goto cleanup;
> + }
> +
> + ret = 0;
> +
> + cleanup:
> + virDomainObjEndAPI(&vm);
> + return ret;
> +}
> +
> +static int
> +qemuDomainGetPerfEvents(virDomainPtr dom,
> + virTypedParameterPtr *params,
> + int *nparams)
> +{
> + size_t i;
> + virDomainObjPtr vm = NULL;
> + qemuDomainObjPrivatePtr priv;
> + int ret = -1;
> + virTypedParameterPtr par = NULL;
> + int maxpar = 0;
> + int npar = 0;
> +
> + if (!(vm = qemuDomObjFromDomain(dom)))
> + goto cleanup;
> +
> + priv = vm->privateData;
> +
> + if (virDomainGetPerfEventsEnsureACL(dom->conn, vm->def) < 0)
> + goto cleanup;
> +
> + for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
> + if (virTypedParamsAddBoolean(&par, &npar, &maxpar,
> + virPerfEventTypeToString(i),
> + virPerfEventIsEnabled(priv->perf, i)) < 0) {
> + virTypedParamsFree(par, npar);
> + goto cleanup;
> + }
> + }
> +
> + *params = par;
> + *nparams = npar;
> + ret = 0;
> +
> + cleanup:
> + virDomainObjEndAPI(&vm);
> + return ret;
> +}
> +
> +static int
> qemuSetVcpusBWLive(virDomainObjPtr vm, virCgroupPtr cgroup,
> unsigned long long period, long long quota)
> {
> @@ -19427,6 +19508,69 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
>
> #undef QEMU_ADD_COUNT_PARAM
>
> +static int
> +qemuDomainGetStatsPerfCmt(virPerfPtr perf,
> + virDomainStatsRecordPtr record,
> + int *maxparams)
> +{
> + unsigned long long cache = 0;
> + int scaling_factor = 0;
> + int event_fd = virPerfGetEventFd(perf, VIR_PERF_EVENT_CMT);
> +
> + if (event_fd <= 0)
> + return -1;
> +
> + if (read(event_fd, &cache, sizeof(uint64_t)) < 0) {
> + virReportSystemError(errno, "%s",
> + _("Unable to read cache data"));
> + return -1;
> + }
> +
> + scaling_factor = virPerfGetCmtScale(perf);
> + if (scaling_factor <= 0)
> + return -1;
> +
> + cache *= scaling_factor;
This feels like it is exposing impl detail from virPerf.
I'd expect the virPerf API to support us doing
virPerfReadEvent(perf, VIR_PERF_EVENT_CMT, &cache);
and hide the scaling_factor & read(event_fd) code in
virPerfReadEvent
> +
> + if (virTypedParamsAddULLong(&record->params,
> + &record->nparams,
> + maxparams,
> + "perf.cache",
> + cache) < 0)
> + return -1;
> +
> + return 0;
> +}
> @@ -20207,6 +20352,8 @@ static virHypervisorDriver qemuHypervisorDriver = {
> .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
> .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
> .domainSendKey = qemuDomainSendKey, /* 0.9.4 */
> + .domainGetPerfEvents = qemuDomainGetPerfEvents, /* 1.3.0 */
> + .domainSetPerfEvents = qemuDomainSetPerfEvents, /* 1.3.0 */
1.3.1
> + VIR_DEBUG("Initializing perf event");
Best to put that debug line inside virPerfNew in fact
> + priv->perf = virPerfNew();
> + if (!priv->perf)
> + goto cleanup;
> +
> /* This must be done after cgroup placement to avoid resetting CPU
> * affinity */
> if (!vm->def->cputune.emulatorpin &&
> @@ -5391,6 +5396,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
> }
> virCgroupFree(&priv->cgroup);
>
> + virPerfFree(priv->perf);
> +
> qemuProcessRemoveDomainStatus(driver, vm);
>
> /* Remove VNC and Spice ports from port reservation bitmap, but only if
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list