2008-12-05 04:33:06 +08:00
|
|
|
/*
|
2011-07-20 16:07:01 +08:00
|
|
|
* Virtio Balloon Device
|
2008-12-05 04:33:06 +08:00
|
|
|
*
|
|
|
|
* Copyright IBM, Corp. 2008
|
2011-07-20 16:07:01 +08:00
|
|
|
* Copyright (C) 2011 Red Hat, Inc.
|
|
|
|
* Copyright (C) 2011 Amit Shah <amit.shah@redhat.com>
|
2008-12-05 04:33:06 +08:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Anthony Liguori <aliguori@us.ibm.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
|
|
* the COPYING file in the top-level directory.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-01-27 02:17:07 +08:00
|
|
|
#include "qemu/osdep.h"
|
2012-12-18 01:20:00 +08:00
|
|
|
#include "qemu/iov.h"
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
#include "qemu/timer.h"
|
2008-12-05 04:33:06 +08:00
|
|
|
#include "qemu-common.h"
|
2013-02-06 00:06:20 +08:00
|
|
|
#include "hw/virtio/virtio.h"
|
2017-10-18 00:44:13 +08:00
|
|
|
#include "hw/mem/pc-dimm.h"
|
2012-12-18 01:20:04 +08:00
|
|
|
#include "sysemu/balloon.h"
|
2013-02-06 00:06:20 +08:00
|
|
|
#include "hw/virtio/virtio-balloon.h"
|
2012-12-18 01:20:04 +08:00
|
|
|
#include "sysemu/kvm.h"
|
2012-12-18 01:19:49 +08:00
|
|
|
#include "exec/address-spaces.h"
|
2018-02-01 19:18:31 +08:00
|
|
|
#include "qapi/error.h"
|
2018-02-27 07:13:27 +08:00
|
|
|
#include "qapi/qapi-events-misc.h"
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
#include "qapi/visitor.h"
|
2014-11-17 13:11:10 +08:00
|
|
|
#include "trace.h"
|
2017-09-12 03:52:50 +08:00
|
|
|
#include "qemu/error-report.h"
|
2008-12-05 04:33:06 +08:00
|
|
|
|
2013-02-06 00:06:20 +08:00
|
|
|
#include "hw/virtio/virtio-bus.h"
|
2014-06-25 01:43:22 +08:00
|
|
|
#include "hw/virtio/virtio-access.h"
|
2013-03-27 17:49:10 +08:00
|
|
|
|
2016-04-14 16:50:07 +08:00
|
|
|
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
|
|
|
|
|
2008-12-05 04:33:06 +08:00
|
|
|
static void balloon_page(void *addr, int deflate)
|
|
|
|
{
|
2015-11-06 02:11:23 +08:00
|
|
|
if (!qemu_balloon_is_inhibited() && (!kvm_enabled() ||
|
|
|
|
kvm_has_sync_mmu())) {
|
2016-04-14 16:50:07 +08:00
|
|
|
qemu_madvise(addr, BALLOON_PAGE_SIZE,
|
2010-09-25 19:26:05 +08:00
|
|
|
deflate ? QEMU_MADV_WILLNEED : QEMU_MADV_DONTNEED);
|
2015-11-06 02:11:23 +08:00
|
|
|
}
|
2008-12-05 04:33:06 +08:00
|
|
|
}
|
|
|
|
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
static const char *balloon_stat_names[] = {
|
|
|
|
[VIRTIO_BALLOON_S_SWAP_IN] = "stat-swap-in",
|
|
|
|
[VIRTIO_BALLOON_S_SWAP_OUT] = "stat-swap-out",
|
|
|
|
[VIRTIO_BALLOON_S_MAJFLT] = "stat-major-faults",
|
|
|
|
[VIRTIO_BALLOON_S_MINFLT] = "stat-minor-faults",
|
|
|
|
[VIRTIO_BALLOON_S_MEMFREE] = "stat-free-memory",
|
|
|
|
[VIRTIO_BALLOON_S_MEMTOT] = "stat-total-memory",
|
2016-02-24 15:50:48 +08:00
|
|
|
[VIRTIO_BALLOON_S_AVAIL] = "stat-available-memory",
|
2017-12-05 20:14:46 +08:00
|
|
|
[VIRTIO_BALLOON_S_CACHES] = "stat-disk-caches",
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
[VIRTIO_BALLOON_S_NR] = NULL
|
|
|
|
};
|
|
|
|
|
2010-01-27 04:17:35 +08:00
|
|
|
/*
|
|
|
|
* reset_stats - Mark all items in the stats array as unset
|
|
|
|
*
|
2013-07-25 01:48:56 +08:00
|
|
|
* This function needs to be called at device initialization and before
|
|
|
|
* updating to a set of newly-generated stats. This will ensure that no
|
2010-01-27 04:17:35 +08:00
|
|
|
* stale values stick around in case the guest reports a subset of the supported
|
|
|
|
* statistics.
|
|
|
|
*/
|
|
|
|
static inline void reset_stats(VirtIOBalloon *dev)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < VIRTIO_BALLOON_S_NR; dev->stats[i++] = -1);
|
|
|
|
}
|
|
|
|
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
static bool balloon_stats_supported(const VirtIOBalloon *s)
|
|
|
|
{
|
2013-03-27 17:49:14 +08:00
|
|
|
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
2015-08-17 17:48:29 +08:00
|
|
|
return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ);
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool balloon_stats_enabled(const VirtIOBalloon *s)
|
|
|
|
{
|
|
|
|
return s->stats_poll_interval > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void balloon_stats_destroy_timer(VirtIOBalloon *s)
|
|
|
|
{
|
|
|
|
if (balloon_stats_enabled(s)) {
|
2013-08-21 23:03:08 +08:00
|
|
|
timer_del(s->stats_timer);
|
|
|
|
timer_free(s->stats_timer);
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
s->stats_timer = NULL;
|
|
|
|
s->stats_poll_interval = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-16 00:00:11 +08:00
|
|
|
static void balloon_stats_change_timer(VirtIOBalloon *s, int64_t secs)
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
{
|
2013-08-21 23:03:08 +08:00
|
|
|
timer_mod(s->stats_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + secs * 1000);
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void balloon_stats_poll_cb(void *opaque)
|
|
|
|
{
|
|
|
|
VirtIOBalloon *s = opaque;
|
2013-03-27 17:49:14 +08:00
|
|
|
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
|
2016-03-01 19:14:03 +08:00
|
|
|
if (s->stats_vq_elem == NULL || !balloon_stats_supported(s)) {
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
/* re-schedule */
|
|
|
|
balloon_stats_change_timer(s, s->stats_poll_interval);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-02-04 22:26:51 +08:00
|
|
|
virtqueue_push(s->svq, s->stats_vq_elem, s->stats_vq_offset);
|
2013-03-27 17:49:14 +08:00
|
|
|
virtio_notify(vdev, s->svq);
|
2016-02-04 22:26:51 +08:00
|
|
|
g_free(s->stats_vq_elem);
|
|
|
|
s->stats_vq_elem = NULL;
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 21:48:55 +08:00
|
|
|
static void balloon_stats_get_all(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
{
|
2014-05-07 15:53:52 +08:00
|
|
|
Error *err = NULL;
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
VirtIOBalloon *s = opaque;
|
|
|
|
int i;
|
|
|
|
|
2016-01-29 21:48:57 +08:00
|
|
|
visit_start_struct(v, name, NULL, 0, &err);
|
2014-05-07 15:53:52 +08:00
|
|
|
if (err) {
|
|
|
|
goto out;
|
|
|
|
}
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 21:48:54 +08:00
|
|
|
visit_type_int(v, "last-update", &s->stats_last_update, &err);
|
qapi: Replace uncommon use of the error API by the common one
We commonly use the error API like this:
err = NULL;
foo(..., &err);
if (err) {
goto out;
}
bar(..., &err);
Every error source is checked separately. The second function is only
called when the first one succeeds. Both functions are free to pass
their argument to error_set(). Because error_set() asserts no error
has been set, this effectively means they must not be called with an
error set.
The qapi-generated code uses the error API differently:
// *errp was initialized to NULL somewhere up the call chain
frob(..., errp);
gnat(..., errp);
Errors accumulate in *errp: first error wins, subsequent errors get
dropped. To make this work, the second function does nothing when
called with an error set. Requires non-null errp, or else the second
function can't see the first one fail.
This usage has also bled into visitor tests, and two device model
object property getters rtc_get_date() and balloon_stats_get_all().
With the "accumulate" technique, you need fewer error checks in
callers, and buy that with an error check in every callee. Can be
nice.
However, mixing the two techniques is confusing. You can't use the
"accumulate" technique with functions designed for the "check
separately" technique. You can use the "check separately" technique
with functions designed for the "accumulate" technique, but then
error_set() can't catch you setting an error more than once.
Standardize on the "check separately" technique for now, because it's
overwhelmingly prevalent.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-05-07 15:53:54 +08:00
|
|
|
if (err) {
|
|
|
|
goto out_end;
|
|
|
|
}
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
|
2016-01-29 21:48:57 +08:00
|
|
|
visit_start_struct(v, "stats", NULL, 0, &err);
|
2014-05-07 15:53:52 +08:00
|
|
|
if (err) {
|
|
|
|
goto out_end;
|
|
|
|
}
|
2016-01-29 21:48:45 +08:00
|
|
|
for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 21:48:54 +08:00
|
|
|
visit_type_uint64(v, balloon_stat_names[i], &s->stats[i], &err);
|
2016-01-29 21:48:45 +08:00
|
|
|
if (err) {
|
qapi: Split visit_end_struct() into pieces
As mentioned in previous patches, we want to call visit_end_struct()
functions unconditionally, so that visitors can release resources
tied up since the matching visit_start_struct() without also having
to worry about error priority if more than one error occurs.
Even though error_propagate() can be safely used to ignore a second
error during cleanup caused by a first error, it is simpler if the
cleanup cannot set an error. So, split out the error checking
portion (basically, input visitors checking for unvisited keys) into
a new function visit_check_struct(), which can be safely skipped if
any earlier errors are encountered, and leave the cleanup portion
(which never fails, but must be called unconditionally if
visit_start_struct() succeeded) in visit_end_struct().
Generated code in qapi-visit.c has diffs resembling:
|@@ -59,10 +59,12 @@ void visit_type_ACPIOSTInfo(Visitor *v,
| goto out_obj;
| }
| visit_type_ACPIOSTInfo_members(v, obj, &err);
|- error_propagate(errp, err);
|- err = NULL;
|+ if (err) {
|+ goto out_obj;
|+ }
|+ visit_check_struct(v, &err);
| out_obj:
|- visit_end_struct(v, &err);
|+ visit_end_struct(v);
| out:
and in qapi-event.c:
@@ -47,7 +47,10 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
| visit_type_q_obj_ACPI_DEVICE_OST_arg_members(v, ¶m, &err);
|- visit_end_struct(v, err ? NULL : &err);
|+ if (!err) {
|+ visit_check_struct(v, &err);
|+ }
|+ visit_end_struct(v);
| if (err) {
| goto out;
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1461879932-9020-20-git-send-email-eblake@redhat.com>
[Conflict with a doc fixup resolved]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-04-29 05:45:27 +08:00
|
|
|
goto out_nested;
|
2016-01-29 21:48:45 +08:00
|
|
|
}
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
}
|
qapi: Split visit_end_struct() into pieces
As mentioned in previous patches, we want to call visit_end_struct()
functions unconditionally, so that visitors can release resources
tied up since the matching visit_start_struct() without also having
to worry about error priority if more than one error occurs.
Even though error_propagate() can be safely used to ignore a second
error during cleanup caused by a first error, it is simpler if the
cleanup cannot set an error. So, split out the error checking
portion (basically, input visitors checking for unvisited keys) into
a new function visit_check_struct(), which can be safely skipped if
any earlier errors are encountered, and leave the cleanup portion
(which never fails, but must be called unconditionally if
visit_start_struct() succeeded) in visit_end_struct().
Generated code in qapi-visit.c has diffs resembling:
|@@ -59,10 +59,12 @@ void visit_type_ACPIOSTInfo(Visitor *v,
| goto out_obj;
| }
| visit_type_ACPIOSTInfo_members(v, obj, &err);
|- error_propagate(errp, err);
|- err = NULL;
|+ if (err) {
|+ goto out_obj;
|+ }
|+ visit_check_struct(v, &err);
| out_obj:
|- visit_end_struct(v, &err);
|+ visit_end_struct(v);
| out:
and in qapi-event.c:
@@ -47,7 +47,10 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
| visit_type_q_obj_ACPI_DEVICE_OST_arg_members(v, ¶m, &err);
|- visit_end_struct(v, err ? NULL : &err);
|+ if (!err) {
|+ visit_check_struct(v, &err);
|+ }
|+ visit_end_struct(v);
| if (err) {
| goto out;
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1461879932-9020-20-git-send-email-eblake@redhat.com>
[Conflict with a doc fixup resolved]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-04-29 05:45:27 +08:00
|
|
|
visit_check_struct(v, &err);
|
|
|
|
out_nested:
|
qapi: Add parameter to visit_end_*
Rather than making the dealloc visitor track of stack of pointers
remembered during visit_start_* in order to free them during
visit_end_*, it's a lot easier to just make all callers pass the
same pointer to visit_end_*. The generated code has access to the
same pointer, while all other users are doing virtual walks and
can pass NULL. The dealloc visitor is then greatly simplified.
All three visit_end_*() functions intentionally take a void**,
even though the visit_start_*() functions differ between void**,
GenericList**, and GenericAlternate**. This is done for several
reasons: when doing a virtual walk, passing NULL doesn't care
what the type is, but when doing a generated walk, we already
have to cast the caller's specific FOO* to call visit_start,
while using void** lets us use visit_end without a cast. Also,
an upcoming patch will add a clone visitor that wants to use
the same implementation for all three visit_end callbacks,
which is made easier if all three share the same signature.
For visitors with already track per-object state (the QMP visitors
via a stack, and the string visitors which do not allow nesting),
add an assertion that the caller is indeed passing the same
pointer to paired calls.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-4-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-10 00:48:34 +08:00
|
|
|
visit_end_struct(v, NULL);
|
2014-05-07 15:53:52 +08:00
|
|
|
|
qapi: Split visit_end_struct() into pieces
As mentioned in previous patches, we want to call visit_end_struct()
functions unconditionally, so that visitors can release resources
tied up since the matching visit_start_struct() without also having
to worry about error priority if more than one error occurs.
Even though error_propagate() can be safely used to ignore a second
error during cleanup caused by a first error, it is simpler if the
cleanup cannot set an error. So, split out the error checking
portion (basically, input visitors checking for unvisited keys) into
a new function visit_check_struct(), which can be safely skipped if
any earlier errors are encountered, and leave the cleanup portion
(which never fails, but must be called unconditionally if
visit_start_struct() succeeded) in visit_end_struct().
Generated code in qapi-visit.c has diffs resembling:
|@@ -59,10 +59,12 @@ void visit_type_ACPIOSTInfo(Visitor *v,
| goto out_obj;
| }
| visit_type_ACPIOSTInfo_members(v, obj, &err);
|- error_propagate(errp, err);
|- err = NULL;
|+ if (err) {
|+ goto out_obj;
|+ }
|+ visit_check_struct(v, &err);
| out_obj:
|- visit_end_struct(v, &err);
|+ visit_end_struct(v);
| out:
and in qapi-event.c:
@@ -47,7 +47,10 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
| visit_type_q_obj_ACPI_DEVICE_OST_arg_members(v, ¶m, &err);
|- visit_end_struct(v, err ? NULL : &err);
|+ if (!err) {
|+ visit_check_struct(v, &err);
|+ }
|+ visit_end_struct(v);
| if (err) {
| goto out;
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1461879932-9020-20-git-send-email-eblake@redhat.com>
[Conflict with a doc fixup resolved]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-04-29 05:45:27 +08:00
|
|
|
if (!err) {
|
|
|
|
visit_check_struct(v, &err);
|
|
|
|
}
|
2014-05-07 15:53:52 +08:00
|
|
|
out_end:
|
qapi: Add parameter to visit_end_*
Rather than making the dealloc visitor track of stack of pointers
remembered during visit_start_* in order to free them during
visit_end_*, it's a lot easier to just make all callers pass the
same pointer to visit_end_*. The generated code has access to the
same pointer, while all other users are doing virtual walks and
can pass NULL. The dealloc visitor is then greatly simplified.
All three visit_end_*() functions intentionally take a void**,
even though the visit_start_*() functions differ between void**,
GenericList**, and GenericAlternate**. This is done for several
reasons: when doing a virtual walk, passing NULL doesn't care
what the type is, but when doing a generated walk, we already
have to cast the caller's specific FOO* to call visit_start,
while using void** lets us use visit_end without a cast. Also,
an upcoming patch will add a clone visitor that wants to use
the same implementation for all three visit_end callbacks,
which is made easier if all three share the same signature.
For visitors with already track per-object state (the QMP visitors
via a stack, and the string visitors which do not allow nesting),
add an assertion that the caller is indeed passing the same
pointer to paired calls.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-4-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-10 00:48:34 +08:00
|
|
|
visit_end_struct(v, NULL);
|
2014-05-07 15:53:52 +08:00
|
|
|
out:
|
|
|
|
error_propagate(errp, err);
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
}
|
|
|
|
|
2016-01-29 21:48:53 +08:00
|
|
|
static void balloon_stats_get_poll_interval(Object *obj, Visitor *v,
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 21:48:55 +08:00
|
|
|
const char *name, void *opaque,
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
VirtIOBalloon *s = opaque;
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 21:48:54 +08:00
|
|
|
visit_type_int(v, name, &s->stats_poll_interval, errp);
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
}
|
|
|
|
|
2016-01-29 21:48:53 +08:00
|
|
|
static void balloon_stats_set_poll_interval(Object *obj, Visitor *v,
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 21:48:55 +08:00
|
|
|
const char *name, void *opaque,
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
VirtIOBalloon *s = opaque;
|
2014-04-25 18:44:22 +08:00
|
|
|
Error *local_err = NULL;
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
int64_t value;
|
|
|
|
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 21:48:54 +08:00
|
|
|
visit_type_int(v, name, &value, &local_err);
|
2014-04-25 18:44:22 +08:00
|
|
|
if (local_err) {
|
|
|
|
error_propagate(errp, local_err);
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value < 0) {
|
|
|
|
error_setg(errp, "timer value must be greater than zero");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-02 00:43:44 +08:00
|
|
|
if (value > UINT32_MAX) {
|
2014-09-16 00:00:11 +08:00
|
|
|
error_setg(errp, "timer value is too big");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
if (value == s->stats_poll_interval) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value == 0) {
|
|
|
|
/* timer=0 disables the timer */
|
|
|
|
balloon_stats_destroy_timer(s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (balloon_stats_enabled(s)) {
|
|
|
|
/* timer interval change */
|
|
|
|
s->stats_poll_interval = value;
|
|
|
|
balloon_stats_change_timer(s, value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create a new timer */
|
|
|
|
g_assert(s->stats_timer == NULL);
|
2013-08-21 23:03:08 +08:00
|
|
|
s->stats_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, balloon_stats_poll_cb, s);
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
s->stats_poll_interval = value;
|
|
|
|
balloon_stats_change_timer(s, 0);
|
|
|
|
}
|
|
|
|
|
2008-12-05 04:33:06 +08:00
|
|
|
static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
|
|
|
{
|
2013-03-27 17:49:14 +08:00
|
|
|
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
|
2016-02-04 22:26:51 +08:00
|
|
|
VirtQueueElement *elem;
|
2011-12-19 19:18:13 +08:00
|
|
|
MemoryRegionSection section;
|
2008-12-05 04:33:06 +08:00
|
|
|
|
2016-02-04 22:26:51 +08:00
|
|
|
for (;;) {
|
2008-12-05 04:33:06 +08:00
|
|
|
size_t offset = 0;
|
|
|
|
uint32_t pfn;
|
2016-02-04 22:26:51 +08:00
|
|
|
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
|
|
|
if (!elem) {
|
|
|
|
return;
|
|
|
|
}
|
2008-12-05 04:33:06 +08:00
|
|
|
|
2016-02-04 22:26:51 +08:00
|
|
|
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) {
|
2009-10-02 05:12:16 +08:00
|
|
|
ram_addr_t pa;
|
|
|
|
ram_addr_t addr;
|
2014-06-25 01:43:22 +08:00
|
|
|
int p = virtio_ldl_p(vdev, &pfn);
|
2008-12-05 04:33:06 +08:00
|
|
|
|
2014-06-25 01:43:22 +08:00
|
|
|
pa = (ram_addr_t) p << VIRTIO_BALLOON_PFN_SHIFT;
|
2008-12-05 04:33:06 +08:00
|
|
|
offset += 4;
|
|
|
|
|
2011-12-19 19:18:13 +08:00
|
|
|
/* FIXME: remove get_system_memory(), but how? */
|
|
|
|
section = memory_region_find(get_system_memory(), pa, 1);
|
2016-12-16 19:41:55 +08:00
|
|
|
if (!int128_nz(section.size) ||
|
|
|
|
!memory_region_is_ram(section.mr) ||
|
|
|
|
memory_region_is_rom(section.mr) ||
|
|
|
|
memory_region_is_romd(section.mr)) {
|
|
|
|
trace_virtio_balloon_bad_addr(pa);
|
2018-01-25 15:12:43 +08:00
|
|
|
memory_region_unref(section.mr);
|
2008-12-05 04:33:06 +08:00
|
|
|
continue;
|
2016-12-16 19:41:55 +08:00
|
|
|
}
|
2008-12-05 04:33:06 +08:00
|
|
|
|
2014-11-17 13:11:10 +08:00
|
|
|
trace_virtio_balloon_handle_output(memory_region_name(section.mr),
|
|
|
|
pa);
|
2011-12-19 19:18:13 +08:00
|
|
|
/* Using memory_region_get_ram_ptr is bending the rules a bit, but
|
2009-04-10 22:29:45 +08:00
|
|
|
should be OK because we only want a single page. */
|
2011-12-19 19:18:13 +08:00
|
|
|
addr = section.offset_within_region;
|
|
|
|
balloon_page(memory_region_get_ram_ptr(section.mr) + addr,
|
|
|
|
!!(vq == s->dvq));
|
2013-05-06 16:46:11 +08:00
|
|
|
memory_region_unref(section.mr);
|
2008-12-05 04:33:06 +08:00
|
|
|
}
|
|
|
|
|
2016-02-04 22:26:51 +08:00
|
|
|
virtqueue_push(vq, elem, offset);
|
2008-12-05 04:33:06 +08:00
|
|
|
virtio_notify(vdev, vq);
|
2016-02-04 22:26:51 +08:00
|
|
|
g_free(elem);
|
2008-12-05 04:33:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-27 04:17:35 +08:00
|
|
|
static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
|
|
|
|
{
|
2013-03-27 17:49:14 +08:00
|
|
|
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
|
2016-02-04 22:26:51 +08:00
|
|
|
VirtQueueElement *elem;
|
2010-01-27 04:17:35 +08:00
|
|
|
VirtIOBalloonStat stat;
|
|
|
|
size_t offset = 0;
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
qemu_timeval tv;
|
2010-01-27 04:17:35 +08:00
|
|
|
|
2016-03-01 19:14:03 +08:00
|
|
|
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
2016-02-04 22:26:51 +08:00
|
|
|
if (!elem) {
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
goto out;
|
2010-01-27 04:17:35 +08:00
|
|
|
}
|
|
|
|
|
2016-03-01 19:14:03 +08:00
|
|
|
if (s->stats_vq_elem != NULL) {
|
|
|
|
/* This should never happen if the driver follows the spec. */
|
|
|
|
virtqueue_push(vq, s->stats_vq_elem, 0);
|
|
|
|
virtio_notify(vdev, vq);
|
|
|
|
g_free(s->stats_vq_elem);
|
|
|
|
}
|
|
|
|
|
|
|
|
s->stats_vq_elem = elem;
|
|
|
|
|
2010-01-27 04:17:35 +08:00
|
|
|
/* Initialize the stats to get rid of any stale values. This is only
|
|
|
|
* needed to handle the case where a guest supports fewer stats than it
|
|
|
|
* used to (ie. it has booted into an old kernel).
|
|
|
|
*/
|
|
|
|
reset_stats(s);
|
|
|
|
|
change iov_* function prototypes to be more appropriate
Reorder arguments to be more natural, readable and
consistent with other iov_* functions, and change
argument names, from:
iov_from_buf(iov, iov_cnt, buf, iov_off, size)
to
iov_from_buf(iov, iov_cnt, offset, buf, bytes)
The result becomes natural English:
copy data to this `iov' vector with `iov_cnt'
elements starting at byte offset `offset'
from memory buffer `buf', processing `bytes'
bytes max.
(Try to read the original prototype this way).
Also change iov_clear() to more general iov_memset()
(it uses memset() internally anyway).
While at it, add comments to the header file
describing what the routines actually does.
The patch only renames argumens in the header, but
keeps old names in the implementation. The next
patch will touch actual code to match.
Now, it might look wrong to pay so much attention
to so small things. But we've so many badly designed
interfaces already so the whole thing becomes rather
confusing or error prone. One example of this is
previous commit and small discussion which emerged
from it, with an outcome that the utility functions
like these aren't well-understdandable, leading to
strange usage cases. That's why I paid quite some
attention to this set of functions and a few
others in subsequent patches.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-11 22:05:12 +08:00
|
|
|
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &stat, sizeof(stat))
|
2010-04-27 20:34:06 +08:00
|
|
|
== sizeof(stat)) {
|
2014-06-25 01:43:22 +08:00
|
|
|
uint16_t tag = virtio_tswap16(vdev, stat.tag);
|
|
|
|
uint64_t val = virtio_tswap64(vdev, stat.val);
|
2010-01-27 04:17:35 +08:00
|
|
|
|
|
|
|
offset += sizeof(stat);
|
|
|
|
if (tag < VIRTIO_BALLOON_S_NR)
|
|
|
|
s->stats[tag] = val;
|
|
|
|
}
|
|
|
|
s->stats_vq_offset = offset;
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
|
|
|
|
if (qemu_gettimeofday(&tv) < 0) {
|
2017-09-12 03:52:50 +08:00
|
|
|
warn_report("%s: failed to get time of day", __func__);
|
balloon: re-enable balloon stats
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query available stats.
Polling is enabled by setting an update interval (in seconds)
to a property named guest-stats-polling-interval, like this:
{ "execute": "qom-set",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats-polling-interval", "value": 4 } }
Then the available stats can be retrieved by querying the
guest-stats property. The returned object is a dict containing
all available stats. Example:
{ "execute": "qom-get",
"arguments": { "path": "/machine/peripheral-anon/device[1]",
"property": "guest-stats" } }
{
"return": {
"stats": {
"stat-swap-out": 0,
"stat-free-memory": 844943360,
"stat-minor-faults": 219028,
"stat-major-faults": 235,
"stat-total-memory": 1044406272,
"stat-swap-in": 0
},
"last-update": 1358529861
}
}
Please, check the next commit for full documentation.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2012-12-01 10:14:57 +08:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
s->stats_last_update = tv.tv_sec;
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (balloon_stats_enabled(s)) {
|
|
|
|
balloon_stats_change_timer(s, s->stats_poll_interval);
|
|
|
|
}
|
2010-01-27 04:17:35 +08:00
|
|
|
}
|
|
|
|
|
2008-12-05 04:33:06 +08:00
|
|
|
static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
|
|
|
|
{
|
2013-03-27 17:49:14 +08:00
|
|
|
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
|
2008-12-05 04:33:06 +08:00
|
|
|
struct virtio_balloon_config config;
|
|
|
|
|
|
|
|
config.num_pages = cpu_to_le32(dev->num_pages);
|
|
|
|
config.actual = cpu_to_le32(dev->actual);
|
|
|
|
|
2014-11-17 13:11:10 +08:00
|
|
|
trace_virtio_balloon_get_config(config.num_pages, config.actual);
|
2014-01-09 22:58:16 +08:00
|
|
|
memcpy(config_data, &config, sizeof(struct virtio_balloon_config));
|
2008-12-05 04:33:06 +08:00
|
|
|
}
|
|
|
|
|
2016-02-10 16:49:26 +08:00
|
|
|
static int build_dimm_list(Object *obj, void *opaque)
|
|
|
|
{
|
|
|
|
GSList **list = opaque;
|
|
|
|
|
|
|
|
if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
|
|
|
|
DeviceState *dev = DEVICE(obj);
|
|
|
|
if (dev->realized) { /* only realized DIMMs matter */
|
|
|
|
*list = g_slist_prepend(*list, dev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object_child_foreach(obj, build_dimm_list, opaque);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-10 16:49:22 +08:00
|
|
|
static ram_addr_t get_current_ram_size(void)
|
|
|
|
{
|
2016-02-10 16:49:25 +08:00
|
|
|
GSList *list = NULL, *item;
|
2016-02-10 16:49:22 +08:00
|
|
|
ram_addr_t size = ram_size;
|
|
|
|
|
2016-02-10 16:49:26 +08:00
|
|
|
build_dimm_list(qdev_get_machine(), &list);
|
2016-02-10 16:49:25 +08:00
|
|
|
for (item = list; item; item = g_slist_next(item)) {
|
|
|
|
Object *obj = OBJECT(item->data);
|
2016-02-10 16:49:26 +08:00
|
|
|
if (!strcmp(object_get_typename(obj), TYPE_PC_DIMM)) {
|
|
|
|
size += object_property_get_int(obj, PC_DIMM_SIZE_PROP,
|
|
|
|
&error_abort);
|
|
|
|
}
|
2016-02-10 16:49:22 +08:00
|
|
|
}
|
2016-02-10 16:49:25 +08:00
|
|
|
g_slist_free(list);
|
2016-02-10 16:49:22 +08:00
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2008-12-05 04:33:06 +08:00
|
|
|
static void virtio_balloon_set_config(VirtIODevice *vdev,
|
|
|
|
const uint8_t *config_data)
|
|
|
|
{
|
2013-03-27 17:49:14 +08:00
|
|
|
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
|
2008-12-05 04:33:06 +08:00
|
|
|
struct virtio_balloon_config config;
|
2012-06-15 01:12:56 +08:00
|
|
|
uint32_t oldactual = dev->actual;
|
2014-11-17 13:11:09 +08:00
|
|
|
ram_addr_t vm_ram_size = get_current_ram_size();
|
|
|
|
|
2014-01-09 22:58:16 +08:00
|
|
|
memcpy(&config, config_data, sizeof(struct virtio_balloon_config));
|
virtio-balloon: fixed endianness bug in the config space
The specification for the virtio balloon device requres that the values
in the config space be encoded little-endian. This differs from most
virtio things, where guest-native endian is the norm.
Currently, the qemu virtio-balloon code correctly makes the conversion
on get_config(), but doesn't on set_config for the 'actual' field. The
kernel driver, on the other hand, correctly converts when setting the
actual field, but does not convert when reading the config space. The
upshot is that virtio-balloon will only work correctly if both host and
guest are LE, making all the conversions nops.
This patch corrects the qemu side, correctly doing host-native <-> LE
conversions when accessing the config space. This won't break any setups
that aren't already broken, and fixes the case of BE host, LE guest.
Fixing the BE guest case will require kernel fixes as well.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
2011-04-07 11:02:04 +08:00
|
|
|
dev->actual = le32_to_cpu(config.actual);
|
2012-06-15 01:12:56 +08:00
|
|
|
if (dev->actual != oldactual) {
|
2014-11-17 13:11:09 +08:00
|
|
|
qapi_event_send_balloon_change(vm_ram_size -
|
2014-06-18 14:43:51 +08:00
|
|
|
((ram_addr_t) dev->actual << VIRTIO_BALLOON_PFN_SHIFT),
|
|
|
|
&error_abort);
|
2012-06-15 01:12:56 +08:00
|
|
|
}
|
2014-11-17 13:11:10 +08:00
|
|
|
trace_virtio_balloon_set_config(dev->actual, oldactual);
|
2008-12-05 04:33:06 +08:00
|
|
|
}
|
|
|
|
|
2015-07-27 17:49:19 +08:00
|
|
|
static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f,
|
|
|
|
Error **errp)
|
2008-12-05 04:33:06 +08:00
|
|
|
{
|
2015-06-15 18:52:52 +08:00
|
|
|
VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
|
|
|
|
f |= dev->host_features;
|
2015-06-04 18:34:32 +08:00
|
|
|
virtio_add_feature(&f, VIRTIO_BALLOON_F_STATS_VQ);
|
2010-01-10 19:52:53 +08:00
|
|
|
return f;
|
2008-12-05 04:33:06 +08:00
|
|
|
}
|
|
|
|
|
2011-10-21 21:41:37 +08:00
|
|
|
static void virtio_balloon_stat(void *opaque, BalloonInfo *info)
|
2011-07-20 15:49:07 +08:00
|
|
|
{
|
|
|
|
VirtIOBalloon *dev = opaque;
|
2014-11-17 13:11:09 +08:00
|
|
|
info->actual = get_current_ram_size() - ((uint64_t) dev->actual <<
|
|
|
|
VIRTIO_BALLOON_PFN_SHIFT);
|
2011-07-20 15:49:07 +08:00
|
|
|
}
|
|
|
|
|
balloon: Separate out stat and balloon handling
Passing on '0' as ballooning target to indicate retrieval of stats is
bad API. It also makes 'balloon 0' in the monitor cause a segfault.
Have two different functions handle the different functionality instead.
Detailed explanation from Markus's review:
1. do_info_balloon() is an info_async() method. It receives a callback
with argument, to be called exactly once (callback frees the
argument). It passes the callback via qemu_balloon_status() and
indirectly through qemu_balloon_event to virtio_balloon_to_target().
virtio_balloon_to_target() executes its balloon stats half. It
stores the callback in the device state.
If it can't send a stats request, it resets stats and calls the
callback right away.
Else, it sends a stats request. The device model runs the callback
when it receives the answer.
Works.
2. do_balloon() is a cmd_async() method. It receives a callback with
argument, to be called when the command completes. do_balloon()
calls it right before it succeeds. Odd, but should work.
Nevertheless, it passes the callback on via qemu_ballon() and
indirectly through qemu_balloon_event to virtio_balloon_to_target().
a. If the argument is non-zero, virtio_balloon_to_target() executes
its balloon half, which doesn't use the callback in any way.
Odd, but works.
b. If the argument is zero, virtio_balloon_to_target() executes its
balloon stats half, just like in 1. It either calls the callback
right away, or arranges for it to be called later.
Thus, the callback runs twice: use after free and double free.
Test case: start with -S -device virtio-balloon, execute "balloon 0" in
human monitor. Runs the callback first from virtio_balloon_to_target(),
then again from do_balloon().
Reported-by: Mike Cao <bcao@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
2011-07-20 16:00:56 +08:00
|
|
|
static void virtio_balloon_to_target(void *opaque, ram_addr_t target)
|
2008-12-05 04:33:06 +08:00
|
|
|
{
|
2013-03-27 17:49:14 +08:00
|
|
|
VirtIOBalloon *dev = VIRTIO_BALLOON(opaque);
|
|
|
|
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
2014-11-17 13:11:09 +08:00
|
|
|
ram_addr_t vm_ram_size = get_current_ram_size();
|
2008-12-05 04:33:06 +08:00
|
|
|
|
2014-11-17 13:11:09 +08:00
|
|
|
if (target > vm_ram_size) {
|
|
|
|
target = vm_ram_size;
|
2011-07-20 15:49:07 +08:00
|
|
|
}
|
2008-12-05 04:33:06 +08:00
|
|
|
if (target) {
|
2014-11-17 13:11:09 +08:00
|
|
|
dev->num_pages = (vm_ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
|
2013-03-27 17:49:14 +08:00
|
|
|
virtio_notify_config(vdev);
|
2008-12-05 04:33:06 +08:00
|
|
|
}
|
2014-11-17 13:11:10 +08:00
|
|
|
trace_virtio_balloon_to_target(target, dev->num_pages);
|
2008-12-05 04:33:06 +08:00
|
|
|
}
|
|
|
|
|
2016-10-28 01:36:37 +08:00
|
|
|
static int virtio_balloon_post_load_device(void *opaque, int version_id)
|
2014-06-25 01:20:08 +08:00
|
|
|
{
|
2016-10-28 01:36:37 +08:00
|
|
|
VirtIOBalloon *s = VIRTIO_BALLOON(opaque);
|
2016-03-29 22:00:49 +08:00
|
|
|
|
|
|
|
if (balloon_stats_enabled(s)) {
|
|
|
|
balloon_stats_change_timer(s, s->stats_poll_interval);
|
|
|
|
}
|
2008-12-05 04:33:06 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-10-28 01:36:37 +08:00
|
|
|
static const VMStateDescription vmstate_virtio_balloon_device = {
|
|
|
|
.name = "virtio-balloon-device",
|
|
|
|
.version_id = 1,
|
|
|
|
.minimum_version_id = 1,
|
|
|
|
.post_load = virtio_balloon_post_load_device,
|
|
|
|
.fields = (VMStateField[]) {
|
|
|
|
VMSTATE_UINT32(num_pages, VirtIOBalloon),
|
|
|
|
VMSTATE_UINT32(actual, VirtIOBalloon),
|
|
|
|
VMSTATE_END_OF_LIST()
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2013-07-30 08:51:37 +08:00
|
|
|
static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
|
2008-12-05 04:33:06 +08:00
|
|
|
{
|
2013-07-30 08:51:37 +08:00
|
|
|
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
2013-07-30 11:33:58 +08:00
|
|
|
VirtIOBalloon *s = VIRTIO_BALLOON(dev);
|
2011-07-27 14:59:33 +08:00
|
|
|
int ret;
|
2008-12-05 04:33:06 +08:00
|
|
|
|
2014-01-09 22:58:16 +08:00
|
|
|
virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON,
|
|
|
|
sizeof(struct virtio_balloon_config));
|
2008-12-05 04:33:06 +08:00
|
|
|
|
2011-07-27 14:59:33 +08:00
|
|
|
ret = qemu_add_balloon_handler(virtio_balloon_to_target,
|
|
|
|
virtio_balloon_stat, s);
|
2013-03-27 17:49:13 +08:00
|
|
|
|
2013-03-27 17:49:10 +08:00
|
|
|
if (ret < 0) {
|
balloon: improve error msg when adding second device
A VM supports only one balloon device, but due to several changes
in infrastructure the error message got messed up when trying
to add a second device. Fix it.
Before this fix
Command-line:
qemu-qmp: -device virtio-balloon-pci,id=balloon0: Another balloon device already registered
qemu-qmp: -device virtio-balloon-pci,id=balloon0: Adding balloon handler failed
qemu-qmp: -device virtio-balloon-pci,id=balloon0: Device 'virtio-balloon-pci' could not be initialized
HMP:
Another balloon device already registered
Adding balloon handler failed
Device 'virtio-balloon-pci' could not be initialized
QMP:
{ "execute": "device_add", "arguments": { "driver": "virtio-balloon-pci", "id": "balloon0" } }
{
"error": {
"class": "GenericError",
"desc": "Adding balloon handler failed"
}
}
After this fix
Command-line:
qemu-qmp: -device virtio-balloon-pci,id=balloon0: Only one balloon device is supported
qemu-qmp: -device virtio-balloon-pci,id=balloon0: Device 'virtio-balloon-pci' could not be initialized
HMP:
(qemu) device_add virtio-balloon-pci,id=balloon0
Only one balloon device is supported
Device 'virtio-balloon-pci' could not be initialized
(qemu)
QMP:
{ "execute": "device_add",
"arguments": { "driver": "virtio-balloon-pci", "id": "balloon0" } }
{
"error": {
"class": "GenericError",
"desc": "Only one balloon device is supported"
}
}
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-04-01 01:00:26 +08:00
|
|
|
error_setg(errp, "Only one balloon device is supported");
|
2013-07-30 11:33:58 +08:00
|
|
|
virtio_cleanup(vdev);
|
2013-07-30 08:51:37 +08:00
|
|
|
return;
|
2013-03-27 17:49:10 +08:00
|
|
|
}
|
2011-07-27 14:59:33 +08:00
|
|
|
|
2013-03-27 17:49:13 +08:00
|
|
|
s->ivq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
|
|
|
|
s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
|
|
|
|
s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
|
2008-12-05 04:33:06 +08:00
|
|
|
|
2014-05-21 17:03:47 +08:00
|
|
|
reset_stats(s);
|
2013-03-27 17:49:10 +08:00
|
|
|
}
|
|
|
|
|
2013-07-30 09:50:44 +08:00
|
|
|
static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp)
|
2013-03-27 17:49:10 +08:00
|
|
|
{
|
2013-07-30 09:50:44 +08:00
|
|
|
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
|
|
|
VirtIOBalloon *s = VIRTIO_BALLOON(dev);
|
2013-03-27 17:49:10 +08:00
|
|
|
|
|
|
|
balloon_stats_destroy_timer(s);
|
|
|
|
qemu_remove_balloon_handler(s);
|
2013-04-24 16:21:22 +08:00
|
|
|
virtio_cleanup(vdev);
|
2013-03-27 17:49:10 +08:00
|
|
|
}
|
|
|
|
|
2016-03-01 19:14:03 +08:00
|
|
|
static void virtio_balloon_device_reset(VirtIODevice *vdev)
|
|
|
|
{
|
|
|
|
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
|
|
|
|
|
|
|
|
if (s->stats_vq_elem != NULL) {
|
2016-11-03 16:55:49 +08:00
|
|
|
virtqueue_unpop(s->svq, s->stats_vq_elem, 0);
|
2016-03-01 19:14:03 +08:00
|
|
|
g_free(s->stats_vq_elem);
|
|
|
|
s->stats_vq_elem = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-07 23:20:49 +08:00
|
|
|
static void virtio_balloon_set_status(VirtIODevice *vdev, uint8_t status)
|
|
|
|
{
|
|
|
|
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
|
|
|
|
|
|
|
|
if (!s->stats_vq_elem && vdev->vm_running &&
|
|
|
|
(status & VIRTIO_CONFIG_S_DRIVER_OK) && virtqueue_rewind(s->svq, 1)) {
|
|
|
|
/* poll stats queue for the element we have discarded when the VM
|
|
|
|
* was stopped */
|
|
|
|
virtio_balloon_receive_stats(vdev, s->svq);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-11 17:34:05 +08:00
|
|
|
static void virtio_balloon_instance_init(Object *obj)
|
|
|
|
{
|
|
|
|
VirtIOBalloon *s = VIRTIO_BALLOON(obj);
|
|
|
|
|
|
|
|
object_property_add(obj, "guest-stats", "guest statistics",
|
|
|
|
balloon_stats_get_all, NULL, NULL, s, NULL);
|
|
|
|
|
|
|
|
object_property_add(obj, "guest-stats-polling-interval", "int",
|
|
|
|
balloon_stats_get_poll_interval,
|
|
|
|
balloon_stats_set_poll_interval,
|
|
|
|
NULL, s, NULL);
|
|
|
|
}
|
|
|
|
|
2016-10-06 20:55:47 +08:00
|
|
|
static const VMStateDescription vmstate_virtio_balloon = {
|
|
|
|
.name = "virtio-balloon",
|
|
|
|
.minimum_version_id = 1,
|
|
|
|
.version_id = 1,
|
|
|
|
.fields = (VMStateField[]) {
|
|
|
|
VMSTATE_VIRTIO_DEVICE,
|
|
|
|
VMSTATE_END_OF_LIST()
|
|
|
|
},
|
|
|
|
};
|
2016-07-15 01:22:49 +08:00
|
|
|
|
2013-03-27 17:49:10 +08:00
|
|
|
static Property virtio_balloon_properties[] = {
|
2015-06-15 18:52:52 +08:00
|
|
|
DEFINE_PROP_BIT("deflate-on-oom", VirtIOBalloon, host_features,
|
|
|
|
VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false),
|
2013-03-27 17:49:10 +08:00
|
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
|
|
};
|
|
|
|
|
|
|
|
static void virtio_balloon_class_init(ObjectClass *klass, void *data)
|
|
|
|
{
|
|
|
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
|
|
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
|
2013-07-30 08:51:37 +08:00
|
|
|
|
2013-03-27 17:49:10 +08:00
|
|
|
dc->props = virtio_balloon_properties;
|
2016-07-15 01:22:49 +08:00
|
|
|
dc->vmsd = &vmstate_virtio_balloon;
|
2013-07-29 22:17:45 +08:00
|
|
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
2013-07-30 08:51:37 +08:00
|
|
|
vdc->realize = virtio_balloon_device_realize;
|
2013-07-30 09:50:44 +08:00
|
|
|
vdc->unrealize = virtio_balloon_device_unrealize;
|
2016-03-01 19:14:03 +08:00
|
|
|
vdc->reset = virtio_balloon_device_reset;
|
2013-03-27 17:49:10 +08:00
|
|
|
vdc->get_config = virtio_balloon_get_config;
|
|
|
|
vdc->set_config = virtio_balloon_set_config;
|
|
|
|
vdc->get_features = virtio_balloon_get_features;
|
2016-09-07 23:20:49 +08:00
|
|
|
vdc->set_status = virtio_balloon_set_status;
|
2016-10-28 01:36:37 +08:00
|
|
|
vdc->vmsd = &vmstate_virtio_balloon_device;
|
2013-03-27 17:49:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo virtio_balloon_info = {
|
|
|
|
.name = TYPE_VIRTIO_BALLOON,
|
|
|
|
.parent = TYPE_VIRTIO_DEVICE,
|
|
|
|
.instance_size = sizeof(VirtIOBalloon),
|
2015-05-11 17:34:05 +08:00
|
|
|
.instance_init = virtio_balloon_instance_init,
|
2013-03-27 17:49:10 +08:00
|
|
|
.class_init = virtio_balloon_class_init,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void virtio_register_types(void)
|
|
|
|
{
|
|
|
|
type_register_static(&virtio_balloon_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_init(virtio_register_types)
|