static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) { VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev); VirtQueueElement *elem = &s->stats_vq_elem; VirtIOBalloonStat stat; size_t offset = 0; if (!virtqueue_pop(vq, elem)) { return; } /* 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, &stat, offset, sizeof(stat)) == sizeof(stat)) { uint16_t tag = tswap16(stat.tag); uint64_t val = tswap64(stat.val); offset += sizeof(stat); if (tag < VIRTIO_BALLOON_S_NR) s->stats[tag] = val; } s->stats_vq_offset = offset; complete_stats_request(s); }
static void virtio_balloon_stat(void *opaque, MonitorCompletion cb, void *cb_data) { VirtIOBalloon *dev = opaque; /* For now, only allow one request at a time. This restriction can be * removed later by queueing callback and data pairs. */ if (dev->stats_callback != NULL) { return; } dev->stats_callback = cb; dev->stats_opaque_callback_data = cb_data; if (ENABLE_GUEST_STATS && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) { virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset); virtio_notify(&dev->vdev, dev->svq); return; } /* Stats are not supported. Clear out any stale values that might * have been set by a more featureful guest kernel. */ reset_stats(dev); complete_stats_request(dev); }