static void balloon_stats_set_poll_interval(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { VirtIOBalloon *s = opaque; Error *local_err = NULL; int64_t value; visit_type_int(v, name, &value, &local_err); if (local_err) { error_propagate(errp, local_err); return; } if (value < 0) { error_setg(errp, "timer value must be greater than zero"); return; } if (value > UINT32_MAX) { error_setg(errp, "timer value is too big"); return; } 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); s->stats_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, balloon_stats_poll_cb, s); s->stats_poll_interval = value; balloon_stats_change_timer(s, 0); }
static int virtio_balloon_post_load_device(void *opaque, int version_id) { VirtIOBalloon *s = VIRTIO_BALLOON(opaque); if (balloon_stats_enabled(s)) { balloon_stats_change_timer(s, s->stats_poll_interval); } return 0; }
static void balloon_stats_set_poll_interval(Object *obj, struct Visitor *v, void *opaque, const char *name, Error **errp) { VirtIOBalloon *s = opaque; int64_t value; visit_type_int(v, &value, name, errp); if (error_is_set(errp)) { return; } if (value < 0) { error_setg(errp, "timer value must be greater than zero"); return; } 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); s->stats_timer = qemu_new_timer_ms(vm_clock, balloon_stats_poll_cb, s); s->stats_poll_interval = value; balloon_stats_change_timer(s, 0); }
static int virtio_balloon_load_device(VirtIODevice *vdev, QEMUFile *f, int version_id) { VirtIOBalloon *s = VIRTIO_BALLOON(vdev); s->num_pages = qemu_get_be32(f); s->actual = qemu_get_be32(f); if (balloon_stats_enabled(s)) { balloon_stats_change_timer(s, s->stats_poll_interval); } return 0; }
static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) { VirtIOBalloon *s = VIRTIO_BALLOON(vdev); VirtQueueElement *elem; VirtIOBalloonStat stat; size_t offset = 0; qemu_timeval tv; elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); if (!elem) { goto out; } 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; /* 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); while (iov_to_buf(elem->out_sg, elem->out_num, offset, &stat, sizeof(stat)) == sizeof(stat)) { uint16_t tag = virtio_tswap16(vdev, stat.tag); uint64_t val = virtio_tswap64(vdev, stat.val); offset += sizeof(stat); if (tag < VIRTIO_BALLOON_S_NR) s->stats[tag] = val; } s->stats_vq_offset = offset; if (qemu_gettimeofday(&tv) < 0) { fprintf(stderr, "warning: %s: failed to get time of day\n", __func__); goto out; } s->stats_last_update = tv.tv_sec; out: if (balloon_stats_enabled(s)) { balloon_stats_change_timer(s, s->stats_poll_interval); } }
static void balloon_stats_poll_cb(void *opaque) { VirtIOBalloon *s = opaque; VirtIODevice *vdev = VIRTIO_DEVICE(s); if (!balloon_stats_supported(s)) { /* re-schedule */ balloon_stats_change_timer(s, s->stats_poll_interval); return; } virtqueue_push(s->svq, &s->stats_vq_elem, s->stats_vq_offset); virtio_notify(vdev, s->svq); }